import { z } from 'zod'; import { getCountryCallingCode, isValidPhoneNumber, parsePhoneNumberFromString, type CountryCode } from 'libphonenumber-js'; /** * Accepts any international number in E.164 (`+`) or a * bare national number, which is assumed Ethiopian (`0911223344` -> * `+251911223344`) for backward compatibility with existing records. */ export const phoneNumber = z .string() .trim() .transform((v) => parsePhoneNumberFromString(v, 'ET')?.number ?? v) .refine((v) => isValidPhoneNumber(v), { message: 'Enter a valid phone number', }); /** Same rules, but blank is allowed. */ export const optionalPhoneNumber = z.union([z.literal(''), phoneNumber]).optional(); /** * Digits the field should hold after an edit. A keystroke that only removed * a formatting character (backspacing the ')' out of "(415)") leaves the * digits unchanged, which would otherwise make the caret stick — drop a real * digit in that case. */ export function nextNationalDigits(text: string, prevDisplay: string): string { const digits = text.replace(/\D/g, ''); const deleting = text.length < prevDisplay.length; if (deleting && digits === prevDisplay.replace(/\D/g, '')) return digits.slice(0, -1); return digits; } /** National digits of a stored value, for display in the number box. */ export function toNationalDigits(value: string, country: CountryCode): string { if (!value) return ''; const parsed = parsePhoneNumberFromString(value); if (parsed) return parsed.nationalNumber; if (value.startsWith('+')) { const prefix = `+${getCountryCallingCode(country)}`; if (value.startsWith(prefix)) return value.slice(prefix.length).replace(/\D/g, ''); } return value.replace(/\D/g, ''); } /** * E.164 for the digits typed so far. Incomplete numbers don't parse, so they * fall back to a plain dial-code concatenation rather than collapsing to '' * — the value has to survive mid-typing for the field to be usable. */ export function toE164(digits: string, country: CountryCode): string { if (!digits) return ''; return ( parsePhoneNumberFromString(digits, country)?.number ?? `+${getCountryCallingCode(country)}${digits}` ); }