Files
goodgo-platform/apps/web/lib/phone.ts
Ho Ngoc Hai b4bb05479e feat(web): add lib/phone.ts with formatPhone/normalizePhone/zaloHref helpers
- Create apps/web/lib/phone.ts with VN_PHONE_REGEX, normalizePhone,
  formatPhone, and zaloHref helpers
- Deduplicate phone regex: auth.ts and inquiry.ts now import VN_PHONE_REGEX
  from @/lib/phone instead of defining their own local patterns
- Replace raw .replace(/^0/, '84') in inquiry-detail-dialog.tsx and
  lead-detail-dialog.tsx with zaloHref(); use formatPhone() for display

Resolves GOO-209

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-24 12:01:14 +07:00

60 lines
1.9 KiB
TypeScript

/**
* Vietnamese phone number helpers.
*
* Regex covers the current VN numbering plan:
* 0[35789]x xxxxxxx — Viettel, Mobifone, Vinaphone, Gmobile, Indochina
*
* See: https://en.wikipedia.org/wiki/Telephone_numbers_in_Vietnam
*/
/** Matches a VN mobile number, with optional +84 or leading 0. */
export const VN_PHONE_REGEX =
/^(0|\+84)(3[2-9]|5[2689]|7[06-9]|8[1-9]|9[0-9])\d{7}$/;
/**
* Normalise a VN phone number to the E.164-ish form used by Zalo / APIs:
* strip leading 0 and prepend the country code (84).
*
* "0987654321" → "84987654321"
* "+84987654321" → "84987654321"
* "84987654321" → "84987654321" (already normalised — idempotent)
*/
export function normalizePhone(phone: string): string {
const cleaned = phone.trim();
if (cleaned.startsWith('+84')) return `84${cleaned.slice(3)}`;
if (cleaned.startsWith('84')) return cleaned;
if (cleaned.startsWith('0')) return `84${cleaned.slice(1)}`;
return cleaned;
}
/**
* Format a raw VN phone number for display.
* Handles 10-digit numbers (0xx xxxx xxxx).
*
* "0987654321" → "0987 654 321"
* Passthrough for anything that doesn't match.
*/
export function formatPhone(phone: string): string {
const cleaned = phone.trim().replace(/\s+/g, '');
// 10-digit local format: 0xxx yyy zzz
const tenDigit = cleaned.match(/^(0\d{3})(\d{3})(\d{3})$/);
if (tenDigit) return `${tenDigit[1]} ${tenDigit[2]} ${tenDigit[3]}`;
// +84 prefix → treat as 10-digit local after swapping prefix
const e164 = cleaned.match(/^\+84(\d{9})$/);
if (e164) return formatPhone(`0${e164[1]}`);
return phone;
}
/**
* Returns the https://zalo.me deep-link URL for a given phone number.
*
* Zalo expects the number without a leading zero, prefixed with 84.
* "0987654321" → "https://zalo.me/84987654321"
*/
export function zaloHref(phone: string): string {
return `https://zalo.me/${normalizePhone(phone)}`;
}