// Белорусский телефон: +375, код оператора или Минска, 7 цифр. // Один и тот же код работает в форме и в api, поэтому подсказки совпадают. export const BELARUS_CODES = ['25', '29', '33', '44', '17'] as const; const SUBSCRIBER_LENGTH = 7; type Parsed = | { ok: true; code: string; subscriber: string } | { ok: false; reason: 'empty' | 'country' | 'code' | 'length' }; function parse(input: string): Parsed { const trimmed = input.trim(); if (trimmed === '') return { ok: false, reason: 'empty' }; const hasPlus = trimmed.startsWith('+'); if (/\+/.test(trimmed.slice(1))) return { ok: false, reason: 'country' }; const digits = trimmed.replace(/\D/g, ''); if (digits === '') return { ok: false, reason: 'country' }; // Отрезаем префикс страны или старый внутренний «8 0…» / «0…», остаётся код + номер. let national: string; if (digits.startsWith('375')) national = digits.slice(3); else if (hasPlus) return { ok: false, reason: 'country' }; else if (digits.startsWith('80')) national = digits.slice(2); else if (digits.startsWith('0')) national = digits.slice(1); else national = digits; const code = national.slice(0, 2); const subscriber = national.slice(2); // Без префикса 375: российские «7…» / «8 9xx…» и слишком длинные номера — иностранные. if (!digits.startsWith('375') && (/^(7|8[1-9])/.test(digits) || digits.length > 11)) { return { ok: false, reason: 'country' }; } if (national.length >= 2 && !(BELARUS_CODES as readonly string[]).includes(code)) { return { ok: false, reason: 'code' }; } if (subscriber.length !== SUBSCRIBER_LENGTH) return { ok: false, reason: 'length' }; return { ok: true, code, subscriber }; } export const PHONE_ERRORS = { empty: 'Укажите телефон — по нему перезвоним', country: 'Нужен белорусский номер: +375…', code: 'Проверьте код оператора: 25, 29, 33, 44 или 17', length: 'После кода нужно 7 цифр', } as const; /** Любой формат ввода → `+375XXXXXXXXX` или null. */ export function normalizeBelarusPhone(input: string): string | null { const parsed = parse(input); return parsed.ok ? `+375${parsed.code}${parsed.subscriber}` : null; } export function isValidBelarusPhone(input: string): boolean { return parse(input).ok; } /** Текст подсказки под полем или null, если номер валиден. */ export function phoneError(input: string): string | null { const parsed = parse(input); return parsed.ok ? null : PHONE_ERRORS[parsed.reason]; } /** `+375 29 123-45-67` для показа в поле после blur. */ export function formatBelarusPhone(input: string): string | null { const parsed = parse(input); if (!parsed.ok) return null; const s = parsed.subscriber; return `+375 ${parsed.code} ${s.slice(0, 3)}-${s.slice(3, 5)}-${s.slice(5)}`; }