Files
policy-ui/app/data/mock-support.ts
Jordan Weingarten 67482f6629 WIP jordan
2026-04-16 11:11:44 -05:00

700 lines
42 KiB
TypeScript

// ─── Support Ticket System — Types, Labels, Helpers, Mock Data ───────────────
// ── Channel ──
export type SupportChannel = 'whatsapp' | 'email' | 'phone' | 'walk_in' | 'web_form'
// ── Routing Tier ──
export type RoutingTier = 'tier1_auto' | 'tier2_rule' | 'tier3_open'
// ── Ticket Status ──
export type TicketStatus = 'open' | 'in_progress' | 'pending_customer' | 'resolved'
// ── Priority ──
export type TicketPriority = 'urgent' | 'high' | 'medium' | 'low'
// ── Intent Category (LLM classification) ──
export type IntentCategory =
| 'payment_inquiry'
| 'claim_report'
| 'sales_interest'
| 'doc_request'
| 'policy_question'
| 'complaint'
| 'endorsement'
| 'certificate_request'
| 'general'
// ── Routed Queue ──
export type RoutedQueue = 'collections' | 'claims' | 'sales' | 'renewals' | 'operations' | 'open_pool'
// ── Message Types ──
export type MessageType = 'whatsapp' | 'email' | 'phone_note' | 'internal_note' | 'system'
export type MessageDirection = 'inbound' | 'outbound' | 'internal'
// ── Routing Rule Type ──
export type RoutingRuleType = 'customer_match' | 'lob_specialist' | 'keyword_intent' | 'doc_auto_fulfill'
// ─── Interfaces ──────────────────────────────────────────────────────────────
export interface TicketMessage {
id: string
type: MessageType
direction: MessageDirection
from: string
to: string | null
subject: string | null
body: string
timestamp: string
aiDigest: string | null
deliveryStatus?: 'sent' | 'delivered' | 'read'
}
export interface SupportTicket {
id: string
subject: string
channel: SupportChannel
status: TicketStatus
priority: TicketPriority
intentCategory: IntentCategory
routingTier: RoutingTier
routedQueue: RoutedQueue
customerId: string | null
customerName: string
policyId: string | null
policyNumber: string | null
assignedTo: string | null
createdAt: string
updatedAt: string
daysOpen: number
slaPercent: number
messageCount: number
lastMessagePreview: string
}
export interface SupportTicketDetail extends SupportTicket {
customerEmail: string | null
customerPhone: string | null
linkedPolicies: { id: string; number: string; carrier: string; lob: string; status: string; renewal: string }[]
linkedClaims: { id: string; type: string; status: string }[]
messages: TicketMessage[]
aiSummary: string
aiSuggestedIntent: IntentCategory
aiConfidence: number
routingTrace: { step: string; result: string; timestamp: string }[]
}
export interface RoutingRule {
id: string
tier: RoutingTier
type: RoutingRuleType
name: string
condition: string
targetQueue: RoutedQueue
targetAgent: string | null
enabled: boolean
priority: number
}
// ─── Label Maps ──────────────────────────────────────────────────────────────
export const CHANNEL_LABELS: Record<SupportChannel, string> = {
whatsapp: 'WhatsApp',
email: 'Email',
phone: 'Teléfono',
walk_in: 'Presencial',
web_form: 'Formulario Web',
}
export const CHANNEL_ICONS: Record<SupportChannel, string> = {
whatsapp: 'i-heroicons-chat-bubble-left-ellipsis',
email: 'i-heroicons-envelope',
phone: 'i-heroicons-phone',
walk_in: 'i-heroicons-building-storefront',
web_form: 'i-heroicons-globe-alt',
}
export const STATUS_LABELS: Record<TicketStatus, string> = {
open: 'Abierto',
in_progress: 'En Proceso',
pending_customer: 'Esperando Cliente',
resolved: 'Resuelto',
}
export const PRIORITY_LABELS: Record<TicketPriority, string> = {
urgent: 'Urgente',
high: 'Alta',
medium: 'Media',
low: 'Baja',
}
export const INTENT_LABELS: Record<IntentCategory, string> = {
payment_inquiry: 'Consulta de Pago',
claim_report: 'Reporte de Siniestro',
sales_interest: 'Interés en Seguros',
doc_request: 'Solicitud de Documento',
policy_question: 'Consulta de Póliza',
complaint: 'Queja',
endorsement: 'Endoso',
certificate_request: 'Certificado',
general: 'General',
}
export const TIER_LABELS: Record<RoutingTier, string> = {
tier1_auto: 'Tier 1 — Auto',
tier2_rule: 'Tier 2 — Regla',
tier3_open: 'Tier 3 — Pool',
}
export const QUEUE_LABELS: Record<RoutedQueue, string> = {
collections: 'Cobranza',
claims: 'Siniestros',
sales: 'Ventas',
renewals: 'Renovaciones',
operations: 'Operaciones',
open_pool: 'Pool Abierto',
}
export const MESSAGE_TYPE_LABELS: Record<MessageType, string> = {
whatsapp: 'WhatsApp',
email: 'Email',
phone_note: 'Nota de Llamada',
internal_note: 'Nota Interna',
system: 'Sistema',
}
// ─── Helpers ─────────────────────────────────────────────────────────────────
export function slaColor(percent: number): 'green' | 'amber' | 'red' {
if (percent >= 100) return 'red'
if (percent >= 75) return 'amber'
return 'green'
}
export function channelIcon(ch: SupportChannel): string {
return CHANNEL_ICONS[ch] ?? 'i-heroicons-question-mark-circle'
}
export function tierBadgeClass(tier: RoutingTier): string {
switch (tier) {
case 'tier1_auto': return 'sp-tier-1'
case 'tier2_rule': return 'sp-tier-2'
case 'tier3_open': return 'sp-tier-3'
default: return ''
}
}
export function fmtDate(d: string): string {
return new Date(d).toLocaleDateString('es-PA', { month: 'short', day: 'numeric', year: 'numeric' })
}
export function fmtTime(d: string): string {
return new Date(d).toLocaleTimeString('es-PA', { hour: '2-digit', minute: '2-digit' })
}
export function fmtDateTime(d: string): string {
return `${fmtDate(d)} ${fmtTime(d)}`
}
// ─── Mock Tickets (List) ─────────────────────────────────────────────────────
export const MOCK_SUPPORT_TICKETS: SupportTicket[] = [
{
id: 'SP-001',
subject: 'Consulta sobre pago pendiente de póliza auto',
channel: 'whatsapp',
status: 'resolved',
priority: 'medium',
intentCategory: 'payment_inquiry',
routingTier: 'tier2_rule',
routedQueue: 'collections',
customerId: 'cust-001',
customerName: 'María Elena Pérez Solano',
policyId: 'POL-2024-4412',
policyNumber: 'AUTO-2024-4412',
assignedTo: 'Carlos Villalba',
createdAt: '2026-04-01T09:15:00',
updatedAt: '2026-04-01T14:30:00',
daysOpen: 0,
slaPercent: 45,
messageCount: 6,
lastMessagePreview: 'Perfecto, ya quedó registrado el pago. Gracias María Elena.',
},
{
id: 'SP-002',
subject: 'Reporte de accidente vehicular — Toyota RAV4',
channel: 'email',
status: 'in_progress',
priority: 'high',
intentCategory: 'claim_report',
routingTier: 'tier2_rule',
routedQueue: 'claims',
customerId: 'cust-004',
customerName: 'Luis Andrés Solís Calderón',
policyId: 'POL-2022-2200',
policyNumber: 'AUTO-2022-2200',
assignedTo: 'María Fernanda Ortiz',
createdAt: '2026-04-03T11:22:00',
updatedAt: '2026-04-07T16:45:00',
daysOpen: 5,
slaPercent: 62,
messageCount: 5,
lastMessagePreview: 'Adjunto las fotos del daño al vehículo tomadas esta mañana.',
},
{
id: 'SP-003',
subject: 'Solicitud de certificado de seguro para banco',
channel: 'walk_in',
status: 'resolved',
priority: 'low',
intentCategory: 'certificate_request',
routingTier: 'tier1_auto',
routedQueue: 'operations',
customerId: 'cust-002',
customerName: 'Roberto Jiménez Mora',
policyId: 'POL-2023-3301',
policyNumber: 'AUTO-2023-3301',
assignedTo: 'Ana R.',
createdAt: '2026-04-04T10:00:00',
updatedAt: '2026-04-04T10:35:00',
daysOpen: 0,
slaPercent: 20,
messageCount: 3,
lastMessagePreview: 'Certificado generado y entregado en mano.',
},
{
id: 'SP-004',
subject: 'Cotización seguro auto para BMW X3 2025',
channel: 'whatsapp',
status: 'open',
priority: 'medium',
intentCategory: 'sales_interest',
routingTier: 'tier2_rule',
routedQueue: 'sales',
customerId: null,
customerName: 'Número desconocido (+507 6789-0123)',
policyId: null,
policyNumber: null,
assignedTo: 'María Fernanda Ortiz',
createdAt: '2026-04-07T08:30:00',
updatedAt: '2026-04-07T08:30:00',
daysOpen: 1,
slaPercent: 35,
messageCount: 3,
lastMessagePreview: 'Buenas, cuánto sale un seguro todo riesgo para un BMW X3 2025?',
},
{
id: 'SP-005',
subject: 'Queja por demora en proceso de siniestro CLM-0048',
channel: 'email',
status: 'pending_customer',
priority: 'high',
intentCategory: 'complaint',
routingTier: 'tier3_open',
routedQueue: 'open_pool',
customerId: 'cust-001',
customerName: 'María Elena Pérez Solano',
policyId: 'POL-2024-4412',
policyNumber: 'AUTO-2024-4412',
assignedTo: 'Carlos Villalba',
createdAt: '2026-04-02T15:00:00',
updatedAt: '2026-04-06T09:20:00',
daysOpen: 6,
slaPercent: 88,
messageCount: 7,
lastMessagePreview: 'Estamos pendientes de su respuesta con los documentos adicionales.',
},
{
id: 'SP-006',
subject: 'Consulta plan salud colectivo — Grupo Agrícola del Sur',
channel: 'web_form',
status: 'in_progress',
priority: 'medium',
intentCategory: 'policy_question',
routingTier: 'tier1_auto',
routedQueue: 'operations',
customerId: 'cust-010',
customerName: 'Fernando Arias Blanco',
policyId: null,
policyNumber: null,
assignedTo: 'Ana R.',
createdAt: '2026-04-06T14:10:00',
updatedAt: '2026-04-07T11:00:00',
daysOpen: 2,
slaPercent: 50,
messageCount: 4,
lastMessagePreview: 'Le envío las opciones de cobertura para su grupo.',
},
{
id: 'SP-007',
subject: 'Mensaje ambiguo — "necesito ayuda con mi seguro"',
channel: 'whatsapp',
status: 'open',
priority: 'medium',
intentCategory: 'general',
routingTier: 'tier3_open',
routedQueue: 'open_pool',
customerId: null,
customerName: 'Número desconocido (+507 6234-5678)',
policyId: null,
policyNumber: null,
assignedTo: null,
createdAt: '2026-04-08T07:45:00',
updatedAt: '2026-04-08T07:45:00',
daysOpen: 0,
slaPercent: 15,
messageCount: 1,
lastMessagePreview: 'Hola buenos días, necesito ayuda con mi seguro, me pueden atender?',
},
{
id: 'SP-008',
subject: 'Endoso — agregar conductor a póliza auto',
channel: 'email',
status: 'in_progress',
priority: 'medium',
intentCategory: 'endorsement',
routingTier: 'tier2_rule',
routedQueue: 'operations',
customerId: 'cust-004',
customerName: 'Luis Andrés Solís Calderón',
policyId: 'POL-2022-2201',
policyNumber: 'AUTO-2022-2201',
assignedTo: 'Ana R.',
createdAt: '2026-04-05T09:00:00',
updatedAt: '2026-04-07T15:30:00',
daysOpen: 3,
slaPercent: 55,
messageCount: 5,
lastMessagePreview: 'Necesitamos la cédula y licencia del conductor adicional.',
},
{
id: 'SP-009',
subject: 'URGENTE — Choque frontal Toyota Hilux, requiere grúa',
channel: 'whatsapp',
status: 'open',
priority: 'urgent',
intentCategory: 'claim_report',
routingTier: 'tier1_auto',
routedQueue: 'claims',
customerId: 'cust-010',
customerName: 'Fernando Arias Blanco',
policyId: 'POL-2020-1100',
policyNumber: 'AUTO-2020-1100',
assignedTo: 'Carlos Villalba',
createdAt: '2026-04-08T06:15:00',
updatedAt: '2026-04-08T06:45:00',
daysOpen: 0,
slaPercent: 40,
messageCount: 4,
lastMessagePreview: 'Ya coordiné la grúa, llega en 20 minutos a tu ubicación.',
},
{
id: 'SP-010',
subject: 'Seguimiento renovación póliza vida — vence 30 abril',
channel: 'phone',
status: 'resolved',
priority: 'low',
intentCategory: 'policy_question',
routingTier: 'tier2_rule',
routedQueue: 'renewals',
customerId: 'cust-002',
customerName: 'Roberto Jiménez Mora',
policyId: 'POL-2023-3301',
policyNumber: 'AUTO-2023-3301',
assignedTo: 'María Fernanda Ortiz',
createdAt: '2026-04-03T16:00:00',
updatedAt: '2026-04-04T09:00:00',
daysOpen: 0,
slaPercent: 30,
messageCount: 3,
lastMessagePreview: 'Cliente confirmó renovación. Proceso completado.',
},
]
// ─── Mock Ticket Details ─────────────────────────────────────────────────────
const sp001Detail: SupportTicketDetail = {
...MOCK_SUPPORT_TICKETS[0],
customerEmail: 'maria.perez@gmail.com',
customerPhone: '+507 6123-4567',
linkedPolicies: [
{ id: 'POL-2024-4412', number: 'AUTO-2024-4412', carrier: 'ASSA', lob: 'Auto', status: 'Active', renewal: '2027-03-15' },
],
linkedClaims: [],
messages: [
{ id: 'msg-001-1', type: 'whatsapp', direction: 'inbound', from: 'María Elena Pérez', to: null, subject: null, body: 'Hola buenas, tengo una consulta sobre mi pago. Me llegó un recibo pero ya hice la transferencia la semana pasada. Pueden verificar?', timestamp: '2026-04-01T09:15:00', aiDigest: 'Customer inquiring about payment status — claims transfer was already made.' },
{ id: 'msg-001-2', type: 'system', direction: 'internal', from: 'Sistema', to: null, subject: null, body: 'Ticket creado automáticamente. Intent detectado: Consulta de Pago (92% confianza). Enrutado a Cobranza.', timestamp: '2026-04-01T09:15:05', aiDigest: null },
{ id: 'msg-001-3', type: 'whatsapp', direction: 'outbound', from: 'Carlos Villalba', to: 'María Elena Pérez', subject: null, body: 'Buenos días María Elena! Déjame verificar con el departamento de cobranza. ¿Me puede compartir el comprobante de la transferencia?', timestamp: '2026-04-01T09:45:00', aiDigest: null, deliveryStatus: 'read' },
{ id: 'msg-001-4', type: 'whatsapp', direction: 'inbound', from: 'María Elena Pérez', to: null, subject: null, body: 'Claro, aquí está el comprobante. Fue el 25 de marzo por $460.', timestamp: '2026-04-01T10:02:00', aiDigest: null },
{ id: 'msg-001-5', type: 'internal_note', direction: 'internal', from: 'Carlos Villalba', to: null, subject: null, body: 'Verificado con contabilidad. Pago recibido el 26/03 — recibo cruzado con período anterior. Se ajusta en sistema.', timestamp: '2026-04-01T13:00:00', aiDigest: null },
{ id: 'msg-001-6', type: 'whatsapp', direction: 'outbound', from: 'Carlos Villalba', to: 'María Elena Pérez', subject: null, body: 'Perfecto, ya quedó registrado el pago. Gracias María Elena. El recibo que le llegó era del mes anterior, ya se corrigió. Cualquier cosa me avisa!', timestamp: '2026-04-01T14:30:00', aiDigest: null, deliveryStatus: 'read' },
],
aiSummary: 'Cliente consultó sobre un pago que ya había realizado. Se verificó con contabilidad que la transferencia fue recibida y el recibo cruzado con un período anterior fue corregido. Ticket resuelto satisfactoriamente.',
aiSuggestedIntent: 'payment_inquiry',
aiConfidence: 0.92,
routingTrace: [
{ step: 'Channel Detection', result: 'WhatsApp — número registrado: +507 6123-4567', timestamp: '2026-04-01T09:15:01' },
{ step: 'Customer Match', result: 'Matched: María Elena Pérez Solano (cust-001)', timestamp: '2026-04-01T09:15:02' },
{ step: 'Intent Classification', result: 'payment_inquiry (92% confidence) — keywords: "pago", "recibo", "transferencia"', timestamp: '2026-04-01T09:15:03' },
{ step: 'Rule Fired', result: 'Payment intent → Collections queue', timestamp: '2026-04-01T09:15:04' },
{ step: 'Agent Assignment', result: 'Carlos Villalba (assigned broker for cust-001)', timestamp: '2026-04-01T09:15:05' },
],
}
const sp002Detail: SupportTicketDetail = {
...MOCK_SUPPORT_TICKETS[1],
customerEmail: 'luis.solis@outlook.com',
customerPhone: '+507 6555-1234',
linkedPolicies: [
{ id: 'POL-2022-2200', number: 'AUTO-2022-2200', carrier: 'Qualitas', lob: 'Auto', status: 'Active', renewal: '2027-01-15' },
{ id: 'POL-2022-2201', number: 'AUTO-2022-2201', carrier: 'Qualitas', lob: 'Auto', status: 'Active', renewal: '2027-01-15' },
],
linkedClaims: [
{ id: 'CLM-0048', type: 'Collision', status: 'Under Review' },
],
messages: [
{ id: 'msg-002-1', type: 'email', direction: 'inbound', from: 'luis.solis@outlook.com', to: 'soporte@seguros.com', subject: 'Reporte de accidente — BMW X5 SJO-2200', body: 'Estimados, les informo que tuve un accidente vehicular el día de hoy en la autopista Próspero Fernández. Mi vehículo BMW X5 placas SJO-2200 sufrió daños frontales tras una colisión. Adjunto fotos del daño. Por favor indiquen los pasos a seguir para el reclamo.', timestamp: '2026-04-03T11:22:00', aiDigest: 'Customer reporting vehicle collision on Próspero Fernández highway. BMW X5, front damage. Requesting claim process guidance.' },
{ id: 'msg-002-2', type: 'system', direction: 'internal', from: 'Sistema', to: null, subject: null, body: 'Ticket creado. Intent: claim_report (97%). Enrutado a Siniestros. Claim CLM-0048 vinculado automáticamente.', timestamp: '2026-04-03T11:22:10', aiDigest: null },
{ id: 'msg-002-3', type: 'email', direction: 'outbound', from: 'maria.ortiz@seguros.com', to: 'luis.solis@outlook.com', subject: 'Re: Reporte de accidente — BMW X5 SJO-2200', body: 'Estimado Luis, lamentamos mucho el accidente. Ya creamos su reclamo bajo el número CLM-0048. Necesitamos:\n\n1. Parte policial (si aplica)\n2. Fotos adicionales del otro vehículo\n3. Datos del otro conductor\n\nQuedo atenta.', timestamp: '2026-04-03T14:00:00', aiDigest: null },
{ id: 'msg-002-4', type: 'internal_note', direction: 'internal', from: 'María Fernanda Ortiz', to: null, subject: null, body: 'Cliente VIP — 2 pólizas activas, $5,800/yr premium. Priorizar este caso. Contactar ajustador para inspección rápida.', timestamp: '2026-04-04T08:30:00', aiDigest: null },
{ id: 'msg-002-5', type: 'email', direction: 'inbound', from: 'luis.solis@outlook.com', to: 'soporte@seguros.com', subject: 'Re: Reporte de accidente — BMW X5 SJO-2200', body: 'Adjunto las fotos del daño al vehículo tomadas esta mañana. El parte policial lo tengo listo para mañana. El otro conductor no quiso dar sus datos, pero tengo la placa.', timestamp: '2026-04-07T16:45:00', aiDigest: null },
],
aiSummary: 'Accidente vehicular reportado por correo. BMW X5, daños frontales por colisión en autopista. Claim CLM-0048 creado y vinculado. Pendiente: parte policial y datos del otro conductor. Cliente VIP con 2 pólizas — priorizar.',
aiSuggestedIntent: 'claim_report',
aiConfidence: 0.97,
routingTrace: [
{ step: 'Channel Detection', result: 'Email — luis.solis@outlook.com', timestamp: '2026-04-03T11:22:01' },
{ step: 'Customer Match', result: 'Matched: Luis Andrés Solís Calderón (cust-004)', timestamp: '2026-04-03T11:22:02' },
{ step: 'Intent Classification', result: 'claim_report (97%) — keywords: "accidente", "daños", "colisión", "reclamo"', timestamp: '2026-04-03T11:22:03' },
{ step: 'Rule Fired', result: 'Claim intent → Claims queue', timestamp: '2026-04-03T11:22:04' },
{ step: 'Policy Link', result: 'Auto-linked POL-2022-2200 (BMW X5, matching plate SJO-2200)', timestamp: '2026-04-03T11:22:05' },
],
}
const sp003Detail: SupportTicketDetail = {
...MOCK_SUPPORT_TICKETS[2],
customerEmail: 'roberto.jimenez@gmail.com',
customerPhone: '+507 6222-8899',
linkedPolicies: [
{ id: 'POL-2023-3301', number: 'AUTO-2023-3301', carrier: 'Qualitas', lob: 'Auto', status: 'Active', renewal: '2027-04-01' },
],
linkedClaims: [],
messages: [
{ id: 'msg-003-1', type: 'phone_note', direction: 'inbound', from: 'Roberto Jiménez Mora', to: null, subject: null, body: 'Cliente se presentó en oficina solicitando certificado de seguro vigente para trámite bancario. Necesita documento hoy.', timestamp: '2026-04-04T10:00:00', aiDigest: null },
{ id: 'msg-003-2', type: 'system', direction: 'internal', from: 'Sistema', to: null, subject: null, body: 'Cliente conocido (cust-002). Tier 1 auto-route: solicitud de certificado → Operaciones. Auto-fulfill iniciado.', timestamp: '2026-04-04T10:00:05', aiDigest: null },
{ id: 'msg-003-3', type: 'internal_note', direction: 'internal', from: 'Ana R.', to: null, subject: null, body: 'Certificado generado y entregado en mano. Cliente satisfecho. Ticket cerrado.', timestamp: '2026-04-04T10:35:00', aiDigest: null },
],
aiSummary: 'Solicitud de certificado de seguro vigente para trámite bancario. Cliente conocido, auto-enrutado a operaciones. Certificado generado y entregado presencialmente en 35 minutos.',
aiSuggestedIntent: 'certificate_request',
aiConfidence: 0.99,
routingTrace: [
{ step: 'Walk-in Registration', result: 'Registered by front desk', timestamp: '2026-04-04T10:00:01' },
{ step: 'Customer Match', result: 'Matched: Roberto Jiménez Mora (cust-002)', timestamp: '2026-04-04T10:00:02' },
{ step: 'Intent Classification', result: 'certificate_request (99%) — direct request', timestamp: '2026-04-04T10:00:03' },
{ step: 'Tier 1 Auto-Fulfill', result: 'Certificate generation triggered for POL-2023-3301', timestamp: '2026-04-04T10:00:05' },
],
}
const sp004Detail: SupportTicketDetail = {
...MOCK_SUPPORT_TICKETS[3],
customerEmail: null,
customerPhone: '+507 6789-0123',
linkedPolicies: [],
linkedClaims: [],
messages: [
{ id: 'msg-004-1', type: 'whatsapp', direction: 'inbound', from: '+507 6789-0123', to: null, subject: null, body: 'Buenas, cuánto sale un seguro todo riesgo para un BMW X3 2025? Nuevo, recién importado.', timestamp: '2026-04-07T08:30:00', aiDigest: 'Unknown number asking for comprehensive auto insurance quote for new BMW X3 2025.' },
{ id: 'msg-004-2', type: 'system', direction: 'internal', from: 'Sistema', to: null, subject: null, body: 'Número no registrado. Intent: sales_interest (89%). Enrutado a Ventas.', timestamp: '2026-04-07T08:30:05', aiDigest: null },
{ id: 'msg-004-3', type: 'whatsapp', direction: 'outbound', from: 'María Fernanda Ortiz', to: '+507 6789-0123', subject: null, body: 'Buenos días! Con gusto le cotizamos. Para darle las mejores opciones necesito:\n\n1. Nombre completo\n2. Cédula o pasaporte\n3. Valor del vehículo según factura\n4. Uso (particular o comercial)\n\nQuedo atenta!', timestamp: '2026-04-07T09:15:00', aiDigest: null, deliveryStatus: 'delivered' },
],
aiSummary: 'Lead entrante vía WhatsApp — persona desconocida consultando precio de seguro todo riesgo para BMW X3 2025 nuevo. Asignado a ventas. Pendiente respuesta del prospecto con datos personales.',
aiSuggestedIntent: 'sales_interest',
aiConfidence: 0.89,
routingTrace: [
{ step: 'Channel Detection', result: 'WhatsApp — +507 6789-0123', timestamp: '2026-04-07T08:30:01' },
{ step: 'Customer Match', result: 'No match — unknown number', timestamp: '2026-04-07T08:30:02' },
{ step: 'Intent Classification', result: 'sales_interest (89%) — keywords: "cuánto sale", "seguro todo riesgo", "nuevo"', timestamp: '2026-04-07T08:30:03' },
{ step: 'Rule Fired', result: 'Sales intent → Sales queue', timestamp: '2026-04-07T08:30:04' },
],
}
const sp005Detail: SupportTicketDetail = {
...MOCK_SUPPORT_TICKETS[4],
customerEmail: 'maria.perez@gmail.com',
customerPhone: '+507 6123-4567',
linkedPolicies: [
{ id: 'POL-2024-4412', number: 'AUTO-2024-4412', carrier: 'ASSA', lob: 'Auto', status: 'Active', renewal: '2027-03-15' },
],
linkedClaims: [
{ id: 'CLM-0048', type: 'Collision', status: 'Under Review' },
],
messages: [
{ id: 'msg-005-1', type: 'email', direction: 'inbound', from: 'maria.perez@gmail.com', to: 'soporte@seguros.com', subject: 'QUEJA — demora inaceptable en siniestro CLM-0048', body: 'Estimados, llevo más de 3 semanas esperando respuesta sobre mi siniestro CLM-0048. He llamado varias veces y nadie me da una respuesta clara. Esto es inaceptable. Necesito que alguien con autoridad me contacte hoy mismo o procederé con una queja formal ante la Superintendencia.', timestamp: '2026-04-02T15:00:00', aiDigest: 'Frustrated customer filing formal complaint about claim CLM-0048 delays. Threatening regulatory escalation.' },
{ id: 'msg-005-2', type: 'system', direction: 'internal', from: 'Sistema', to: null, subject: null, body: 'Intent ambiguo: complaint (76%) / claim_report (18%). No cumple regla de enrutamiento directo. Enviado a Pool Abierto.', timestamp: '2026-04-02T15:00:05', aiDigest: null },
{ id: 'msg-005-3', type: 'internal_note', direction: 'internal', from: 'Carlos Villalba', to: null, subject: null, body: 'Asigno este ticket a mí. Conozco a la clienta — tiene razón, el claim lleva demasiado tiempo. Voy a escalar con el ajustador de ASSA directamente.', timestamp: '2026-04-02T16:30:00', aiDigest: null },
{ id: 'msg-005-4', type: 'email', direction: 'outbound', from: 'carlos.villalba@seguros.com', to: 'maria.perez@gmail.com', subject: 'Re: QUEJA — demora inaceptable en siniestro CLM-0048', body: 'Estimada María Elena, le pido disculpas sinceras por la demora. He escalado personalmente su caso con el ajustador de ASSA y tenemos reunión mañana a primera hora. Le daré un update antes del mediodía del viernes. Entiendo su frustración y estoy comprometido a resolverlo.', timestamp: '2026-04-02T17:00:00', aiDigest: null },
{ id: 'msg-005-5', type: 'internal_note', direction: 'internal', from: 'Carlos Villalba', to: null, subject: null, body: 'Reunión con ajustador ASSA — dicen que falta un documento del taller. Ya lo solicité. Debería llegar mañana.', timestamp: '2026-04-04T10:00:00', aiDigest: null },
{ id: 'msg-005-6', type: 'email', direction: 'outbound', from: 'carlos.villalba@seguros.com', to: 'maria.perez@gmail.com', subject: 'Re: QUEJA — Actualización siniestro CLM-0048', body: 'María Elena, actualización: ASSA necesita un documento adicional del taller donde se hizo la reparación. ¿Podría solicitarle al taller el presupuesto final firmado y sellado? Con eso podemos cerrar la revisión esta semana.', timestamp: '2026-04-04T14:00:00', aiDigest: null },
{ id: 'msg-005-7', type: 'email', direction: 'outbound', from: 'carlos.villalba@seguros.com', to: 'maria.perez@gmail.com', subject: 'Re: QUEJA — Seguimiento documentos pendientes', body: 'Hola María Elena, solo un seguimiento amable — estamos pendientes de su respuesta con los documentos adicionales del taller para avanzar con ASSA. Quedo a la orden.', timestamp: '2026-04-06T09:20:00', aiDigest: null },
],
aiSummary: 'Queja formal por demora en siniestro CLM-0048 (colisión). Cliente amenaza con escalar a Superintendencia. Broker Carlos Villalba se asignó y escaló con ajustador ASSA. Pendiente: documento del taller (presupuesto firmado) para cerrar revisión. Estado: esperando respuesta del cliente.',
aiSuggestedIntent: 'complaint',
aiConfidence: 0.76,
routingTrace: [
{ step: 'Channel Detection', result: 'Email — maria.perez@gmail.com', timestamp: '2026-04-02T15:00:01' },
{ step: 'Customer Match', result: 'Matched: María Elena Pérez Solano (cust-001)', timestamp: '2026-04-02T15:00:02' },
{ step: 'Intent Classification', result: 'Ambiguous — complaint (76%), claim_report (18%)', timestamp: '2026-04-02T15:00:03' },
{ step: 'No Rule Match', result: 'Confidence below threshold for auto-routing', timestamp: '2026-04-02T15:00:04' },
{ step: 'Routed to Open Pool', result: 'Tier 3 — awaiting manual triage', timestamp: '2026-04-02T15:00:05' },
],
}
const sp006Detail: SupportTicketDetail = {
...MOCK_SUPPORT_TICKETS[5],
customerEmail: 'fernando.arias@transportesnorte.cr',
customerPhone: '+507 6888-4444',
linkedPolicies: [
{ id: 'POL-2020-1100', number: 'AUTO-2020-1100', carrier: 'INS', lob: 'Auto', status: 'Active', renewal: '2026-12-15' },
{ id: 'POL-2021-2200', number: 'HOME-2021-2200', carrier: 'ASSA', lob: 'Home', status: 'Lapsed', renewal: '—' },
],
linkedClaims: [],
messages: [
{ id: 'msg-006-1', type: 'email', direction: 'inbound', from: 'fernando.arias@transportesnorte.cr', to: 'soporte@seguros.com', subject: 'Consulta — plan salud colectivo para nuestro grupo', body: 'Buenos días, soy Fernando Arias de Transportes del Norte. Quiero explorar opciones de seguro de salud colectivo para nuestros empleados (aprox 50 personas). ¿Qué opciones tienen disponibles y cuál sería el proceso?', timestamp: '2026-04-06T14:10:00', aiDigest: 'Existing corporate customer inquiring about group health insurance for ~50 employees.' },
{ id: 'msg-006-2', type: 'system', direction: 'internal', from: 'Sistema', to: null, subject: null, body: 'Cliente conocido (cust-010). Web form con LOB=Health. Tier 1: auto-routed a broker asignado (Ana R.).', timestamp: '2026-04-06T14:10:05', aiDigest: null },
{ id: 'msg-006-3', type: 'email', direction: 'outbound', from: 'ana.r@seguros.com', to: 'fernando.arias@transportesnorte.cr', subject: 'Re: Consulta — plan salud colectivo', body: 'Estimado Fernando, qué gusto saludarlo! Con mucho gusto le ayudamos con el plan colectivo de salud. Tenemos opciones con Vida Plena, Salud Global e Integral Medical. Le envío las opciones de cobertura para su grupo con los detalles de cada plan.', timestamp: '2026-04-06T16:00:00', aiDigest: null },
{ id: 'msg-006-4', type: 'internal_note', direction: 'internal', from: 'Ana R.', to: null, subject: null, body: 'Cliente ya tiene 2 pólizas (1 activa auto, 1 lapsed home). Oportunidad de cross-sell. Preparar propuesta colectiva con las 3 aseguradoras de salud.', timestamp: '2026-04-07T11:00:00', aiDigest: null },
],
aiSummary: 'Cliente corporativo existente (Transportes del Norte) consultando sobre plan de salud colectivo para ~50 empleados. Auto-enrutado por Tier 1 a broker asignado. Oportunidad de cross-sell identificada — ya tiene póliza auto activa.',
aiSuggestedIntent: 'policy_question',
aiConfidence: 0.85,
routingTrace: [
{ step: 'Channel Detection', result: 'Web Form — LOB: Health', timestamp: '2026-04-06T14:10:01' },
{ step: 'Customer Match', result: 'Matched: Fernando Arias Blanco (cust-010)', timestamp: '2026-04-06T14:10:02' },
{ step: 'Tier 1 Auto-Route', result: 'Known customer + LOB form → assigned broker', timestamp: '2026-04-06T14:10:03' },
{ step: 'Agent Assignment', result: 'Ana R. (assigned broker for cust-010)', timestamp: '2026-04-06T14:10:05' },
],
}
const sp007Detail: SupportTicketDetail = {
...MOCK_SUPPORT_TICKETS[6],
customerEmail: null,
customerPhone: '+507 6234-5678',
linkedPolicies: [],
linkedClaims: [],
messages: [
{ id: 'msg-007-1', type: 'whatsapp', direction: 'inbound', from: '+507 6234-5678', to: null, subject: null, body: 'Hola buenos días, necesito ayuda con mi seguro, me pueden atender?', timestamp: '2026-04-08T07:45:00', aiDigest: 'Ambiguous request — "need help with my insurance". No specific intent detectable. Unknown customer.' },
],
aiSummary: 'Mensaje ambiguo de número desconocido. No se puede determinar intención específica. Requiere triage manual por operador del pool abierto.',
aiSuggestedIntent: 'general',
aiConfidence: 0.34,
routingTrace: [
{ step: 'Channel Detection', result: 'WhatsApp — +507 6234-5678', timestamp: '2026-04-08T07:45:01' },
{ step: 'Customer Match', result: 'No match — unknown number', timestamp: '2026-04-08T07:45:02' },
{ step: 'Intent Classification', result: 'Ambiguous — general (34%), policy_question (28%), sales_interest (22%)', timestamp: '2026-04-08T07:45:03' },
{ step: 'No Rule Match', result: 'Low confidence across all intents', timestamp: '2026-04-08T07:45:04' },
{ step: 'Routed to Open Pool', result: 'Tier 3 — unassigned, awaiting manual triage', timestamp: '2026-04-08T07:45:05' },
],
}
const sp008Detail: SupportTicketDetail = {
...MOCK_SUPPORT_TICKETS[7],
customerEmail: 'luis.solis@outlook.com',
customerPhone: '+507 6555-1234',
linkedPolicies: [
{ id: 'POL-2022-2201', number: 'AUTO-2022-2201', carrier: 'Qualitas', lob: 'Auto', status: 'Active', renewal: '2027-01-15' },
],
linkedClaims: [],
messages: [
{ id: 'msg-008-1', type: 'email', direction: 'inbound', from: 'luis.solis@outlook.com', to: 'soporte@seguros.com', subject: 'Agregar conductor adicional a póliza AUTO-2022-2201', body: 'Estimados, necesito agregar a mi esposa como conductor adicional en mi póliza AUTO-2022-2201 (Mercedes GLC). ¿Qué documentos necesitan y cuál es el costo adicional?', timestamp: '2026-04-05T09:00:00', aiDigest: 'Customer requesting driver addition endorsement to auto policy. Asking about requirements and cost.' },
{ id: 'msg-008-2', type: 'system', direction: 'internal', from: 'Sistema', to: null, subject: null, body: 'Intent: endorsement (94%). Enrutado a Operaciones.', timestamp: '2026-04-05T09:00:05', aiDigest: null },
{ id: 'msg-008-3', type: 'email', direction: 'outbound', from: 'ana.r@seguros.com', to: 'luis.solis@outlook.com', subject: 'Re: Agregar conductor adicional a póliza AUTO-2022-2201', body: 'Estimado Luis, con gusto procesamos el endoso. Necesitamos:\n\n1. Cédula de su esposa (copia)\n2. Licencia de conducir vigente (copia)\n3. Fecha de nacimiento\n\nEl costo adicional depende del perfil — generalmente entre $50-$120/año. Le confirmo el monto exacto una vez tenga los documentos.', timestamp: '2026-04-05T11:30:00', aiDigest: null },
{ id: 'msg-008-4', type: 'email', direction: 'inbound', from: 'luis.solis@outlook.com', to: 'soporte@seguros.com', subject: 'Re: Agregar conductor adicional', body: 'Adjunto cédula y licencia de mi esposa Carolina Méndez de Solís. Su fecha de nacimiento es 15 de mayo de 1988.', timestamp: '2026-04-06T14:00:00', aiDigest: null },
{ id: 'msg-008-5', type: 'internal_note', direction: 'internal', from: 'Ana R.', to: null, subject: null, body: 'Documentos recibidos. Solicitando cotización de endoso a Qualitas. Pendiente respuesta del carrier para confirmar monto.', timestamp: '2026-04-07T15:30:00', aiDigest: null },
],
aiSummary: 'Solicitud de endoso para agregar conductor adicional (esposa) a póliza auto Mercedes GLC. Documentos recibidos (cédula + licencia). Pendiente cotización del carrier Qualitas para confirmar costo adicional.',
aiSuggestedIntent: 'endorsement',
aiConfidence: 0.94,
routingTrace: [
{ step: 'Channel Detection', result: 'Email — luis.solis@outlook.com', timestamp: '2026-04-05T09:00:01' },
{ step: 'Customer Match', result: 'Matched: Luis Andrés Solís Calderón (cust-004)', timestamp: '2026-04-05T09:00:02' },
{ step: 'Intent Classification', result: 'endorsement (94%) — keywords: "agregar", "conductor adicional", "endoso"', timestamp: '2026-04-05T09:00:03' },
{ step: 'Rule Fired', result: 'Endorsement intent → Operations queue', timestamp: '2026-04-05T09:00:04' },
],
}
const sp009Detail: SupportTicketDetail = {
...MOCK_SUPPORT_TICKETS[8],
customerEmail: 'fernando.arias@transportesnorte.cr',
customerPhone: '+507 6888-4444',
linkedPolicies: [
{ id: 'POL-2020-1100', number: 'AUTO-2020-1100', carrier: 'INS', lob: 'Auto', status: 'Active', renewal: '2026-12-15' },
],
linkedClaims: [],
messages: [
{ id: 'msg-009-1', type: 'whatsapp', direction: 'inbound', from: 'Fernando Arias', to: null, subject: null, body: 'URGENTE Carlos!! Acabo de tener un choque frontal con la Hilux en la vía Interamericana. El carro no enciende y necesito grúa YA. Estoy en el km 42 dirección David.', timestamp: '2026-04-08T06:15:00', aiDigest: 'URGENT: Known customer reporting front collision with Toyota Hilux. Vehicle disabled, requesting tow truck. Location: km 42 Interamericana highway.' },
{ id: 'msg-009-2', type: 'system', direction: 'internal', from: 'Sistema', to: null, subject: null, body: 'URGENTE — Cliente conocido (cust-010). Intent: claim_report (99%). Tier 1 auto-route a broker asignado. Prioridad: URGENTE.', timestamp: '2026-04-08T06:15:05', aiDigest: null },
{ id: 'msg-009-3', type: 'whatsapp', direction: 'outbound', from: 'Carlos Villalba', to: 'Fernando Arias', subject: null, body: 'Fernando tranquilo, ya estoy en eso. ¿Estás bien? ¿Hay heridos? Voy a coordinar la grúa ahora mismo.', timestamp: '2026-04-08T06:20:00', aiDigest: null, deliveryStatus: 'read' },
{ id: 'msg-009-4', type: 'whatsapp', direction: 'outbound', from: 'Carlos Villalba', to: 'Fernando Arias', subject: null, body: 'Ya coordiné la grúa, llega en 20 minutos a tu ubicación. INS tiene cobertura de asistencia en carretera incluida en tu póliza. ¿Necesitas que llame a alguien más?', timestamp: '2026-04-08T06:45:00', aiDigest: null, deliveryStatus: 'delivered' },
],
aiSummary: 'Emergencia: choque frontal con Toyota Hilux en vía Interamericana km 42. Vehículo inhabilitado. Broker coordinó grúa inmediatamente (20 min ETA). Asistencia en carretera cubierta por póliza INS. Pendiente: confirmar estado del conductor y crear claim formal.',
aiSuggestedIntent: 'claim_report',
aiConfidence: 0.99,
routingTrace: [
{ step: 'Channel Detection', result: 'WhatsApp — +507 6888-4444 (Fernando Arias)', timestamp: '2026-04-08T06:15:01' },
{ step: 'Customer Match', result: 'Matched: Fernando Arias Blanco (cust-010)', timestamp: '2026-04-08T06:15:02' },
{ step: 'Intent Classification', result: 'claim_report (99%) — keywords: "choque", "grúa", "URGENTE"', timestamp: '2026-04-08T06:15:03' },
{ step: 'Priority Escalation', result: 'Auto-set URGENT — emergency keywords detected', timestamp: '2026-04-08T06:15:04' },
{ step: 'Tier 1 Auto-Route', result: 'Known customer → assigned broker Carlos Villalba', timestamp: '2026-04-08T06:15:05' },
],
}
const sp010Detail: SupportTicketDetail = {
...MOCK_SUPPORT_TICKETS[9],
customerEmail: 'roberto.jimenez@gmail.com',
customerPhone: '+507 6222-8899',
linkedPolicies: [
{ id: 'POL-2023-3301', number: 'AUTO-2023-3301', carrier: 'Qualitas', lob: 'Auto', status: 'Active', renewal: '2027-04-01' },
],
linkedClaims: [],
messages: [
{ id: 'msg-010-1', type: 'phone_note', direction: 'inbound', from: 'Roberto Jiménez Mora', to: null, subject: null, body: 'Cliente llamó consultando sobre su renovación que vence el 30 de abril. Quiere saber si hay cambio en prima y si puede agregar cobertura de robo.', timestamp: '2026-04-03T16:00:00', aiDigest: 'Customer calling about upcoming renewal (Apr 30). Asking about premium changes and adding theft coverage.' },
{ id: 'msg-010-2', type: 'system', direction: 'internal', from: 'Sistema', to: null, subject: null, body: 'Intent: policy_question (78%) / sales_interest (15%). Keyword "renovación" → Renewals queue.', timestamp: '2026-04-03T16:00:05', aiDigest: null },
{ id: 'msg-010-3', type: 'internal_note', direction: 'internal', from: 'María Fernanda Ortiz', to: null, subject: null, body: 'Cliente confirmó renovación con cobertura adicional de robo. Prima aumenta $180/año. Proceso completado — renovación efectiva 1 mayo 2027.', timestamp: '2026-04-04T09:00:00', aiDigest: null },
],
aiSummary: 'Seguimiento telefónico sobre renovación próxima (30 abril). Cliente confirmó renovación con adición de cobertura de robo (+$180/año). Proceso completado.',
aiSuggestedIntent: 'policy_question',
aiConfidence: 0.78,
routingTrace: [
{ step: 'Channel Detection', result: 'Phone call logged', timestamp: '2026-04-03T16:00:01' },
{ step: 'Customer Match', result: 'Matched: Roberto Jiménez Mora (cust-002)', timestamp: '2026-04-03T16:00:02' },
{ step: 'Intent Classification', result: 'policy_question (78%) — keyword: "renovación"', timestamp: '2026-04-03T16:00:03' },
{ step: 'Rule Fired', result: 'Renewal keyword → Renewals queue', timestamp: '2026-04-03T16:00:04' },
],
}
export const MOCK_TICKET_DETAILS: Record<string, SupportTicketDetail> = {
'SP-001': sp001Detail,
'SP-002': sp002Detail,
'SP-003': sp003Detail,
'SP-004': sp004Detail,
'SP-005': sp005Detail,
'SP-006': sp006Detail,
'SP-007': sp007Detail,
'SP-008': sp008Detail,
'SP-009': sp009Detail,
'SP-010': sp010Detail,
}
// ─── Mock Routing Rules ──────────────────────────────────────────────────────
export const MOCK_ROUTING_RULES: RoutingRule[] = [
// Tier 1
{ id: 'rule-001', tier: 'tier1_auto', type: 'customer_match', name: 'Known Customer → Assigned Broker', condition: 'When incoming message matches a registered customer, route to their assigned broker', targetQueue: 'operations', targetAgent: null, enabled: true, priority: 1 },
{ id: 'rule-002', tier: 'tier1_auto', type: 'lob_specialist', name: 'Web Form LOB → Specialist', condition: 'Web form with LOB selected routes to LOB specialist team', targetQueue: 'operations', targetAgent: null, enabled: true, priority: 2 },
{ id: 'rule-003', tier: 'tier1_auto', type: 'doc_auto_fulfill', name: 'Certificate Auto-Fulfill', condition: 'Certificate requests from known customers auto-generate and deliver', targetQueue: 'operations', targetAgent: null, enabled: true, priority: 3 },
// Tier 2
{ id: 'rule-004', tier: 'tier2_rule', type: 'keyword_intent', name: 'Payment Keywords → Collections', condition: 'Keywords: pago, factura, cobro, recibo, transferencia, mora', targetQueue: 'collections', targetAgent: null, enabled: true, priority: 10 },
{ id: 'rule-005', tier: 'tier2_rule', type: 'keyword_intent', name: 'Claim Keywords → Claims', condition: 'Keywords: siniestro, accidente, robo, daño, choque, grúa, colisión', targetQueue: 'claims', targetAgent: null, enabled: true, priority: 11 },
{ id: 'rule-006', tier: 'tier2_rule', type: 'keyword_intent', name: 'Sales Keywords → Sales', condition: 'Keywords: cotización, seguro nuevo, precio, cuánto sale, cobertura', targetQueue: 'sales', targetAgent: null, enabled: true, priority: 12 },
{ id: 'rule-007', tier: 'tier2_rule', type: 'keyword_intent', name: 'Renewal Keywords → Renewals', condition: 'Keywords: renovación, vencimiento, prórroga, vigencia', targetQueue: 'renewals', targetAgent: null, enabled: true, priority: 13 },
{ id: 'rule-008', tier: 'tier2_rule', type: 'keyword_intent', name: 'Endorsement Keywords → Operations', condition: 'Keywords: endoso, agregar, modificar, cambio de beneficiario', targetQueue: 'operations', targetAgent: null, enabled: true, priority: 14 },
]