/** * Règles de validation des numéros de téléphone locaux par indicatif pays. * Le numéro local est celui saisi par l'utilisateur SANS le 0 initial et SANS l'indicatif. * Exemples : France 06 12 34 56 78 → local = "612345678" (9 chiffres) * Brésil 11 9 1234-5678 → local = "11912345678" (11 chiffres) */ export type PhoneRule = { /** Longueur minimale du numéro local (chiffres uniquement) */ minLength: number; /** Longueur maximale du numéro local (chiffres uniquement) */ maxLength: number; /** Regex optionnelle pour validation de format */ pattern?: RegExp; /** Exemple de numéro local valide (pour le placeholder) */ example: string; /** Hint affiché sous le champ */ hint: string; }; /** Règles par dialCode (indicatif sans le +) */ export const PHONE_RULES: Record = { // ── France & DOM-TOM ────────────────────────────────────────────────────── "33": { minLength: 9, maxLength: 9, pattern: /^[67]\d{8}$/, example: "612345678", hint: "9 chiffres, commençant par 6 ou 7 (ex : 612 345 678)" }, "590": { minLength: 9, maxLength: 9, example: "690123456", hint: "9 chiffres (Guadeloupe)" }, "596": { minLength: 9, maxLength: 9, example: "696123456", hint: "9 chiffres (Martinique)" }, "262": { minLength: 9, maxLength: 9, example: "692123456", hint: "9 chiffres (Réunion / Mayotte)" }, "594": { minLength: 9, maxLength: 9, example: "694123456", hint: "9 chiffres (Guyane)" }, "687": { minLength: 6, maxLength: 6, example: "123456", hint: "6 chiffres (Nouvelle-Calédonie)" }, "689": { minLength: 8, maxLength: 8, example: "87123456", hint: "8 chiffres (Polynésie française)" }, "508": { minLength: 6, maxLength: 6, example: "551234", hint: "6 chiffres (Saint-Pierre-et-Miquelon)" }, "681": { minLength: 6, maxLength: 6, example: "721234", hint: "6 chiffres (Wallis-et-Futuna)" }, // ── Europe ──────────────────────────────────────────────────────────────── "32": { minLength: 8, maxLength: 9, example: "470123456", hint: "8-9 chiffres (Belgique)" }, "41": { minLength: 9, maxLength: 9, example: "791234567", hint: "9 chiffres (Suisse)" }, "352": { minLength: 6, maxLength: 9, example: "621123456", hint: "6-9 chiffres (Luxembourg)" }, "377": { minLength: 8, maxLength: 8, example: "61234567", hint: "8 chiffres (Monaco)" }, "49": { minLength: 10, maxLength: 11, example: "15123456789", hint: "10-11 chiffres (Allemagne)" }, "34": { minLength: 9, maxLength: 9, example: "612345678", hint: "9 chiffres (Espagne)" }, "39": { minLength: 9, maxLength: 10, example: "3123456789", hint: "9-10 chiffres (Italie)" }, "351": { minLength: 9, maxLength: 9, example: "912345678", hint: "9 chiffres (Portugal)" }, "44": { minLength: 10, maxLength: 10, example: "7911123456", hint: "10 chiffres (Royaume-Uni)" }, "31": { minLength: 9, maxLength: 9, example: "612345678", hint: "9 chiffres (Pays-Bas)" }, "48": { minLength: 9, maxLength: 9, example: "512345678", hint: "9 chiffres (Pologne)" }, "46": { minLength: 7, maxLength: 9, example: "701234567", hint: "7-9 chiffres (Suède)" }, "47": { minLength: 8, maxLength: 8, example: "91234567", hint: "8 chiffres (Norvège)" }, "45": { minLength: 8, maxLength: 8, example: "20123456", hint: "8 chiffres (Danemark)" }, "358": { minLength: 9, maxLength: 10, example: "412345678", hint: "9-10 chiffres (Finlande)" }, "43": { minLength: 10, maxLength: 11, example: "6641234567", hint: "10-11 chiffres (Autriche)" }, "30": { minLength: 10, maxLength: 10, example: "6912345678", hint: "10 chiffres (Grèce)" }, "40": { minLength: 9, maxLength: 9, example: "712345678", hint: "9 chiffres (Roumanie)" }, "36": { minLength: 9, maxLength: 9, example: "201234567", hint: "9 chiffres (Hongrie)" }, "420": { minLength: 9, maxLength: 9, example: "601234567", hint: "9 chiffres (Rép. tchèque)" }, "90": { minLength: 10, maxLength: 10, example: "5321234567", hint: "10 chiffres (Turquie)" }, // ── Afrique ─────────────────────────────────────────────────────────────── "212": { minLength: 9, maxLength: 9, example: "612345678", hint: "9 chiffres (Maroc)" }, "213": { minLength: 9, maxLength: 9, example: "551234567", hint: "9 chiffres (Algérie)" }, "216": { minLength: 8, maxLength: 8, example: "20123456", hint: "8 chiffres (Tunisie)" }, "221": { minLength: 9, maxLength: 9, example: "771234567", hint: "9 chiffres (Sénégal)" }, "225": { minLength: 10, maxLength: 10, example: "0712345678", hint: "10 chiffres (Côte d'Ivoire)" }, "237": { minLength: 9, maxLength: 9, example: "612345678", hint: "9 chiffres (Cameroun)" }, "243": { minLength: 9, maxLength: 9, example: "812345678", hint: "9 chiffres (Congo RDC)" }, "242": { minLength: 9, maxLength: 9, example: "061234567", hint: "9 chiffres (Congo Brazzaville)" }, "261": { minLength: 9, maxLength: 9, example: "321234567", hint: "9 chiffres (Madagascar)" }, "223": { minLength: 8, maxLength: 8, example: "70123456", hint: "8 chiffres (Mali)" }, "226": { minLength: 8, maxLength: 8, example: "70123456", hint: "8 chiffres (Burkina Faso)" }, "227": { minLength: 8, maxLength: 8, example: "90123456", hint: "8 chiffres (Niger)" }, "235": { minLength: 8, maxLength: 8, example: "63123456", hint: "8 chiffres (Tchad)" }, "224": { minLength: 9, maxLength: 9, example: "621234567", hint: "9 chiffres (Guinée)" }, "229": { minLength: 8, maxLength: 8, example: "97123456", hint: "8 chiffres (Bénin)" }, "228": { minLength: 8, maxLength: 8, example: "90123456", hint: "8 chiffres (Togo)" }, "222": { minLength: 8, maxLength: 8, example: "22123456", hint: "8 chiffres (Mauritanie)" }, "241": { minLength: 7, maxLength: 8, example: "6123456", hint: "7-8 chiffres (Gabon)" }, "240": { minLength: 9, maxLength: 9, example: "222123456", hint: "9 chiffres (Guinée équatoriale)" }, "236": { minLength: 8, maxLength: 8, example: "72123456", hint: "8 chiffres (Centrafrique)" }, "269": { minLength: 7, maxLength: 7, example: "3212345", hint: "7 chiffres (Comores)" }, "253": { minLength: 8, maxLength: 8, example: "77123456", hint: "8 chiffres (Djibouti)" }, "230": { minLength: 8, maxLength: 8, example: "52123456", hint: "8 chiffres (Maurice)" }, "248": { minLength: 7, maxLength: 7, example: "2512345", hint: "7 chiffres (Seychelles)" }, "20": { minLength: 10, maxLength: 10, example: "1012345678", hint: "10 chiffres (Égypte)" }, // ── Amériques ───────────────────────────────────────────────────────────── "1": { minLength: 10, maxLength: 10, example: "2125551234", hint: "10 chiffres (US/Canada, sans le 1 initial)" }, "52": { minLength: 10, maxLength: 10, example: "5512345678", hint: "10 chiffres (Mexique)" }, "55": { minLength: 10, maxLength: 11, example: "11912345678", hint: "10-11 chiffres (Brésil, avec DDD)" }, "54": { minLength: 10, maxLength: 11, example: "91123456789", hint: "10-11 chiffres (Argentine)" }, "57": { minLength: 10, maxLength: 10, example: "3001234567", hint: "10 chiffres (Colombie)" }, "56": { minLength: 9, maxLength: 9, example: "912345678", hint: "9 chiffres (Chili)" }, "51": { minLength: 9, maxLength: 9, example: "912345678", hint: "9 chiffres (Pérou)" }, "58": { minLength: 10, maxLength: 10, example: "4121234567", hint: "10 chiffres (Venezuela)" }, "593": { minLength: 9, maxLength: 9, example: "991234567", hint: "9 chiffres (Équateur)" }, "591": { minLength: 8, maxLength: 8, example: "71234567", hint: "8 chiffres (Bolivie)" }, "595": { minLength: 9, maxLength: 9, example: "981234567", hint: "9 chiffres (Paraguay)" }, "598": { minLength: 8, maxLength: 9, example: "91234567", hint: "8-9 chiffres (Uruguay)" }, "509": { minLength: 8, maxLength: 8, example: "36123456", hint: "8 chiffres (Haïti)" }, // ── Asie & Océanie ──────────────────────────────────────────────────────── "91": { minLength: 10, maxLength: 10, example: "9123456789", hint: "10 chiffres (Inde)" }, "86": { minLength: 11, maxLength: 11, example: "13912345678", hint: "11 chiffres (Chine)" }, "81": { minLength: 10, maxLength: 11, example: "9012345678", hint: "10-11 chiffres (Japon)" }, "61": { minLength: 9, maxLength: 9, example: "412345678", hint: "9 chiffres (Australie)" }, "961": { minLength: 7, maxLength: 8, example: "3123456", hint: "7-8 chiffres (Liban)" }, }; /** Règle par défaut si le dialCode n'est pas dans la liste */ export const DEFAULT_RULE: PhoneRule = { minLength: 6, maxLength: 15, example: "123456789", hint: "6-15 chiffres", }; /** * Valide un numéro local (sans indicatif, sans 0 initial). * @returns null si valide, message d'erreur sinon */ export function validateLocalPhone(dialCode: string, localNumber: string): string | null { const digits = localNumber.replace(/\D/g, ""); const rule = PHONE_RULES[dialCode] ?? DEFAULT_RULE; if (digits.length === 0) return "Veuillez saisir votre numéro."; if (digits.length < rule.minLength) { return `Numéro trop court (minimum ${rule.minLength} chiffres). ${rule.hint}`; } if (digits.length > rule.maxLength) { return `Numéro trop long (maximum ${rule.maxLength} chiffres). ${rule.hint}`; } if (rule.pattern && !rule.pattern.test(digits)) { return `Format invalide. ${rule.hint}`; } return null; } /** * Retourne le placeholder adapté au pays sélectionné. */ export function getPhonePlaceholder(dialCode: string): string { const rule = PHONE_RULES[dialCode] ?? DEFAULT_RULE; return rule.example; } /** * Retourne le hint d'aide pour un dialCode. */ export function getPhoneHint(dialCode: string): string { const rule = PHONE_RULES[dialCode] ?? DEFAULT_RULE; return rule.hint; }