/** * WhatsApp message templates with dynamic variable interpolation. * * Variables disponibles : * {{nom}} – Nom du patient * {{ticket}} – Numéro de ticket * {{position}} – Position dans la file * {{attente}} – Temps d'attente estimé (en minutes) * {{cabinet}} – Nom du cabinet */ // ─── Types ─────────────────────────────────────────────────────────────────── export type TemplateType = "joined" | "soon" | "called" | "withdrawn"; export interface TemplateVariable { key: string; // e.g. "{{nom}}" label: string; // e.g. "Nom du patient" description: string; } export interface TemplateContext { nom: string; ticket: number | string; position: number | string; attente: number | string; cabinet: string; } // ─── Available variables ───────────────────────────────────────────────────── export const TEMPLATE_VARIABLES: TemplateVariable[] = [ { key: "{{nom}}", label: "Nom du patient", description: "Prénom ou nom complet du patient" }, { key: "{{ticket}}", label: "N° de ticket", description: "Numéro de ticket attribué" }, { key: "{{position}}", label: "Position", description: "Position actuelle dans la file" }, { key: "{{attente}}", label: "Temps d'attente", description: "Estimation en minutes" }, { key: "{{cabinet}}", label: "Nom du cabinet", description: "Nom du cabinet médical" }, ]; // ─── Default templates (French) ────────────────────────────────────────────── export const DEFAULT_TEMPLATES: Record = { joined: `🏥 *Salle d'attente – {{cabinet}}*\n\n` + `✅ Vous êtes inscrit(e) dans la file d'attente.\n\n` + `🎫 Numéro de ticket : *{{ticket}}*\n` + `📍 Position : *{{position}}*\n` + `⏱️ Attente estimée : *~{{attente}} min*\n\n` + `Vous recevrez un message quand votre tour approche.\n` + `_Ne perdez pas votre position – restez à proximité._`, soon: `🏥 *Salle d'attente – {{cabinet}}*\n\n` + `⚡ *Votre tour approche !*\n\n` + `🎫 Ticket n° *{{ticket}}*\n` + `⏳ Environ *{{attente}} minutes* restantes\n\n` + `Merci de vous rendre en salle d'attente maintenant.`, called: `🏥 *Salle d'attente – {{cabinet}}*\n\n` + `🔔 *C'est votre tour !*\n\n` + `🎫 Ticket n° *{{ticket}}* – Veuillez vous présenter au cabinet.\n\n` + `_Si vous n'êtes pas disponible, vous serez marqué(e) absent(e) après 5 minutes._`, withdrawn: `🏥 *Salle d'attente – {{cabinet}}*\n\n` + `✅ Votre désistement a bien été enregistré.\n\n` + `🎫 Ticket n° *{{ticket}}* annulé.\n\n` + `Merci et à bientôt !`, }; // ─── Template labels ───────────────────────────────────────────────────────── export const TEMPLATE_LABELS: Record = { joined: { title: "Inscription", description: "Envoyé quand le patient rejoint la file d'attente", icon: "✅", }, soon: { title: "Tour approche", description: "Envoyé quand le patient est bientôt appelé (position ≤ 2)", icon: "⚡", }, called: { title: "Appel", description: "Envoyé quand c'est le tour du patient", icon: "🔔", }, withdrawn: { title: "Désistement", description: "Envoyé quand le patient se désiste", icon: "👋", }, }; // ─── Interpolation engine ──────────────────────────────────────────────────── /** * Replace all {{variable}} placeholders in a template string with actual values. */ export function interpolateTemplate(template: string, context: TemplateContext): string { return template .replace(/\{\{nom\}\}/g, String(context.nom)) .replace(/\{\{ticket\}\}/g, String(context.ticket)) .replace(/\{\{position\}\}/g, String(context.position)) .replace(/\{\{attente\}\}/g, String(context.attente)) .replace(/\{\{cabinet\}\}/g, String(context.cabinet)); } /** * Get the effective template for a given type: custom if set, otherwise default. */ export function getEffectiveTemplate( type: TemplateType, customTemplates?: Partial> ): string { const custom = customTemplates?.[type]; if (custom && custom.trim().length > 0) return custom; return DEFAULT_TEMPLATES[type]; } /** * Build a final message by resolving the template and interpolating variables. */ export function buildMessage( type: TemplateType, context: TemplateContext, customTemplates?: Partial> ): string { const template = getEffectiveTemplate(type, customTemplates); return interpolateTemplate(template, context); } // ─── Preview with sample data ──────────────────────────────────────────────── export const SAMPLE_CONTEXT: TemplateContext = { nom: "Marie Dupont", ticket: 42, position: 3, attente: 12, cabinet: "Cabinet Dr Martin", }; /** * Generate a preview of a template with sample data. */ export function previewTemplate(template: string): string { return interpolateTemplate(template, SAMPLE_CONTEXT); }