WIP jordan
This commit is contained in:
70
app/data/auto-quote-intake.ts
Normal file
70
app/data/auto-quote-intake.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
/** Auto quoting — option lists aligned with grid filters / production LOB vocabulary (ES labels). */
|
||||
|
||||
export const AUTO_RAMO_LABEL = 'Vehículos'
|
||||
|
||||
/** First option is empty — pair with placeholder “Select one” in UI */
|
||||
export const AUTO_SUB_RAMO_OPTIONS: { label: string; value: string }[] = [
|
||||
{ label: 'Manual', value: 'manual' },
|
||||
{ label: 'Cobertura completa', value: 'cobertura_completa' },
|
||||
{ label: 'Daños a terceros', value: 'danos_terceros' }
|
||||
]
|
||||
|
||||
export const AUTO_CLASE_OPTIONS: { label: string; value: string }[] = [
|
||||
{ label: 'Pickup', value: 'pickup' },
|
||||
{ label: 'Mula', value: 'mula' },
|
||||
{ label: 'Van', value: 'van' },
|
||||
{ label: 'MiniVan', value: 'minivan' },
|
||||
{ label: 'Panel', value: 'panel' },
|
||||
{ label: 'Camión', value: 'camion' },
|
||||
{ label: 'Camioneta', value: 'camioneta' },
|
||||
{ label: 'Sedan', value: 'sedan' },
|
||||
{ label: 'Cabezal', value: 'cabezal' },
|
||||
{ label: 'Bus (0-15)', value: 'bus_0_15' },
|
||||
{ label: 'Bus (16-30)', value: 'bus_16_30' },
|
||||
{ label: 'Bus (+30)', value: 'bus_30_plus' },
|
||||
{ label: 'Liviano', value: 'liviano' },
|
||||
{ label: 'Mediano', value: 'mediano' },
|
||||
{ label: 'Pesado', value: 'pesado' },
|
||||
{ label: 'Moto', value: 'moto' }
|
||||
]
|
||||
|
||||
export const AUTO_USO_OPTIONS: { label: string; value: string }[] = [
|
||||
{ label: 'Particular', value: 'particular' },
|
||||
{ label: 'Comercial', value: 'comercial' }
|
||||
]
|
||||
|
||||
export const AUTO_MARCA_OPTIONS: { label: string; value: string }[] = [
|
||||
{ label: 'Toyota', value: 'toyota' }
|
||||
]
|
||||
|
||||
export const AUTO_MODELO_OPTIONS: { label: string; value: string }[] = [
|
||||
{ label: 'Cellica', value: 'cellica' },
|
||||
{ label: 'Corolla', value: 'corolla' }
|
||||
]
|
||||
|
||||
const currentYear = new Date().getFullYear()
|
||||
|
||||
export const AUTO_YEAR_OPTIONS: { label: string; value: string }[] = [
|
||||
...Array.from({ length: 22 }, (_, i) => {
|
||||
const y = String(currentYear - i)
|
||||
return { label: y, value: y }
|
||||
})
|
||||
]
|
||||
|
||||
/**
|
||||
* Carriers available for solicit — in production, matches providers configured under Settings / Providers
|
||||
* (each has a quoting email on file).
|
||||
*/
|
||||
export const AUTO_QUOTE_CARRIERS: { id: string; name: string; detail: string }[] = [
|
||||
{ id: 'mapfre', name: 'Mapfre', detail: 'Quoting email on file in provider profile' },
|
||||
{ id: 'seguros_aurora', name: 'Seguros Aurora', detail: 'Quoting email on file in provider profile' },
|
||||
{ id: 'continental', name: 'Continental', detail: 'Quoting email on file in provider profile' },
|
||||
{ id: 'internacional', name: 'Internacional', detail: 'Quoting email on file in provider profile' }
|
||||
]
|
||||
|
||||
/** Predetermined plan packages — comparative mode builds side-by-side rows from these */
|
||||
export const AUTO_COVERAGE_PLANS: { id: string; label: string; hint: string }[] = [
|
||||
{ id: 'cc_full', label: 'Cobertura completa', hint: 'Collision, comprehensive, liability' },
|
||||
{ id: 'dat', label: 'Daños a terceros', hint: 'Third-party liability' },
|
||||
{ id: 'plan_corporate', label: 'Paquete corporativo', hint: 'Fleet-friendly endorsements' }
|
||||
]
|
||||
41
app/data/form-field-groups.json
Normal file
41
app/data/form-field-groups.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"version": 1,
|
||||
"groups": [
|
||||
{
|
||||
"id": "kyc_identity",
|
||||
"title": "Identificación",
|
||||
"description": "Cédula, pasaporte, PEP según SSRP",
|
||||
"fieldKeys": ["full_name", "document_id", "document_expiry", "nationality"]
|
||||
},
|
||||
{
|
||||
"id": "life_risk_health",
|
||||
"title": "Salud y hábitos (vida)",
|
||||
"description": "Declaración de salud, tabaco, deportes de riesgo",
|
||||
"fieldKeys": ["smoking", "height_cm", "weight_kg", "medical_conditions"]
|
||||
},
|
||||
{
|
||||
"id": "auto_vehicle",
|
||||
"title": "Vehículo",
|
||||
"description": "Placa, uso, valor, accesorios",
|
||||
"fieldKeys": ["plate", "vin", "year", "use_type", "declared_value"]
|
||||
},
|
||||
{
|
||||
"id": "health_local_cover",
|
||||
"title": "Salud local · cobertura",
|
||||
"description": "Red, deducible, preexistencias",
|
||||
"fieldKeys": ["network", "deductible_usd", "preexisting_disclosure"]
|
||||
},
|
||||
{
|
||||
"id": "health_intl_cover",
|
||||
"title": "Salud internacional",
|
||||
"description": "Zona de cobertura, repatriación, USA cover",
|
||||
"fieldKeys": ["coverage_zone", "usa_cover", "repatriation"]
|
||||
},
|
||||
{
|
||||
"id": "home_property",
|
||||
"title": "Propiedad (hogar)",
|
||||
"description": "Ubicación, construcción, suma contenido",
|
||||
"fieldKeys": ["address", "construction_type", "contents_sum"]
|
||||
}
|
||||
]
|
||||
}
|
||||
116
app/data/forms-catalog.json
Normal file
116
app/data/forms-catalog.json
Normal file
@@ -0,0 +1,116 @@
|
||||
{
|
||||
"version": 1,
|
||||
"rows": [
|
||||
{
|
||||
"id": 39,
|
||||
"description": "1031083 GE_ADB_GEN_OPTIMA_DIG 250507",
|
||||
"insurerSlugs": ["optima"],
|
||||
"subRamoKey": "danos_terceros_completa",
|
||||
"subRamoLabel": "Daños a terceros · Cobertura completa",
|
||||
"personKinds": "both",
|
||||
"productLine": "auto_full_coverage",
|
||||
"fileUrl": "/forms/README.txt",
|
||||
"fileLabel": "17569365751031083-GE_ADB_GEN_OPTIMA.pdf",
|
||||
"badge": 39,
|
||||
"kind": "carrier_pdf",
|
||||
"fieldGroupIds": ["kyc_identity", "auto_vehicle"]
|
||||
},
|
||||
{
|
||||
"id": 38,
|
||||
"description": "1031082 GE_ADB_GEN_OPTIMA_DAT",
|
||||
"insurerSlugs": ["optima"],
|
||||
"subRamoKey": "vehiculos_dat",
|
||||
"subRamoLabel": "Vehículos · Daños a terceros (DAT)",
|
||||
"personKinds": "both",
|
||||
"productLine": "auto_dat_liability",
|
||||
"fileUrl": "/forms/README.txt",
|
||||
"fileLabel": "OPTIMA_DAT_solicitud.pdf",
|
||||
"badge": 38,
|
||||
"kind": "carrier_pdf",
|
||||
"fieldGroupIds": ["kyc_identity", "auto_vehicle"]
|
||||
},
|
||||
{
|
||||
"id": 37,
|
||||
"description": "MAPFRE_MUNDIAL_AUTO_FULL",
|
||||
"insurerSlugs": ["mapfre"],
|
||||
"subRamoKey": "danos_terceros_completa",
|
||||
"subRamoLabel": "Daños a terceros · Cobertura completa",
|
||||
"personKinds": "both",
|
||||
"productLine": "auto_full_coverage",
|
||||
"fileUrl": "/forms/README.txt",
|
||||
"fileLabel": "MAPFRE_MUNDIAL_FOREVER_PLUS.pdf",
|
||||
"badge": 37,
|
||||
"kind": "carrier_pdf",
|
||||
"fieldGroupIds": ["kyc_identity", "auto_vehicle"]
|
||||
},
|
||||
{
|
||||
"id": 36,
|
||||
"description": "ASSA_VIDA_UNIVERSAL_PACK",
|
||||
"insurerSlugs": ["assa"],
|
||||
"subRamoKey": "vida_universal",
|
||||
"subRamoLabel": "Vida universal · Protección y ahorro",
|
||||
"personKinds": "natural",
|
||||
"productLine": "life",
|
||||
"fileUrl": "/forms/README.txt",
|
||||
"fileLabel": "ASSA_Universal_II_illustration.pdf",
|
||||
"badge": 36,
|
||||
"kind": "carrier_pdf",
|
||||
"fieldGroupIds": ["kyc_identity", "life_risk_health"]
|
||||
},
|
||||
{
|
||||
"id": 35,
|
||||
"description": "SALUD_LOCAL_KYC",
|
||||
"insurerSlugs": ["mapfre", "assa"],
|
||||
"subRamoKey": "salud_local",
|
||||
"subRamoLabel": "Salud local",
|
||||
"personKinds": "both",
|
||||
"productLine": "health_local",
|
||||
"fileUrl": "/forms/README.txt",
|
||||
"fileLabel": "KYC_salud_local.pdf",
|
||||
"badge": 35,
|
||||
"kind": "carrier_pdf",
|
||||
"fieldGroupIds": ["kyc_identity", "health_local_cover"]
|
||||
},
|
||||
{
|
||||
"id": 34,
|
||||
"description": "SALUD_INTERNACIONAL_KYC",
|
||||
"insurerSlugs": ["palig", "mapfre"],
|
||||
"subRamoKey": "salud_internacional",
|
||||
"subRamoLabel": "Salud internacional / IPMI",
|
||||
"personKinds": "both",
|
||||
"productLine": "health_international",
|
||||
"fileUrl": "/forms/README.txt",
|
||||
"fileLabel": "IPMI_solicitud.pdf",
|
||||
"badge": 34,
|
||||
"kind": "carrier_pdf",
|
||||
"fieldGroupIds": ["kyc_identity", "health_intl_cover"]
|
||||
},
|
||||
{
|
||||
"id": 33,
|
||||
"description": "CEDULA_NATURAL",
|
||||
"insurerSlugs": ["optima", "mapfre", "assa", "acerta", "fedpa", "ancon"],
|
||||
"subRamoKey": "any",
|
||||
"subRamoLabel": "Cualquier ramo (identificación)",
|
||||
"personKinds": "natural",
|
||||
"productLine": null,
|
||||
"fileUrl": "/forms/README.txt",
|
||||
"fileLabel": "cedula_ejemplo.png",
|
||||
"kind": "identity",
|
||||
"fieldGroupIds": ["kyc_identity"]
|
||||
},
|
||||
{
|
||||
"id": 32,
|
||||
"description": "ACERTA_VEH_FULL_1012013",
|
||||
"insurerSlugs": ["acerta"],
|
||||
"subRamoKey": "danos_terceros_completa",
|
||||
"subRamoLabel": "Daños a terceros · Cobertura completa",
|
||||
"personKinds": "both",
|
||||
"productLine": "auto_full_coverage",
|
||||
"fileUrl": "/forms/README.txt",
|
||||
"fileLabel": "GE_ATC_GEN_ACERTA_DIG.pdf",
|
||||
"badge": 32,
|
||||
"kind": "carrier_pdf",
|
||||
"fieldGroupIds": ["kyc_identity", "auto_vehicle"]
|
||||
}
|
||||
]
|
||||
}
|
||||
53
app/data/health-quote-intake.ts
Normal file
53
app/data/health-quote-intake.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
/** Health quoting — mock carriers, plans, and reference rate table (age bands). */
|
||||
|
||||
export const HEALTH_QUOTE_CARRIERS: { id: string; name: string; detail: string; hasPublishedRateTable?: boolean }[] = [
|
||||
{
|
||||
id: 'vida_plena',
|
||||
name: 'Vida Plena Salud',
|
||||
detail: 'Quoting email on file · published age-banded table',
|
||||
hasPublishedRateTable: true
|
||||
},
|
||||
{
|
||||
id: 'salud_global',
|
||||
name: 'Salud Global',
|
||||
detail: 'Quoting email on file',
|
||||
hasPublishedRateTable: false
|
||||
},
|
||||
{
|
||||
id: 'integral_med',
|
||||
name: 'Integral Medical',
|
||||
detail: 'Quoting email on file',
|
||||
hasPublishedRateTable: true
|
||||
}
|
||||
]
|
||||
|
||||
export const HEALTH_COVERAGE_PLANS: { id: string; label: string; hint: string }[] = [
|
||||
{ id: 'local_base', label: 'Local · Base', hint: 'In-country network, standard deductible' },
|
||||
{ id: 'local_plus', label: 'Local · Plus', hint: 'Broader network, lower copay' },
|
||||
{ id: 'intl_major', label: 'International · Major medical', hint: 'Evacuation + US/EU coverage tier' }
|
||||
]
|
||||
|
||||
export const HEALTH_COVERAGE_AREA: { label: string; value: string }[] = [
|
||||
{ label: 'Local', value: 'local' },
|
||||
{ label: 'International', value: 'international' }
|
||||
]
|
||||
|
||||
export const HEALTH_NETWORK_TIER: { label: string; value: string }[] = [
|
||||
{ label: 'Preferred / cerrado', value: 'preferred' },
|
||||
{ label: 'Open / amplio', value: 'open' }
|
||||
]
|
||||
|
||||
export const HEALTH_DEDUCTIBLE: { label: string; value: string }[] = [
|
||||
{ label: '$500', value: '500' },
|
||||
{ label: '$1,000', value: '1000' },
|
||||
{ label: '$2,500', value: '2500' }
|
||||
]
|
||||
|
||||
/** Mock age-band premium table (USD/mo) — some carriers publish this instead of email-only quotes */
|
||||
export const HEALTH_AGE_BAND_REFERENCE: { ageBand: string; employee: number; spouse: number; children: number }[] = [
|
||||
{ ageBand: '0–17', employee: 0, spouse: 0, children: 118 },
|
||||
{ ageBand: '18–29', employee: 142, spouse: 198, children: 0 },
|
||||
{ ageBand: '30–44', employee: 186, spouse: 251, children: 0 },
|
||||
{ ageBand: '45–54', employee: 264, spouse: 318, children: 0 },
|
||||
{ ageBand: '55–64', employee: 352, spouse: 401, children: 0 }
|
||||
]
|
||||
45
app/data/life-quote-intake.ts
Normal file
45
app/data/life-quote-intake.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
/** Life quoting — mock carriers, plans, and option lists. */
|
||||
|
||||
export const LIFE_QUOTE_CARRIERS: { id: string; name: string; detail: string }[] = [
|
||||
{ id: 'vida_plena', name: 'Vida Plena', detail: 'Quoting email on file in provider profile' },
|
||||
{ id: 'seguros_del_pacifico', name: 'Seguros del Pacífico', detail: 'Quoting email on file in provider profile' },
|
||||
{ id: 'continental_life', name: 'Continental Life', detail: 'Quoting email on file in provider profile' }
|
||||
]
|
||||
|
||||
export const LIFE_COVERAGE_PLANS: { id: string; label: string; hint: string }[] = [
|
||||
{ id: 'term_basic', label: 'Term life · Basic', hint: 'Level-premium term, standard coverage' },
|
||||
{ id: 'term_plus', label: 'Term life · Plus', hint: 'Term with accidental-death rider' },
|
||||
{ id: 'whole_life', label: 'Whole life', hint: 'Permanent coverage with cash-value component' },
|
||||
{ id: 'keyman', label: 'Key person', hint: 'Business-owned policy on key employee' }
|
||||
]
|
||||
|
||||
export const LIFE_GENDER_OPTIONS: { label: string; value: string }[] = [
|
||||
{ label: 'Male', value: 'male' },
|
||||
{ label: 'Female', value: 'female' }
|
||||
]
|
||||
|
||||
export const LIFE_COVERAGE_TERM_OPTIONS: { label: string; value: string }[] = [
|
||||
{ label: '10 years', value: '10' },
|
||||
{ label: '15 years', value: '15' },
|
||||
{ label: '20 years', value: '20' },
|
||||
{ label: '30 years', value: '30' },
|
||||
{ label: 'Whole life', value: 'whole' }
|
||||
]
|
||||
|
||||
export const LIFE_COVERAGE_AMOUNT_OPTIONS: { label: string; value: string }[] = [
|
||||
{ label: '$25,000', value: '25000' },
|
||||
{ label: '$50,000', value: '50000' },
|
||||
{ label: '$100,000', value: '100000' },
|
||||
{ label: '$250,000', value: '250000' },
|
||||
{ label: '$500,000', value: '500000' },
|
||||
{ label: '$1,000,000', value: '1000000' }
|
||||
]
|
||||
|
||||
export const LIFE_BENEFICIARY_RELATIONSHIP_OPTIONS: { label: string; value: string }[] = [
|
||||
{ label: 'Spouse', value: 'spouse' },
|
||||
{ label: 'Child', value: 'child' },
|
||||
{ label: 'Parent', value: 'parent' },
|
||||
{ label: 'Sibling', value: 'sibling' },
|
||||
{ label: 'Business entity', value: 'business' },
|
||||
{ label: 'Other', value: 'other' }
|
||||
]
|
||||
363
app/data/mock-analytics.ts
Normal file
363
app/data/mock-analytics.ts
Normal file
@@ -0,0 +1,363 @@
|
||||
// ─── Business Analytics — Types, Labels, Mock Data ───────────────────────────
|
||||
|
||||
export type AnalyticsTimePoint = { m: string; v: number; display: string }
|
||||
export type AnalyticsDomainId = 'production' | 'claims' | 'pipeline' | 'service'
|
||||
export type AnalyticsChartType = 'line' | 'bar' | 'area'
|
||||
|
||||
export interface AnalyticsMetric {
|
||||
id: string
|
||||
domain: AnalyticsDomainId
|
||||
label: string
|
||||
unit: string
|
||||
data12m: AnalyticsTimePoint[]
|
||||
change: string
|
||||
changeTone: 'positive' | 'negative' | 'neutral'
|
||||
defaultChartType: AnalyticsChartType
|
||||
}
|
||||
|
||||
export interface AnalyticsKpiSummary {
|
||||
id: string
|
||||
label: string
|
||||
value: string
|
||||
change: string
|
||||
changeTone: 'positive' | 'negative' | 'neutral'
|
||||
hint: string
|
||||
sparkline: number[]
|
||||
}
|
||||
|
||||
// ─── Domain Labels ───────────────────────────────────────────────────────────
|
||||
|
||||
export const ANALYTICS_DOMAIN_LABELS: Record<AnalyticsDomainId, string> = {
|
||||
production: 'Producción',
|
||||
claims: 'Siniestros',
|
||||
pipeline: 'Pipeline',
|
||||
service: 'Servicio',
|
||||
}
|
||||
|
||||
// ─── Headline KPI Summaries ──────────────────────────────────────────────────
|
||||
|
||||
export const ANALYTICS_KPI_SUMMARIES: AnalyticsKpiSummary[] = [
|
||||
{ id: 'gwp', label: 'GWP Written', value: '$5.41M', change: '+6.2%', changeTone: 'positive', hint: 'Gross written premium YTD', sparkline: [72, 68, 76, 74, 81, 88, 85, 90, 87, 92, 95, 98] },
|
||||
{ id: 'policies', label: 'Active Policies', value: '342', change: '+12', changeTone: 'positive', hint: 'Currently active policies', sparkline: [290, 295, 298, 305, 310, 315, 318, 322, 328, 332, 338, 342] },
|
||||
{ id: 'loss-ratio', label: 'Loss Ratio', value: '58%', change: '-3.1%', changeTone: 'positive', hint: 'Claims paid / earned premium', sparkline: [68, 72, 65, 63, 60, 58, 61, 59, 57, 60, 58, 58] },
|
||||
{ id: 'retention', label: 'Retention Rate', value: '91%', change: '+1.2%', changeTone: 'positive', hint: 'Client renewal rate', sparkline: [86, 87, 88, 87, 89, 90, 89, 90, 91, 90, 91, 91] },
|
||||
{ id: 'open-claims', label: 'Open Claims', value: '7', change: '-2', changeTone: 'positive', hint: 'Currently unresolved claims', sparkline: [12, 11, 10, 9, 11, 10, 8, 9, 8, 7, 8, 7] },
|
||||
{ id: 'pipeline-value', label: 'Pipeline Value', value: '$6.2M', change: '+$820K', changeTone: 'positive', hint: 'Open quoted premium', sparkline: [42, 45, 48, 50, 52, 55, 53, 56, 58, 60, 62, 65] },
|
||||
]
|
||||
|
||||
// ─── Metrics: Production & Revenue ───────────────────────────────────────────
|
||||
|
||||
const productionMetrics: AnalyticsMetric[] = [
|
||||
{
|
||||
id: 'gwp', domain: 'production', label: 'GWP Written', unit: '$',
|
||||
change: '+6.2%', changeTone: 'positive', defaultChartType: 'area',
|
||||
data12m: [
|
||||
{ m: 'May', v: 62, display: '$3.82M' }, { m: 'Jun', v: 65, display: '$4.01M' },
|
||||
{ m: 'Jul', v: 60, display: '$3.70M' }, { m: 'Aug', v: 68, display: '$4.19M' },
|
||||
{ m: 'Sep', v: 71, display: '$4.38M' }, { m: 'Oct', v: 72, display: '$4.52M' },
|
||||
{ m: 'Nov', v: 68, display: '$4.28M' }, { m: 'Dec', v: 76, display: '$4.71M' },
|
||||
{ m: 'Jan', v: 74, display: '$4.61M' }, { m: 'Feb', v: 81, display: '$4.98M' },
|
||||
{ m: 'Mar', v: 88, display: '$5.41M' }, { m: 'Apr', v: 91, display: '$5.58M' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'premium-by-lob', domain: 'production', label: 'Premium by LOB', unit: '$',
|
||||
change: '+4.8%', changeTone: 'positive', defaultChartType: 'bar',
|
||||
data12m: [
|
||||
{ m: 'Auto', v: 85, display: '$1.82M' }, { m: 'Health', v: 72, display: '$1.54M' },
|
||||
{ m: 'Life', v: 48, display: '$1.03M' }, { m: 'Property', v: 35, display: '$750K' },
|
||||
{ m: 'Marine', v: 18, display: '$386K' }, { m: 'Liability', v: 12, display: '$257K' },
|
||||
{ m: 'Surety', v: 8, display: '$171K' }, { m: 'Travel', v: 5, display: '$107K' },
|
||||
{ m: 'Other', v: 3, display: '$64K' }, { m: '', v: 0, display: '' },
|
||||
{ m: '', v: 0, display: '' }, { m: '', v: 0, display: '' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'new-biz-vs-renewal', domain: 'production', label: 'New Biz vs Renewal', unit: '$',
|
||||
change: '+$820K', changeTone: 'positive', defaultChartType: 'bar',
|
||||
data12m: [
|
||||
{ m: 'May', v: 45, display: '$1.8M' }, { m: 'Jun', v: 48, display: '$1.9M' },
|
||||
{ m: 'Jul', v: 42, display: '$1.7M' }, { m: 'Aug', v: 52, display: '$2.1M' },
|
||||
{ m: 'Sep', v: 55, display: '$2.2M' }, { m: 'Oct', v: 52, display: '$2.4M' },
|
||||
{ m: 'Nov', v: 48, display: '$2.2M' }, { m: 'Dec', v: 62, display: '$2.9M' },
|
||||
{ m: 'Jan', v: 58, display: '$2.7M' }, { m: 'Feb', v: 64, display: '$3.0M' },
|
||||
{ m: 'Mar', v: 70, display: '$3.2M' }, { m: 'Apr', v: 73, display: '$3.4M' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'commission-revenue', domain: 'production', label: 'Commission Revenue', unit: '$',
|
||||
change: '+8.4%', changeTone: 'positive', defaultChartType: 'area',
|
||||
data12m: [
|
||||
{ m: 'May', v: 48, display: '$590K' }, { m: 'Jun', v: 50, display: '$615K' },
|
||||
{ m: 'Jul', v: 46, display: '$565K' }, { m: 'Aug', v: 53, display: '$652K' },
|
||||
{ m: 'Sep', v: 55, display: '$680K' }, { m: 'Oct', v: 55, display: '$680K' },
|
||||
{ m: 'Nov', v: 52, display: '$640K' }, { m: 'Dec', v: 60, display: '$740K' },
|
||||
{ m: 'Jan', v: 58, display: '$715K' }, { m: 'Feb', v: 65, display: '$800K' },
|
||||
{ m: 'Mar', v: 72, display: '$886K' }, { m: 'Apr', v: 75, display: '$923K' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'policies-bound', domain: 'production', label: 'Policies Bound', unit: '#',
|
||||
change: '+12', changeTone: 'positive', defaultChartType: 'bar',
|
||||
data12m: [
|
||||
{ m: 'May', v: 28, display: '28' }, { m: 'Jun', v: 30, display: '30' },
|
||||
{ m: 'Jul', v: 25, display: '25' }, { m: 'Aug', v: 33, display: '33' },
|
||||
{ m: 'Sep', v: 35, display: '35' }, { m: 'Oct', v: 32, display: '32' },
|
||||
{ m: 'Nov', v: 28, display: '28' }, { m: 'Dec', v: 35, display: '35' },
|
||||
{ m: 'Jan', v: 38, display: '38' }, { m: 'Feb', v: 36, display: '36' },
|
||||
{ m: 'Mar', v: 42, display: '42' }, { m: 'Apr', v: 44, display: '44' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'avg-premium', domain: 'production', label: 'Avg Premium', unit: '$',
|
||||
change: '+2.1%', changeTone: 'positive', defaultChartType: 'line',
|
||||
data12m: [
|
||||
{ m: 'May', v: 52, display: '$12.4K' }, { m: 'Jun', v: 53, display: '$12.6K' },
|
||||
{ m: 'Jul', v: 51, display: '$12.1K' }, { m: 'Aug', v: 54, display: '$12.8K' },
|
||||
{ m: 'Sep', v: 55, display: '$13.1K' }, { m: 'Oct', v: 56, display: '$13.3K' },
|
||||
{ m: 'Nov', v: 55, display: '$13.1K' }, { m: 'Dec', v: 57, display: '$13.6K' },
|
||||
{ m: 'Jan', v: 56, display: '$13.3K' }, { m: 'Feb', v: 58, display: '$13.8K' },
|
||||
{ m: 'Mar', v: 59, display: '$14.0K' }, { m: 'Apr', v: 60, display: '$14.3K' },
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
// ─── Metrics: Claims & Loss ──────────────────────────────────────────────────
|
||||
|
||||
const claimsMetrics: AnalyticsMetric[] = [
|
||||
{
|
||||
id: 'claims-count', domain: 'claims', label: 'Claims Opened', unit: '#',
|
||||
change: '-2', changeTone: 'positive', defaultChartType: 'bar',
|
||||
data12m: [
|
||||
{ m: 'May', v: 8, display: '8' }, { m: 'Jun', v: 6, display: '6' },
|
||||
{ m: 'Jul', v: 10, display: '10' }, { m: 'Aug', v: 7, display: '7' },
|
||||
{ m: 'Sep', v: 9, display: '9' }, { m: 'Oct', v: 8, display: '8' },
|
||||
{ m: 'Nov', v: 6, display: '6' }, { m: 'Dec', v: 5, display: '5' },
|
||||
{ m: 'Jan', v: 7, display: '7' }, { m: 'Feb', v: 8, display: '8' },
|
||||
{ m: 'Mar', v: 6, display: '6' }, { m: 'Apr', v: 5, display: '5' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'loss-ratio', domain: 'claims', label: 'Loss Ratio', unit: '%',
|
||||
change: '-3.1%', changeTone: 'positive', defaultChartType: 'line',
|
||||
data12m: [
|
||||
{ m: 'May', v: 66, display: '66%' }, { m: 'Jun', v: 64, display: '64%' },
|
||||
{ m: 'Jul', v: 70, display: '70%' }, { m: 'Aug', v: 67, display: '67%' },
|
||||
{ m: 'Sep', v: 65, display: '65%' }, { m: 'Oct', v: 68, display: '68%' },
|
||||
{ m: 'Nov', v: 72, display: '72%' }, { m: 'Dec', v: 65, display: '65%' },
|
||||
{ m: 'Jan', v: 63, display: '63%' }, { m: 'Feb', v: 60, display: '60%' },
|
||||
{ m: 'Mar', v: 58, display: '58%' }, { m: 'Apr', v: 57, display: '57%' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'avg-resolution-days', domain: 'claims', label: 'Avg Resolution', unit: 'days',
|
||||
change: '-4d', changeTone: 'positive', defaultChartType: 'line',
|
||||
data12m: [
|
||||
{ m: 'May', v: 38, display: '38d' }, { m: 'Jun', v: 35, display: '35d' },
|
||||
{ m: 'Jul', v: 40, display: '40d' }, { m: 'Aug', v: 36, display: '36d' },
|
||||
{ m: 'Sep', v: 34, display: '34d' }, { m: 'Oct', v: 32, display: '32d' },
|
||||
{ m: 'Nov', v: 30, display: '30d' }, { m: 'Dec', v: 28, display: '28d' },
|
||||
{ m: 'Jan', v: 31, display: '31d' }, { m: 'Feb', v: 29, display: '29d' },
|
||||
{ m: 'Mar', v: 27, display: '27d' }, { m: 'Apr', v: 26, display: '26d' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'reserve-trend', domain: 'claims', label: 'Reserve Trend', unit: '$',
|
||||
change: '-$45K', changeTone: 'positive', defaultChartType: 'area',
|
||||
data12m: [
|
||||
{ m: 'May', v: 75, display: '$380K' }, { m: 'Jun', v: 70, display: '$355K' },
|
||||
{ m: 'Jul', v: 80, display: '$405K' }, { m: 'Aug', v: 72, display: '$365K' },
|
||||
{ m: 'Sep', v: 68, display: '$345K' }, { m: 'Oct', v: 65, display: '$330K' },
|
||||
{ m: 'Nov', v: 60, display: '$304K' }, { m: 'Dec', v: 58, display: '$294K' },
|
||||
{ m: 'Jan', v: 62, display: '$314K' }, { m: 'Feb', v: 57, display: '$289K' },
|
||||
{ m: 'Mar', v: 55, display: '$279K' }, { m: 'Apr', v: 52, display: '$264K' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'claims-by-status', domain: 'claims', label: 'Claims by Status', unit: '#',
|
||||
change: '', changeTone: 'neutral', defaultChartType: 'bar',
|
||||
data12m: [
|
||||
{ m: 'Open', v: 3, display: '3' }, { m: 'Review', v: 3, display: '3' },
|
||||
{ m: 'Docs', v: 1, display: '1' }, { m: 'Approved', v: 2, display: '2' },
|
||||
{ m: 'Denied', v: 0, display: '0' }, { m: 'Closed', v: 1, display: '1' },
|
||||
{ m: '', v: 0, display: '' }, { m: '', v: 0, display: '' },
|
||||
{ m: '', v: 0, display: '' }, { m: '', v: 0, display: '' },
|
||||
{ m: '', v: 0, display: '' }, { m: '', v: 0, display: '' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'severity-trend', domain: 'claims', label: 'Avg Severity', unit: '$',
|
||||
change: '-$2.1K', changeTone: 'positive', defaultChartType: 'line',
|
||||
data12m: [
|
||||
{ m: 'May', v: 65, display: '$18.5K' }, { m: 'Jun', v: 60, display: '$17.1K' },
|
||||
{ m: 'Jul', v: 72, display: '$20.5K' }, { m: 'Aug', v: 63, display: '$17.9K' },
|
||||
{ m: 'Sep', v: 58, display: '$16.5K' }, { m: 'Oct', v: 55, display: '$15.7K' },
|
||||
{ m: 'Nov', v: 52, display: '$14.8K' }, { m: 'Dec', v: 50, display: '$14.2K' },
|
||||
{ m: 'Jan', v: 54, display: '$15.4K' }, { m: 'Feb', v: 48, display: '$13.7K' },
|
||||
{ m: 'Mar', v: 46, display: '$13.1K' }, { m: 'Apr', v: 44, display: '$12.5K' },
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
// ─── Metrics: Sales Pipeline ─────────────────────────────────────────────────
|
||||
|
||||
const pipelineMetrics: AnalyticsMetric[] = [
|
||||
{
|
||||
id: 'conversion-rate', domain: 'pipeline', label: 'Conversion Rate', unit: '%',
|
||||
change: '+2.8%', changeTone: 'positive', defaultChartType: 'line',
|
||||
data12m: [
|
||||
{ m: 'May', v: 28, display: '28%' }, { m: 'Jun', v: 30, display: '30%' },
|
||||
{ m: 'Jul', v: 27, display: '27%' }, { m: 'Aug', v: 32, display: '32%' },
|
||||
{ m: 'Sep', v: 31, display: '31%' }, { m: 'Oct', v: 33, display: '33%' },
|
||||
{ m: 'Nov', v: 30, display: '30%' }, { m: 'Dec', v: 35, display: '35%' },
|
||||
{ m: 'Jan', v: 34, display: '34%' }, { m: 'Feb', v: 36, display: '36%' },
|
||||
{ m: 'Mar', v: 38, display: '38%' }, { m: 'Apr', v: 39, display: '39%' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'pipeline-value', domain: 'pipeline', label: 'Pipeline Value', unit: '$',
|
||||
change: '+$820K', changeTone: 'positive', defaultChartType: 'area',
|
||||
data12m: [
|
||||
{ m: 'May', v: 42, display: '$3.8M' }, { m: 'Jun', v: 45, display: '$4.1M' },
|
||||
{ m: 'Jul', v: 40, display: '$3.6M' }, { m: 'Aug', v: 48, display: '$4.4M' },
|
||||
{ m: 'Sep', v: 52, display: '$4.7M' }, { m: 'Oct', v: 55, display: '$5.0M' },
|
||||
{ m: 'Nov', v: 50, display: '$4.5M' }, { m: 'Dec', v: 58, display: '$5.3M' },
|
||||
{ m: 'Jan', v: 56, display: '$5.1M' }, { m: 'Feb', v: 60, display: '$5.5M' },
|
||||
{ m: 'Mar', v: 65, display: '$5.9M' }, { m: 'Apr', v: 68, display: '$6.2M' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'lead-sources', domain: 'pipeline', label: 'Lead Sources', unit: '#',
|
||||
change: '+18%', changeTone: 'positive', defaultChartType: 'bar',
|
||||
data12m: [
|
||||
{ m: 'Referral', v: 85, display: '85' }, { m: 'Walk-in', v: 42, display: '42' },
|
||||
{ m: 'WhatsApp', v: 38, display: '38' }, { m: 'Google', v: 28, display: '28' },
|
||||
{ m: 'Instagram', v: 22, display: '22' }, { m: 'Facebook', v: 15, display: '15' },
|
||||
{ m: 'Partner', v: 12, display: '12' }, { m: 'Event', v: 8, display: '8' },
|
||||
{ m: 'Other', v: 6, display: '6' }, { m: '', v: 0, display: '' },
|
||||
{ m: '', v: 0, display: '' }, { m: '', v: 0, display: '' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'quote-to-bind-days', domain: 'pipeline', label: 'Quote-to-Bind', unit: 'days',
|
||||
change: '-2d', changeTone: 'positive', defaultChartType: 'line',
|
||||
data12m: [
|
||||
{ m: 'May', v: 18, display: '18d' }, { m: 'Jun', v: 16, display: '16d' },
|
||||
{ m: 'Jul', v: 20, display: '20d' }, { m: 'Aug', v: 15, display: '15d' },
|
||||
{ m: 'Sep', v: 14, display: '14d' }, { m: 'Oct', v: 13, display: '13d' },
|
||||
{ m: 'Nov', v: 15, display: '15d' }, { m: 'Dec', v: 12, display: '12d' },
|
||||
{ m: 'Jan', v: 14, display: '14d' }, { m: 'Feb', v: 11, display: '11d' },
|
||||
{ m: 'Mar', v: 10, display: '10d' }, { m: 'Apr', v: 9, display: '9d' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'agent-performance', domain: 'pipeline', label: 'Agent Performance', unit: '#',
|
||||
change: '', changeTone: 'neutral', defaultChartType: 'bar',
|
||||
data12m: [
|
||||
{ m: 'Ana R.', v: 88, display: '44 pólizas' }, { m: 'Marco V.', v: 72, display: '36 pólizas' },
|
||||
{ m: 'Carlos V.', v: 64, display: '32 pólizas' }, { m: 'María F.', v: 56, display: '28 pólizas' },
|
||||
{ m: 'Luis G.', v: 40, display: '20 pólizas' }, { m: '', v: 0, display: '' },
|
||||
{ m: '', v: 0, display: '' }, { m: '', v: 0, display: '' },
|
||||
{ m: '', v: 0, display: '' }, { m: '', v: 0, display: '' },
|
||||
{ m: '', v: 0, display: '' }, { m: '', v: 0, display: '' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'win-rate', domain: 'pipeline', label: 'Win Rate', unit: '%',
|
||||
change: '+3.5%', changeTone: 'positive', defaultChartType: 'line',
|
||||
data12m: [
|
||||
{ m: 'May', v: 35, display: '35%' }, { m: 'Jun', v: 38, display: '38%' },
|
||||
{ m: 'Jul', v: 33, display: '33%' }, { m: 'Aug', v: 40, display: '40%' },
|
||||
{ m: 'Sep', v: 42, display: '42%' }, { m: 'Oct', v: 41, display: '41%' },
|
||||
{ m: 'Nov', v: 39, display: '39%' }, { m: 'Dec', v: 44, display: '44%' },
|
||||
{ m: 'Jan', v: 43, display: '43%' }, { m: 'Feb', v: 46, display: '46%' },
|
||||
{ m: 'Mar', v: 48, display: '48%' }, { m: 'Apr', v: 50, display: '50%' },
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
// ─── Metrics: Customer & Service ─────────────────────────────────────────────
|
||||
|
||||
const serviceMetrics: AnalyticsMetric[] = [
|
||||
{
|
||||
id: 'support-volume', domain: 'service', label: 'Tickets Opened', unit: '#',
|
||||
change: '+15%', changeTone: 'negative', defaultChartType: 'bar',
|
||||
data12m: [
|
||||
{ m: 'May', v: 22, display: '22' }, { m: 'Jun', v: 25, display: '25' },
|
||||
{ m: 'Jul', v: 28, display: '28' }, { m: 'Aug', v: 24, display: '24' },
|
||||
{ m: 'Sep', v: 30, display: '30' }, { m: 'Oct', v: 27, display: '27' },
|
||||
{ m: 'Nov', v: 32, display: '32' }, { m: 'Dec', v: 20, display: '20' },
|
||||
{ m: 'Jan', v: 26, display: '26' }, { m: 'Feb', v: 29, display: '29' },
|
||||
{ m: 'Mar', v: 34, display: '34' }, { m: 'Apr', v: 36, display: '36' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'sla-compliance', domain: 'service', label: 'SLA Compliance', unit: '%',
|
||||
change: '+4%', changeTone: 'positive', defaultChartType: 'line',
|
||||
data12m: [
|
||||
{ m: 'May', v: 78, display: '78%' }, { m: 'Jun', v: 80, display: '80%' },
|
||||
{ m: 'Jul', v: 76, display: '76%' }, { m: 'Aug', v: 82, display: '82%' },
|
||||
{ m: 'Sep', v: 84, display: '84%' }, { m: 'Oct', v: 83, display: '83%' },
|
||||
{ m: 'Nov', v: 85, display: '85%' }, { m: 'Dec', v: 88, display: '88%' },
|
||||
{ m: 'Jan', v: 86, display: '86%' }, { m: 'Feb', v: 89, display: '89%' },
|
||||
{ m: 'Mar', v: 90, display: '90%' }, { m: 'Apr', v: 92, display: '92%' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'avg-response-time', domain: 'service', label: 'Avg Response Time', unit: 'hrs',
|
||||
change: '-1.2h', changeTone: 'positive', defaultChartType: 'line',
|
||||
data12m: [
|
||||
{ m: 'May', v: 72, display: '5.8h' }, { m: 'Jun', v: 68, display: '5.4h' },
|
||||
{ m: 'Jul', v: 75, display: '6.0h' }, { m: 'Aug', v: 65, display: '5.2h' },
|
||||
{ m: 'Sep', v: 60, display: '4.8h' }, { m: 'Oct', v: 55, display: '4.4h' },
|
||||
{ m: 'Nov', v: 52, display: '4.2h' }, { m: 'Dec', v: 48, display: '3.8h' },
|
||||
{ m: 'Jan', v: 50, display: '4.0h' }, { m: 'Feb', v: 45, display: '3.6h' },
|
||||
{ m: 'Mar', v: 42, display: '3.4h' }, { m: 'Apr', v: 40, display: '3.2h' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'retention-rate', domain: 'service', label: 'Retention Rate', unit: '%',
|
||||
change: '+1.2%', changeTone: 'positive', defaultChartType: 'area',
|
||||
data12m: [
|
||||
{ m: 'May', v: 84, display: '84%' }, { m: 'Jun', v: 85, display: '85%' },
|
||||
{ m: 'Jul', v: 86, display: '86%' }, { m: 'Aug', v: 87, display: '87%' },
|
||||
{ m: 'Sep', v: 88, display: '88%' }, { m: 'Oct', v: 88, display: '88%' },
|
||||
{ m: 'Nov', v: 87, display: '87%' }, { m: 'Dec', v: 89, display: '89%' },
|
||||
{ m: 'Jan', v: 90, display: '90%' }, { m: 'Feb', v: 90, display: '90%' },
|
||||
{ m: 'Mar', v: 91, display: '91%' }, { m: 'Apr', v: 91, display: '91%' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'nps-score', domain: 'service', label: 'NPS Score', unit: '#',
|
||||
change: '+5', changeTone: 'positive', defaultChartType: 'line',
|
||||
data12m: [
|
||||
{ m: 'May', v: 42, display: '42' }, { m: 'Jun', v: 44, display: '44' },
|
||||
{ m: 'Jul', v: 40, display: '40' }, { m: 'Aug', v: 46, display: '46' },
|
||||
{ m: 'Sep', v: 48, display: '48' }, { m: 'Oct', v: 50, display: '50' },
|
||||
{ m: 'Nov', v: 48, display: '48' }, { m: 'Dec', v: 52, display: '52' },
|
||||
{ m: 'Jan', v: 54, display: '54' }, { m: 'Feb', v: 55, display: '55' },
|
||||
{ m: 'Mar', v: 58, display: '58' }, { m: 'Apr', v: 60, display: '60' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'ticket-resolution-days', domain: 'service', label: 'Ticket Resolution', unit: 'days',
|
||||
change: '-0.8d', changeTone: 'positive', defaultChartType: 'line',
|
||||
data12m: [
|
||||
{ m: 'May', v: 55, display: '4.4d' }, { m: 'Jun', v: 52, display: '4.2d' },
|
||||
{ m: 'Jul', v: 58, display: '4.6d' }, { m: 'Aug', v: 50, display: '4.0d' },
|
||||
{ m: 'Sep', v: 48, display: '3.8d' }, { m: 'Oct', v: 45, display: '3.6d' },
|
||||
{ m: 'Nov', v: 42, display: '3.4d' }, { m: 'Dec', v: 40, display: '3.2d' },
|
||||
{ m: 'Jan', v: 43, display: '3.4d' }, { m: 'Feb', v: 38, display: '3.0d' },
|
||||
{ m: 'Mar', v: 36, display: '2.9d' }, { m: 'Apr', v: 34, display: '2.7d' },
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
// ─── Combined Export ─────────────────────────────────────────────────────────
|
||||
|
||||
export const ANALYTICS_METRICS: AnalyticsMetric[] = [
|
||||
...productionMetrics,
|
||||
...claimsMetrics,
|
||||
...pipelineMetrics,
|
||||
...serviceMetrics,
|
||||
]
|
||||
550
app/data/mock-claims.ts
Normal file
550
app/data/mock-claims.ts
Normal file
@@ -0,0 +1,550 @@
|
||||
// ── Claims Management — Types & Mock Data ───────────────────────────────────
|
||||
|
||||
export type CarrierStatus =
|
||||
| 'fnol_submitted'
|
||||
| 'acknowledged'
|
||||
| 'investigation'
|
||||
| 'documentation_pending'
|
||||
| 'reserved'
|
||||
| 'negotiation'
|
||||
| 'settlement_offered'
|
||||
| 'closed'
|
||||
|
||||
export type BrokerWorkflowStatus =
|
||||
| 'waiting_carrier'
|
||||
| 'waiting_insured_docs'
|
||||
| 'needs_escalation'
|
||||
| 'client_update_overdue'
|
||||
| 'ready_to_close'
|
||||
|
||||
export type ClaimPriority = 'critical' | 'high' | 'medium' | 'low'
|
||||
|
||||
export type PartyRole = 'insured' | 'adjuster' | 'carrier_contact' | 'handler' | 'attorney'
|
||||
|
||||
export interface ClaimParty {
|
||||
id: string
|
||||
role: PartyRole
|
||||
name: string
|
||||
initials: string
|
||||
email?: string
|
||||
phone?: string
|
||||
company?: string
|
||||
unreadComms: number
|
||||
}
|
||||
|
||||
export type TaskType = 'document' | 'communication' | 'escalation' | 'general'
|
||||
export type TaskStatus = 'open' | 'in_progress' | 'overdue' | 'done'
|
||||
|
||||
export interface ClaimTask {
|
||||
id: string
|
||||
title: string
|
||||
status: TaskStatus
|
||||
assignee: string
|
||||
dueDate: string
|
||||
slaPercent: number
|
||||
type: TaskType
|
||||
isSystemSuggested?: boolean
|
||||
dismissedUntil?: string | null
|
||||
}
|
||||
|
||||
export type CommType = 'email' | 'call' | 'note' | 'system'
|
||||
|
||||
export interface ClaimCommEntry {
|
||||
id: string
|
||||
type: CommType
|
||||
partyId: string
|
||||
from: string
|
||||
to?: string
|
||||
subject?: string
|
||||
body: string
|
||||
timestamp: string
|
||||
threadId?: string
|
||||
aiDigest?: string
|
||||
}
|
||||
|
||||
export type DocCategory = 'fnol' | 'evidence' | 'estimates' | 'correspondence' | 'settlement'
|
||||
|
||||
export interface ClaimDocument {
|
||||
id: string
|
||||
name: string
|
||||
category: DocCategory
|
||||
uploadedBy: string
|
||||
uploadedAt: string
|
||||
size: string
|
||||
required: boolean
|
||||
received: boolean
|
||||
}
|
||||
|
||||
export type IntakeStatus = 'not_sent' | 'sent' | 'in_progress' | 'completed'
|
||||
export type GeneratedFormStatus = 'draft' | 'ready_for_signature' | 'signed' | 'submitted'
|
||||
|
||||
export interface GeneratedForm {
|
||||
id: string
|
||||
carrierFormName: string
|
||||
carrier: string
|
||||
lob: string
|
||||
status: GeneratedFormStatus
|
||||
generatedAt: string
|
||||
signedAt: string | null
|
||||
}
|
||||
|
||||
export type FinancialType = 'reserve_change' | 'payment' | 'subrogation' | 'expense'
|
||||
|
||||
export interface ClaimFinancialEntry {
|
||||
id: string
|
||||
type: FinancialType
|
||||
date: string
|
||||
amount: number
|
||||
description: string
|
||||
annotation?: string
|
||||
}
|
||||
|
||||
export interface ClaimDetail {
|
||||
id: string
|
||||
customerId: string
|
||||
customerName: string
|
||||
policyId: string
|
||||
policyNumber: string
|
||||
carrier: string
|
||||
lob: string
|
||||
type: string
|
||||
carrierStatus: CarrierStatus
|
||||
workflowStatus: BrokerWorkflowStatus
|
||||
priority: ClaimPriority
|
||||
dateFiled: string
|
||||
daysOpen: number
|
||||
handler: string
|
||||
reservedAmount: number
|
||||
paidAmount: number
|
||||
parties: ClaimParty[]
|
||||
tasks: ClaimTask[]
|
||||
communications: ClaimCommEntry[]
|
||||
documents: ClaimDocument[]
|
||||
financials: ClaimFinancialEntry[]
|
||||
aiRecap: string
|
||||
aiRecapSourceCount: number
|
||||
keyDates: { label: string; date: string; done: boolean }[]
|
||||
reserveHistory: { date: string; amount: number; annotation: string }[]
|
||||
intakeToken: string | null
|
||||
intakeStatus: IntakeStatus
|
||||
intakeSentAt: string | null
|
||||
intakeCompletedAt: string | null
|
||||
generatedForms: GeneratedForm[]
|
||||
}
|
||||
|
||||
// ── Label Maps ──────────────────────────────────────────────────────────────
|
||||
|
||||
export const CARRIER_STATUS_LABELS: Record<CarrierStatus, string> = {
|
||||
fnol_submitted: 'FNOL Submitted',
|
||||
acknowledged: 'Acknowledged',
|
||||
investigation: 'Investigation',
|
||||
documentation_pending: 'Documentation Pending',
|
||||
reserved: 'Reserved',
|
||||
negotiation: 'Negotiation',
|
||||
settlement_offered: 'Settlement Offered',
|
||||
closed: 'Closed',
|
||||
}
|
||||
|
||||
export const WORKFLOW_STATUS_LABELS: Record<BrokerWorkflowStatus, string> = {
|
||||
waiting_carrier: 'Waiting on Carrier',
|
||||
waiting_insured_docs: 'Waiting on Insured Docs',
|
||||
needs_escalation: 'Needs Escalation',
|
||||
client_update_overdue: 'Client Update Overdue',
|
||||
ready_to_close: 'Ready to Close',
|
||||
}
|
||||
|
||||
export const PRIORITY_LABELS: Record<ClaimPriority, string> = {
|
||||
critical: 'Critical',
|
||||
high: 'High',
|
||||
medium: 'Medium',
|
||||
low: 'Low',
|
||||
}
|
||||
|
||||
export const TASK_STATUS_LABELS: Record<TaskStatus, string> = {
|
||||
open: 'Open',
|
||||
in_progress: 'In Progress',
|
||||
overdue: 'Overdue',
|
||||
done: 'Done',
|
||||
}
|
||||
|
||||
export const DOC_CATEGORY_LABELS: Record<DocCategory, string> = {
|
||||
fnol: 'FNOL & Notice',
|
||||
evidence: 'Evidence & Photos',
|
||||
estimates: 'Estimates & Appraisals',
|
||||
correspondence: 'Correspondence',
|
||||
settlement: 'Settlement',
|
||||
}
|
||||
|
||||
// ── Helpers ─────────────────────────────────────────────────────────────────
|
||||
|
||||
export function slaColor(percent: number): 'green' | 'amber' | 'red' {
|
||||
if (percent >= 100) return 'red'
|
||||
if (percent >= 75) return 'amber'
|
||||
return 'green'
|
||||
}
|
||||
|
||||
export function fmtClaimMoney(n: number): string {
|
||||
if (n >= 1_000_000) return '$' + (n / 1_000_000).toFixed(1) + 'M'
|
||||
if (n >= 1_000) return '$' + (n / 1_000).toFixed(1) + 'K'
|
||||
return '$' + n.toLocaleString()
|
||||
}
|
||||
|
||||
// ── Mock Data ───────────────────────────────────────────────────────────────
|
||||
|
||||
const clm0048: ClaimDetail = {
|
||||
id: 'CLM-0048',
|
||||
customerId: 'corp-hotel-pacifico',
|
||||
customerName: 'Hotel Pacífico S.A.',
|
||||
policyId: 'POL-2024-HP-001',
|
||||
policyNumber: 'PROP-2024-HP-001',
|
||||
carrier: 'ASSA',
|
||||
lob: 'General Risk',
|
||||
type: 'Fire damage — kitchen wing',
|
||||
carrierStatus: 'investigation',
|
||||
workflowStatus: 'waiting_carrier',
|
||||
priority: 'critical',
|
||||
dateFiled: '2026-04-05',
|
||||
daysOpen: 3,
|
||||
handler: 'Ana R.',
|
||||
reservedAmount: 128_000,
|
||||
paidAmount: 0,
|
||||
|
||||
parties: [
|
||||
{ id: 'p1', role: 'insured', name: 'Carlos Montero', initials: 'CM', email: 'cmontero@hotelpacifico.cr', phone: '+506 2643-1200', company: 'Hotel Pacífico S.A.', unreadComms: 2 },
|
||||
{ id: 'p2', role: 'adjuster', name: 'Roberto Méndez', initials: 'RM', email: 'rmendez@peritajes.cr', phone: '+506 8844-2200', company: 'Peritajes CR', unreadComms: 0 },
|
||||
{ id: 'p3', role: 'carrier_contact', name: 'Lucía Vargas', initials: 'LV', email: 'lvargas@assa.cr', phone: '+506 2222-5000', company: 'ASSA', unreadComms: 1 },
|
||||
{ id: 'p4', role: 'handler', name: 'Ana Ramírez', initials: 'AR', email: 'ana.r@seguros.cr', phone: '+506 8855-3300', unreadComms: 0 },
|
||||
],
|
||||
|
||||
tasks: [
|
||||
{ id: 't1', title: 'Upload police/fire report', status: 'overdue', assignee: 'Ana R.', dueDate: '2026-04-07', slaPercent: 110, type: 'document' },
|
||||
{ id: 't2', title: 'Follow up with adjuster — no site visit scheduled', status: 'open', assignee: 'Ana R.', dueDate: '2026-04-09', slaPercent: 60, type: 'communication' },
|
||||
{ id: 't3', title: 'Send initial status update to insured', status: 'open', assignee: 'Ana R.', dueDate: '2026-04-08', slaPercent: 85, type: 'communication' },
|
||||
{ id: 't4', title: 'Carrier non-response 3 days — escalate?', status: 'open', assignee: 'Ana R.', dueDate: '2026-04-08', slaPercent: 90, type: 'escalation', isSystemSuggested: true },
|
||||
{ id: 't5', title: 'Request preliminary damage estimate from adjuster', status: 'open', assignee: 'Ana R.', dueDate: '2026-04-12', slaPercent: 30, type: 'general' },
|
||||
{ id: 't6', title: 'Confirm policy coverage for fire peril', status: 'done', assignee: 'Ana R.', dueDate: '2026-04-06', slaPercent: 100, type: 'general' },
|
||||
],
|
||||
|
||||
communications: [
|
||||
{ id: 'c1', type: 'system', partyId: 'p4', from: 'System', body: 'Claim CLM-0048 created. FNOL submitted to ASSA.', timestamp: '2026-04-05T09:15:00' },
|
||||
{ id: 'c2', type: 'email', partyId: 'p1', from: 'Carlos Montero', to: 'Ana Ramírez', subject: 'Fire Incident — Hotel Pacífico Kitchen Wing', body: 'Ana, the fire started around 2am in the kitchen exhaust system. The fire department responded within 20 minutes. The kitchen wing sustained significant structural damage, and the adjacent dining area has smoke and water damage. We have temporarily closed the restaurant. Attached are initial photos from the scene. We need to process this claim urgently as we are losing revenue daily.', timestamp: '2026-04-05T10:30:00', threadId: 'th1' },
|
||||
{ id: 'c3', type: 'email', partyId: 'p4', from: 'Ana Ramírez', to: 'Lucía Vargas', subject: 'FNOL — Hotel Pacífico Fire Claim CLM-0048', body: 'Lucía, please find attached the FNOL for Hotel Pacífico. Fire damage to kitchen wing on April 5. Policy PROP-2024-HP-001 covers fire peril with $500K limit. Requesting immediate adjuster assignment. This is a high-value commercial client with business interruption exposure.', timestamp: '2026-04-05T11:45:00', threadId: 'th2' },
|
||||
{ id: 'c4', type: 'call', partyId: 'p1', from: 'Ana Ramírez', body: 'Called Carlos Montero to confirm FNOL was submitted. Discussed initial documentation needed: fire report, photos, inventory of damaged equipment. Carlos will send equipment list by end of day. Advised to keep all receipts for temporary repairs.', timestamp: '2026-04-05T14:00:00' },
|
||||
{ id: 'c5', type: 'email', partyId: 'p3', from: 'Lucía Vargas', to: 'Ana Ramírez', subject: 'RE: FNOL — Hotel Pacífico Fire Claim CLM-0048', body: 'Ana, claim received and logged under ASSA reference FI-2026-04412. We are assigning adjuster Roberto Méndez from Peritajes CR. He will contact you to schedule site inspection.', timestamp: '2026-04-06T09:00:00', threadId: 'th2', aiDigest: 'ASSA acknowledged claim as FI-2026-04412. Adjuster Roberto Méndez (Peritajes CR) assigned. Site inspection pending scheduling.' },
|
||||
{ id: 'c6', type: 'system', partyId: 'p4', from: 'System', body: 'Carrier status updated: FNOL Submitted → Acknowledged', timestamp: '2026-04-06T09:05:00' },
|
||||
{ id: 'c7', type: 'note', partyId: 'p4', from: 'Ana Ramírez', body: 'Reviewed policy. Fire peril covered. Business interruption sublimit $200K with 48h waiting period. Need to flag BI exposure to carrier early — hotel restaurant closure = significant daily revenue loss.', timestamp: '2026-04-06T10:30:00' },
|
||||
{ id: 'c8', type: 'email', partyId: 'p2', from: 'Roberto Méndez', to: 'Ana Ramírez', subject: 'Site Inspection — Hotel Pacífico', body: 'Good morning Ana. I have been assigned to inspect the fire damage at Hotel Pacífico. Could you coordinate with the insured for access? I am available Thursday or Friday this week.', timestamp: '2026-04-07T08:00:00', threadId: 'th3' },
|
||||
{ id: 'c9', type: 'email', partyId: 'p4', from: 'Ana Ramírez', to: 'Roberto Méndez', subject: 'RE: Site Inspection — Hotel Pacífico', body: 'Roberto, Thursday works. I will confirm with the hotel and send you the contact details. Please plan for approximately 3 hours — the damage area covers the kitchen wing and adjacent dining area.', timestamp: '2026-04-07T09:15:00', threadId: 'th3' },
|
||||
{ id: 'c10', type: 'system', partyId: 'p4', from: 'System', body: 'Carrier status updated: Acknowledged → Investigation', timestamp: '2026-04-07T10:00:00' },
|
||||
{ id: 'c11', type: 'email', partyId: 'p1', from: 'Carlos Montero', to: 'Ana Ramírez', subject: 'RE: Fire Incident — Equipment Inventory', body: 'Ana, attached is the damaged equipment inventory as requested. Total estimated replacement value approximately $85,000. Also including photos of the structural damage to the exhaust hood and ceiling. The fire inspector\'s preliminary report should be ready by Friday.', timestamp: '2026-04-07T16:00:00', threadId: 'th1', aiDigest: 'Insured provided equipment inventory ($85K estimated). Structural damage photos attached. Fire inspector report expected Friday.' },
|
||||
{ id: 'c12', type: 'note', partyId: 'p4', from: 'Ana Ramírez', body: 'Equipment inventory received — $85K. Combined with structural estimates, total exposure could exceed $150K. May need to flag for reserve increase once adjuster report comes in. BI claim will be separate — need to start documenting daily revenue loss.', timestamp: '2026-04-08T08:30:00' },
|
||||
],
|
||||
|
||||
documents: [
|
||||
{ id: 'd1', name: 'FNOL-CLM0048.pdf', category: 'fnol', uploadedBy: 'Ana R.', uploadedAt: '2026-04-05', size: '245 KB', required: true, received: true },
|
||||
{ id: 'd2', name: 'Policy-Declarations-HP.pdf', category: 'fnol', uploadedBy: 'Ana R.', uploadedAt: '2026-04-05', size: '1.2 MB', required: true, received: true },
|
||||
{ id: 'd3', name: 'Initial-Photos-Kitchen.zip', category: 'evidence', uploadedBy: 'Carlos Montero', uploadedAt: '2026-04-05', size: '18.4 MB', required: true, received: true },
|
||||
{ id: 'd4', name: 'Equipment-Inventory.xlsx', category: 'estimates', uploadedBy: 'Carlos Montero', uploadedAt: '2026-04-07', size: '89 KB', required: true, received: true },
|
||||
{ id: 'd5', name: 'Structural-Damage-Photos.zip', category: 'evidence', uploadedBy: 'Carlos Montero', uploadedAt: '2026-04-07', size: '24.1 MB', required: false, received: true },
|
||||
{ id: 'd6', name: 'ASSA-Acknowledgment-FI202604412.pdf', category: 'correspondence', uploadedBy: 'Ana R.', uploadedAt: '2026-04-06', size: '156 KB', required: false, received: true },
|
||||
{ id: 'd7', name: 'Fire-Inspector-Report.pdf', category: 'evidence', uploadedBy: '', uploadedAt: '', size: '', required: true, received: false },
|
||||
{ id: 'd8', name: 'Adjuster-Preliminary-Estimate.pdf', category: 'estimates', uploadedBy: '', uploadedAt: '', size: '', required: true, received: false },
|
||||
{ id: 'd9', name: 'Business-Interruption-Docs.pdf', category: 'estimates', uploadedBy: '', uploadedAt: '', size: '', required: true, received: false },
|
||||
{ id: 'd10', name: 'Police-Fire-Report.pdf', category: 'fnol', uploadedBy: '', uploadedAt: '', size: '', required: true, received: false },
|
||||
],
|
||||
|
||||
financials: [
|
||||
{ id: 'f1', type: 'reserve_change', date: '2026-04-05', amount: 128_000, description: 'Initial reserve set', annotation: 'Based on preliminary damage assessment and policy limits' },
|
||||
{ id: 'f2', type: 'expense', date: '2026-04-06', amount: 1_500, description: 'Adjuster assignment fee — Peritajes CR', annotation: 'Standard commercial property rate' },
|
||||
{ id: 'f3', type: 'expense', date: '2026-04-07', amount: 450, description: 'Emergency structural assessment', annotation: 'Required for safety clearance' },
|
||||
],
|
||||
|
||||
aiRecap: 'Siniestro por incendio en el ala de cocina del Hotel Pacífico, reportado el 5 de abril de 2026. El fuego se originó en el sistema de extracción de la cocina alrededor de las 2am. Los bomberos respondieron en 20 minutos. Daños significativos a la estructura de la cocina y daños por humo y agua en el comedor adyacente. El restaurante está cerrado temporalmente.\n\nASSA acusó recibo el 6 de abril (ref. FI-2026-04412) y asignó al ajustador Roberto Méndez de Peritajes CR. La inspección del sitio está pendiente de programar para esta semana.\n\nEl asegurado proporcionó un inventario de equipos dañados valorado en ~$85K. La exposición total podría superar $150K una vez que se complete la evaluación estructural. Hay exposición adicional por interrupción de negocio (sublímite de $200K con período de espera de 48h).\n\nPendiente: reporte del inspector de bomberos (esperado viernes), estimación preliminar del ajustador, documentación de pérdida de ingresos diarios para reclamo de BI.',
|
||||
aiRecapSourceCount: 14,
|
||||
|
||||
keyDates: [
|
||||
{ label: 'FNOL Filed', date: '2026-04-05', done: true },
|
||||
{ label: 'Carrier Acknowledged', date: '2026-04-06', done: true },
|
||||
{ label: 'Adjuster Assigned', date: '2026-04-06', done: true },
|
||||
{ label: 'Investigation Started', date: '2026-04-07', done: true },
|
||||
{ label: 'Site Inspection', date: '2026-04-10', done: false },
|
||||
{ label: 'Preliminary Estimate', date: '', done: false },
|
||||
{ label: 'Reserve Review', date: '', done: false },
|
||||
{ label: 'Settlement', date: '', done: false },
|
||||
],
|
||||
|
||||
reserveHistory: [
|
||||
{ date: '2026-04-05', amount: 128_000, annotation: 'Initial reserve — fire damage assessment pending' },
|
||||
],
|
||||
intakeToken: 'tk_hp_048_a3f1',
|
||||
intakeStatus: 'completed',
|
||||
intakeSentAt: '2026-04-05T14:30:00Z',
|
||||
intakeCompletedAt: '2026-04-06T09:12:00Z',
|
||||
generatedForms: [
|
||||
{ id: 'gf-048-1', carrierFormName: 'Aviso de Pérdida — ASSA', carrier: 'ASSA', lob: 'General Risk', status: 'ready_for_signature', generatedAt: '2026-04-06T10:00:00Z', signedAt: null },
|
||||
],
|
||||
}
|
||||
|
||||
const clm0047: ClaimDetail = {
|
||||
id: 'CLM-0047',
|
||||
customerId: 'corp-empresa-abc',
|
||||
customerName: 'Empresa ABC S.A.',
|
||||
policyId: 'POL-2024-ABC-FLEET',
|
||||
policyNumber: 'AUTO-2024-FLEET-007',
|
||||
carrier: 'Qualitas',
|
||||
lob: 'Auto',
|
||||
type: 'Auto collision — fleet vehicle',
|
||||
carrierStatus: 'documentation_pending',
|
||||
workflowStatus: 'waiting_insured_docs',
|
||||
priority: 'high',
|
||||
dateFiled: '2026-04-03',
|
||||
daysOpen: 5,
|
||||
handler: 'Marco V.',
|
||||
reservedAmount: 14_200,
|
||||
paidAmount: 0,
|
||||
|
||||
parties: [
|
||||
{ id: 'p1', role: 'insured', name: 'Fernando Solano', initials: 'FS', email: 'fsolano@empresaabc.cr', phone: '+506 2255-8800', company: 'Empresa ABC S.A.', unreadComms: 0 },
|
||||
{ id: 'p2', role: 'adjuster', name: 'Patricia Ulate', initials: 'PU', email: 'pulate@qualitas.cr', phone: '+506 2233-4400', company: 'Qualitas', unreadComms: 1 },
|
||||
{ id: 'p3', role: 'carrier_contact', name: 'Diego Mora', initials: 'DM', email: 'dmora@qualitas.cr', phone: '+506 2233-4401', company: 'Qualitas', unreadComms: 0 },
|
||||
{ id: 'p4', role: 'handler', name: 'Marco Vargas', initials: 'MV', email: 'marco.v@seguros.cr', phone: '+506 8866-4400', unreadComms: 0 },
|
||||
],
|
||||
|
||||
tasks: [
|
||||
{ id: 't1', title: 'Obtain police report from insured', status: 'overdue', assignee: 'Marco V.', dueDate: '2026-04-06', slaPercent: 120, type: 'document' },
|
||||
{ id: 't2', title: 'Submit repair estimates to carrier', status: 'open', assignee: 'Marco V.', dueDate: '2026-04-10', slaPercent: 50, type: 'document' },
|
||||
{ id: 't3', title: 'Confirm driver was authorized fleet operator', status: 'open', assignee: 'Marco V.', dueDate: '2026-04-09', slaPercent: 65, type: 'general' },
|
||||
{ id: 't4', title: 'Send client status update — 5 days no communication', status: 'open', assignee: 'Marco V.', dueDate: '2026-04-08', slaPercent: 92, type: 'communication', isSystemSuggested: true },
|
||||
{ id: 't5', title: 'Request adjuster photos from body shop', status: 'done', assignee: 'Marco V.', dueDate: '2026-04-05', slaPercent: 100, type: 'general' },
|
||||
],
|
||||
|
||||
communications: [
|
||||
{ id: 'c1', type: 'system', partyId: 'p4', from: 'System', body: 'Claim CLM-0047 created. FNOL submitted to Qualitas.', timestamp: '2026-04-03T08:30:00' },
|
||||
{ id: 'c2', type: 'email', partyId: 'p1', from: 'Fernando Solano', to: 'Marco Vargas', subject: 'Fleet Vehicle Accident — Unit 07', body: 'Marco, one of our delivery trucks (Unit 07, plates SJO-7744) was involved in a collision yesterday on Ruta 27 near Escazú. The driver (José Mora) is fine but the front end is heavily damaged. The vehicle was towed to Taller Central in La Uruca. Police were called and a report was filed.', timestamp: '2026-04-03T09:00:00', threadId: 'th1' },
|
||||
{ id: 'c3', type: 'email', partyId: 'p4', from: 'Marco Vargas', to: 'Diego Mora', subject: 'FNOL — Empresa ABC Fleet Collision CLM-0047', body: 'Diego, submitting FNOL for fleet collision. Policy AUTO-2024-FLEET-007, Unit 07 (SJO-7744). Collision on Ruta 27, 2 April. Vehicle at Taller Central, La Uruca. Police report filed. Requesting adjuster assignment.', timestamp: '2026-04-03T10:15:00', threadId: 'th2' },
|
||||
{ id: 'c4', type: 'email', partyId: 'p3', from: 'Diego Mora', to: 'Marco Vargas', subject: 'RE: FNOL — Empresa ABC Fleet Collision', body: 'Marco, claim received under Qualitas ref QAC-2026-1182. Adjuster Patricia Ulate will handle. She will coordinate directly with the body shop for inspection. Please provide the police report and driver authorization docs at your earliest convenience.', timestamp: '2026-04-04T08:00:00', threadId: 'th2', aiDigest: 'Qualitas acknowledged as QAC-2026-1182. Adjuster Patricia Ulate assigned. Requesting police report and driver authorization docs.' },
|
||||
{ id: 'c5', type: 'call', partyId: 'p2', from: 'Marco Vargas', body: 'Called Patricia Ulate. She confirmed she will visit Taller Central on Monday for inspection. Needs police report before she can proceed with estimate. Estimated repair range $12K–$16K based on initial description.', timestamp: '2026-04-04T14:30:00' },
|
||||
{ id: 'c6', type: 'system', partyId: 'p4', from: 'System', body: 'Carrier status updated: Acknowledged → Documentation Pending', timestamp: '2026-04-05T09:00:00' },
|
||||
{ id: 'c7', type: 'note', partyId: 'p4', from: 'Marco Vargas', body: 'Insured has not yet sent police report. Called Fernando twice, went to voicemail. Will try again tomorrow. Fleet policy requires authorized driver confirmation — need to get signed driver roster from HR department.', timestamp: '2026-04-06T16:00:00' },
|
||||
{ id: 'c8', type: 'email', partyId: 'p2', from: 'Patricia Ulate', to: 'Marco Vargas', subject: 'Body Shop Photos — Unit 07', body: 'Marco, I visited Taller Central this morning. Photos attached. Front bumper, hood, radiator, and right fender all need replacement. Frame appears straight — no structural damage. Preliminary estimate pending receipt of police report to confirm fault assignment.', timestamp: '2026-04-07T11:00:00', threadId: 'th3', aiDigest: 'Adjuster inspected vehicle. Damage: bumper, hood, radiator, right fender. No structural damage. Estimate pending police report for fault assignment.' },
|
||||
],
|
||||
|
||||
documents: [
|
||||
{ id: 'd1', name: 'FNOL-CLM0047.pdf', category: 'fnol', uploadedBy: 'Marco V.', uploadedAt: '2026-04-03', size: '198 KB', required: true, received: true },
|
||||
{ id: 'd2', name: 'Fleet-Policy-Declarations.pdf', category: 'fnol', uploadedBy: 'Marco V.', uploadedAt: '2026-04-03', size: '890 KB', required: true, received: true },
|
||||
{ id: 'd3', name: 'Accident-Scene-Photos.zip', category: 'evidence', uploadedBy: 'Fernando Solano', uploadedAt: '2026-04-03', size: '12.6 MB', required: true, received: true },
|
||||
{ id: 'd4', name: 'Body-Shop-Inspection-Photos.zip', category: 'evidence', uploadedBy: 'Patricia Ulate', uploadedAt: '2026-04-07', size: '8.9 MB', required: false, received: true },
|
||||
{ id: 'd5', name: 'Police-Report.pdf', category: 'fnol', uploadedBy: '', uploadedAt: '', size: '', required: true, received: false },
|
||||
{ id: 'd6', name: 'Driver-Authorization-Roster.pdf', category: 'fnol', uploadedBy: '', uploadedAt: '', size: '', required: true, received: false },
|
||||
{ id: 'd7', name: 'Repair-Estimate-TallerCentral.pdf', category: 'estimates', uploadedBy: '', uploadedAt: '', size: '', required: true, received: false },
|
||||
],
|
||||
|
||||
financials: [
|
||||
{ id: 'f1', type: 'reserve_change', date: '2026-04-03', amount: 14_200, description: 'Initial reserve set', annotation: 'Based on typical fleet collision range' },
|
||||
{ id: 'f2', type: 'expense', date: '2026-04-03', amount: 85, description: 'Towing — Ruta 27 to Taller Central' },
|
||||
],
|
||||
|
||||
aiRecap: 'Colisión de vehículo de flota (Unidad 07, SJO-7744) de Empresa ABC en Ruta 27 cerca de Escazú el 2 de abril. El conductor José Mora no resultó herido. El vehículo fue remolcado a Taller Central en La Uruca.\n\nQualitas acusó recibo (ref QAC-2026-1182) y asignó a la ajustadora Patricia Ulate. Ella inspeccionó el vehículo el 7 de abril — daños en bumper, capó, radiador y guardafango derecho. Sin daño estructural. Estimación pendiente del reporte policial para determinar culpa.\n\nBloqueadores: el asegurado no ha proporcionado el reporte policial (vencido) ni la documentación de autorización del conductor. Se han hecho múltiples intentos de contacto sin respuesta.',
|
||||
aiRecapSourceCount: 9,
|
||||
|
||||
keyDates: [
|
||||
{ label: 'FNOL Filed', date: '2026-04-03', done: true },
|
||||
{ label: 'Carrier Acknowledged', date: '2026-04-04', done: true },
|
||||
{ label: 'Adjuster Assigned', date: '2026-04-04', done: true },
|
||||
{ label: 'Vehicle Inspection', date: '2026-04-07', done: true },
|
||||
{ label: 'Police Report Due', date: '2026-04-06', done: false },
|
||||
{ label: 'Repair Estimate', date: '', done: false },
|
||||
{ label: 'Settlement', date: '', done: false },
|
||||
],
|
||||
|
||||
reserveHistory: [
|
||||
{ date: '2026-04-03', amount: 14_200, annotation: 'Initial reserve — typical fleet collision' },
|
||||
],
|
||||
intakeToken: 'tk_abc_047_b7e2',
|
||||
intakeStatus: 'in_progress',
|
||||
intakeSentAt: '2026-04-04T11:00:00Z',
|
||||
intakeCompletedAt: null,
|
||||
generatedForms: [],
|
||||
}
|
||||
|
||||
const clm0043: ClaimDetail = {
|
||||
id: 'CLM-0043',
|
||||
customerId: 'corp-supermercado-tico',
|
||||
customerName: 'Supermercado Tico S.A.',
|
||||
policyId: 'POL-2023-ST-GL',
|
||||
policyNumber: 'GL-2023-ST-001',
|
||||
carrier: 'INS',
|
||||
lob: 'General Risk',
|
||||
type: 'Liability — customer injury in store',
|
||||
carrierStatus: 'negotiation',
|
||||
workflowStatus: 'client_update_overdue',
|
||||
priority: 'high',
|
||||
dateFiled: '2026-03-17',
|
||||
daysOpen: 22,
|
||||
handler: 'Ana R.',
|
||||
reservedAmount: 45_000,
|
||||
paidAmount: 0,
|
||||
|
||||
parties: [
|
||||
{ id: 'p1', role: 'insured', name: 'Jorge Calvo', initials: 'JC', email: 'jcalvo@supertico.cr', phone: '+506 2244-9900', company: 'Supermercado Tico S.A.', unreadComms: 3 },
|
||||
{ id: 'p2', role: 'adjuster', name: 'Sandra Pérez', initials: 'SP', email: 'sperez@ins.go.cr', phone: '+506 2287-6600', company: 'INS', unreadComms: 0 },
|
||||
{ id: 'p3', role: 'carrier_contact', name: 'Miguel Hernández', initials: 'MH', email: 'mhernandez@ins.go.cr', phone: '+506 2287-6601', company: 'INS', unreadComms: 0 },
|
||||
{ id: 'p4', role: 'handler', name: 'Ana Ramírez', initials: 'AR', email: 'ana.r@seguros.cr', phone: '+506 8855-3300', unreadComms: 0 },
|
||||
{ id: 'p5', role: 'attorney', name: 'Lic. Gabriela Rojas', initials: 'GR', email: 'grojas@bufeterojas.cr', phone: '+506 2255-1100', company: 'Bufete Rojas & Asociados', unreadComms: 1 },
|
||||
],
|
||||
|
||||
tasks: [
|
||||
{ id: 't1', title: 'Send client status update — 8 days overdue', status: 'overdue', assignee: 'Ana R.', dueDate: '2026-03-31', slaPercent: 140, type: 'communication' },
|
||||
{ id: 't2', title: 'Review settlement offer from INS — $38K proposed', status: 'open', assignee: 'Ana R.', dueDate: '2026-04-10', slaPercent: 55, type: 'general' },
|
||||
{ id: 't3', title: 'Coordinate with attorney on counter-offer strategy', status: 'in_progress', assignee: 'Ana R.', dueDate: '2026-04-09', slaPercent: 70, type: 'communication' },
|
||||
{ id: 't4', title: 'Upload updated medical records from claimant', status: 'open', assignee: 'Ana R.', dueDate: '2026-04-11', slaPercent: 40, type: 'document' },
|
||||
{ id: 't5', title: 'Client update overdue — escalate?', status: 'open', assignee: 'Ana R.', dueDate: '2026-04-08', slaPercent: 100, type: 'escalation', isSystemSuggested: true },
|
||||
{ id: 't6', title: 'File FNOL with carrier', status: 'done', assignee: 'Ana R.', dueDate: '2026-03-17', slaPercent: 100, type: 'general' },
|
||||
{ id: 't7', title: 'Obtain incident report from store manager', status: 'done', assignee: 'Ana R.', dueDate: '2026-03-19', slaPercent: 100, type: 'document' },
|
||||
{ id: 't8', title: 'Upload CCTV footage', status: 'done', assignee: 'Ana R.', dueDate: '2026-03-22', slaPercent: 100, type: 'document' },
|
||||
],
|
||||
|
||||
communications: [
|
||||
{ id: 'c1', type: 'system', partyId: 'p4', from: 'System', body: 'Claim CLM-0043 created. FNOL submitted to INS.', timestamp: '2026-03-17T10:00:00' },
|
||||
{ id: 'c2', type: 'email', partyId: 'p1', from: 'Jorge Calvo', to: 'Ana Ramírez', subject: 'Customer Slip and Fall — Produce Section', body: 'Ana, we had an incident on March 16. A customer (Marta Solís) slipped on a wet floor in the produce section and sustained a hip injury. She was taken to Hospital CIMA by ambulance. She has retained an attorney. We have CCTV footage and the incident report from our store manager.', timestamp: '2026-03-17T10:30:00', threadId: 'th1' },
|
||||
{ id: 'c3', type: 'email', partyId: 'p4', from: 'Ana Ramírez', to: 'Miguel Hernández', subject: 'FNOL — Supermercado Tico Liability Claim CLM-0043', body: 'Miguel, submitting FNOL for a general liability claim. Customer slip and fall injury in the produce section. Incident March 16. Claimant retained attorney. We have CCTV footage and incident report. Policy GL-2023-ST-001 with $1M per-occurrence limit.', timestamp: '2026-03-17T11:30:00', threadId: 'th2' },
|
||||
{ id: 'c4', type: 'email', partyId: 'p3', from: 'Miguel Hernández', to: 'Ana Ramírez', subject: 'RE: FNOL — Supermercado Tico Liability', body: 'Ana, claim acknowledged under INS ref LB-2026-0388. Sandra Pérez assigned as adjuster. Please forward CCTV footage and incident report. Given attorney involvement, we are fast-tracking investigation.', timestamp: '2026-03-18T09:00:00', threadId: 'th2', aiDigest: 'INS acknowledged claim as LB-2026-0388. Adjuster Sandra Pérez assigned. Fast-tracking due to attorney involvement. Requesting CCTV and incident report.' },
|
||||
{ id: 'c5', type: 'call', partyId: 'p5', from: 'Lic. Gabriela Rojas', body: 'Incoming call from claimant\'s attorney. Informed that Marta Solís underwent hip surgery. Medical expenses to date approximately $28K. Attorney indicated client is seeking $50K total including pain and suffering. Requested we expedite the claim process.', timestamp: '2026-03-20T14:00:00' },
|
||||
{ id: 'c6', type: 'note', partyId: 'p4', from: 'Ana Ramírez', body: 'Attorney demanding $50K. Medical expenses $28K. Need to review CCTV carefully — if the wet floor sign was properly placed, liability may be disputed. Sent CCTV to INS adjuster for review.', timestamp: '2026-03-20T15:30:00' },
|
||||
{ id: 'c7', type: 'system', partyId: 'p4', from: 'System', body: 'Carrier status updated: Investigation → Reserved. Reserve set at $45,000.', timestamp: '2026-03-25T09:00:00' },
|
||||
{ id: 'c8', type: 'email', partyId: 'p2', from: 'Sandra Pérez', to: 'Ana Ramírez', subject: 'Investigation Update — CLM-0043', body: 'Ana, we reviewed the CCTV footage. The wet floor sign was visible but positioned slightly away from the actual wet area. This creates partial liability exposure. We are setting reserve at $45K. Our recommendation is to negotiate settlement in the $35K–$40K range to avoid litigation costs.', timestamp: '2026-03-25T10:00:00', threadId: 'th4', aiDigest: 'INS reviewed CCTV. Wet floor sign was present but mispositioned — partial liability. Reserve set $45K. Recommends settling $35K–$40K to avoid litigation costs.' },
|
||||
{ id: 'c9', type: 'email', partyId: 'p4', from: 'Ana Ramírez', to: 'Jorge Calvo', subject: 'Claim Update — Liability Assessment', body: 'Jorge, INS has completed their initial investigation. The CCTV review indicates the wet floor sign, while present, was not optimally positioned. This creates some liability exposure. INS is recommending a negotiated settlement. I will discuss strategy with you once we have a formal offer from the carrier. Please call me at your convenience to discuss.', timestamp: '2026-03-25T14:00:00', threadId: 'th5' },
|
||||
{ id: 'c10', type: 'email', partyId: 'p3', from: 'Miguel Hernández', to: 'Ana Ramírez', subject: 'Settlement Offer — CLM-0043', body: 'Ana, INS is prepared to offer $38,000 to settle this claim. This includes medical expenses ($28K) plus $10K for pain and suffering. Please communicate this to the insured and the claimant\'s attorney. We believe this is a fair offer given the shared liability circumstances.', timestamp: '2026-04-01T09:00:00', threadId: 'th6', aiDigest: 'INS offering $38K settlement ($28K medical + $10K pain/suffering). Considers shared liability. Awaiting broker/attorney response.' },
|
||||
{ id: 'c11', type: 'system', partyId: 'p4', from: 'System', body: 'Carrier status updated: Reserved → Negotiation', timestamp: '2026-04-01T09:05:00' },
|
||||
{ id: 'c12', type: 'call', partyId: 'p5', from: 'Ana Ramírez', body: 'Called attorney Gabriela Rojas to discuss $38K offer. Attorney says client won\'t accept less than $45K. Agreed to prepare counter-proposal for $42K based on additional medical documentation showing ongoing rehabilitation needs.', timestamp: '2026-04-02T11:00:00' },
|
||||
],
|
||||
|
||||
documents: [
|
||||
{ id: 'd1', name: 'FNOL-CLM0043.pdf', category: 'fnol', uploadedBy: 'Ana R.', uploadedAt: '2026-03-17', size: '212 KB', required: true, received: true },
|
||||
{ id: 'd2', name: 'GL-Policy-Declarations.pdf', category: 'fnol', uploadedBy: 'Ana R.', uploadedAt: '2026-03-17', size: '1.1 MB', required: true, received: true },
|
||||
{ id: 'd3', name: 'Incident-Report-StoreManager.pdf', category: 'evidence', uploadedBy: 'Jorge Calvo', uploadedAt: '2026-03-18', size: '340 KB', required: true, received: true },
|
||||
{ id: 'd4', name: 'CCTV-Footage-ProduceSection.mp4', category: 'evidence', uploadedBy: 'Jorge Calvo', uploadedAt: '2026-03-19', size: '245 MB', required: true, received: true },
|
||||
{ id: 'd5', name: 'Medical-Records-MartaSolis.pdf', category: 'evidence', uploadedBy: 'Lic. Gabriela Rojas', uploadedAt: '2026-03-21', size: '4.2 MB', required: true, received: true },
|
||||
{ id: 'd6', name: 'INS-Investigation-Report.pdf', category: 'correspondence', uploadedBy: 'Sandra Pérez', uploadedAt: '2026-03-25', size: '890 KB', required: false, received: true },
|
||||
{ id: 'd7', name: 'Settlement-Offer-38K.pdf', category: 'settlement', uploadedBy: 'Ana R.', uploadedAt: '2026-04-01', size: '156 KB', required: false, received: true },
|
||||
{ id: 'd8', name: 'Updated-Medical-Records.pdf', category: 'evidence', uploadedBy: '', uploadedAt: '', size: '', required: true, received: false },
|
||||
{ id: 'd9', name: 'Counter-Offer-Response.pdf', category: 'settlement', uploadedBy: '', uploadedAt: '', size: '', required: true, received: false },
|
||||
{ id: 'd10', name: 'Signed-Release-Form.pdf', category: 'settlement', uploadedBy: '', uploadedAt: '', size: '', required: true, received: false },
|
||||
],
|
||||
|
||||
financials: [
|
||||
{ id: 'f1', type: 'reserve_change', date: '2026-03-17', amount: 30_000, description: 'Initial reserve set', annotation: 'Preliminary — slip and fall with attorney involvement' },
|
||||
{ id: 'f2', type: 'reserve_change', date: '2026-03-25', amount: 45_000, description: 'Reserve increased', annotation: 'CCTV review shows partial liability — increased from $30K' },
|
||||
{ id: 'f3', type: 'expense', date: '2026-03-18', amount: 200, description: 'Incident scene documentation' },
|
||||
{ id: 'f4', type: 'expense', date: '2026-03-25', amount: 750, description: 'Legal consultation — liability assessment' },
|
||||
],
|
||||
|
||||
aiRecap: 'Reclamo de responsabilidad civil por caída de cliente (Marta Solís) en la sección de productos del Supermercado Tico el 16 de marzo. La clienta sufrió una lesión de cadera que requirió cirugía. Ha contratado abogada (Lic. Gabriela Rojas).\n\nINS completó la investigación el 25 de marzo. La revisión del CCTV muestra que el letrero de piso mojado estaba presente pero mal posicionado — esto crea responsabilidad parcial. La reserva se incrementó de $30K a $45K.\n\nINS ofreció $38K para liquidar ($28K gastos médicos + $10K dolor y sufrimiento). La abogada de la reclamante rechazó — exige mínimo $45K. Se está preparando contraoferta de $42K basada en documentación médica adicional que muestra necesidades de rehabilitación continua.\n\nACCIÓN REQUERIDA: Actualización al cliente pendiente hace 8 días. El asegurado (Jorge Calvo) no ha sido informado del estado de la negociación.',
|
||||
aiRecapSourceCount: 18,
|
||||
|
||||
keyDates: [
|
||||
{ label: 'Incident Date', date: '2026-03-16', done: true },
|
||||
{ label: 'FNOL Filed', date: '2026-03-17', done: true },
|
||||
{ label: 'Carrier Acknowledged', date: '2026-03-18', done: true },
|
||||
{ label: 'Investigation Complete', date: '2026-03-25', done: true },
|
||||
{ label: 'Reserve Set ($45K)', date: '2026-03-25', done: true },
|
||||
{ label: 'Settlement Offered ($38K)', date: '2026-04-01', done: true },
|
||||
{ label: 'Counter-Offer Deadline', date: '2026-04-10', done: false },
|
||||
{ label: 'Settlement or Litigation', date: '', done: false },
|
||||
],
|
||||
|
||||
reserveHistory: [
|
||||
{ date: '2026-03-17', amount: 30_000, annotation: 'Initial reserve — slip and fall with legal representation' },
|
||||
{ date: '2026-03-25', amount: 45_000, annotation: 'Increased after CCTV review — partial liability exposure confirmed' },
|
||||
],
|
||||
intakeToken: 'tk_st_043_c9d4',
|
||||
intakeStatus: 'completed',
|
||||
intakeSentAt: '2026-03-17T16:00:00Z',
|
||||
intakeCompletedAt: '2026-03-18T08:45:00Z',
|
||||
generatedForms: [
|
||||
{ id: 'gf-043-1', carrierFormName: 'Aviso de Pérdida — Mapfre', carrier: 'Mapfre', lob: 'General Risk', status: 'submitted', generatedAt: '2026-03-18T10:00:00Z', signedAt: '2026-03-19T14:30:00Z' },
|
||||
],
|
||||
}
|
||||
|
||||
const clm0045: ClaimDetail = {
|
||||
id: 'CLM-0045',
|
||||
customerId: 'corp-clinica-sanjose',
|
||||
customerName: 'Clínica San José',
|
||||
policyId: 'POL-2024-CSJ-LIFE',
|
||||
policyNumber: 'LIFE-2024-CSJ-001',
|
||||
carrier: 'Pan-American Life',
|
||||
lob: 'Life',
|
||||
type: 'Surgery pre-authorization',
|
||||
carrierStatus: 'reserved',
|
||||
workflowStatus: 'waiting_carrier',
|
||||
priority: 'high',
|
||||
dateFiled: '2026-03-27',
|
||||
daysOpen: 12,
|
||||
handler: 'Ana R.',
|
||||
reservedAmount: 23_500,
|
||||
paidAmount: 0,
|
||||
|
||||
parties: [
|
||||
{ id: 'p1', role: 'insured', name: 'Dr. Ricardo Blanco', initials: 'RB', email: 'rblanco@clinicasj.cr', phone: '+506 2290-1500', company: 'Clínica San José', unreadComms: 0 },
|
||||
{ id: 'p2', role: 'carrier_contact', name: 'Elena Cordero', initials: 'EC', email: 'ecordero@palig.com', phone: '+506 2201-3300', company: 'Pan-American Life', unreadComms: 0 },
|
||||
{ id: 'p3', role: 'handler', name: 'Ana Ramírez', initials: 'AR', email: 'ana.r@seguros.cr', phone: '+506 8855-3300', unreadComms: 0 },
|
||||
],
|
||||
|
||||
tasks: [
|
||||
{ id: 't1', title: 'Follow up on pre-authorization decision — 5 days pending', status: 'open', assignee: 'Ana R.', dueDate: '2026-04-09', slaPercent: 78, type: 'communication' },
|
||||
{ id: 't2', title: 'Confirm surgical facility is in-network', status: 'done', assignee: 'Ana R.', dueDate: '2026-03-29', slaPercent: 100, type: 'general' },
|
||||
{ id: 't3', title: 'Upload specialist referral letter', status: 'done', assignee: 'Ana R.', dueDate: '2026-03-30', slaPercent: 100, type: 'document' },
|
||||
],
|
||||
|
||||
communications: [
|
||||
{ id: 'c1', type: 'system', partyId: 'p3', from: 'System', body: 'Claim CLM-0045 created. Pre-authorization request submitted to Pan-American Life.', timestamp: '2026-03-27T09:00:00' },
|
||||
{ id: 'c2', type: 'email', partyId: 'p1', from: 'Dr. Ricardo Blanco', to: 'Ana Ramírez', subject: 'Surgery Pre-Auth Request — Group Policy', body: 'Ana, we need pre-authorization for knee replacement surgery for one of our covered employees (María del Carmen Vega, DOB 15/07/1968). The procedure is scheduled for April 15 at Hospital Metropolitano. Attached are the specialist referral, diagnostic imaging, and treatment plan.', timestamp: '2026-03-27T09:30:00', threadId: 'th1' },
|
||||
{ id: 'c3', type: 'email', partyId: 'p3', from: 'Ana Ramírez', to: 'Elena Cordero', subject: 'Pre-Auth Request — Clínica San José Group CLM-0045', body: 'Elena, submitting pre-authorization for knee replacement surgery under group policy LIFE-2024-CSJ-001. Patient María del Carmen Vega. Surgery scheduled April 15 at Hospital Metropolitano (in-network confirmed). All supporting documentation attached.', timestamp: '2026-03-27T11:00:00', threadId: 'th2' },
|
||||
{ id: 'c4', type: 'email', partyId: 'p2', from: 'Elena Cordero', to: 'Ana Ramírez', subject: 'RE: Pre-Auth Request — Clínica San José Group', body: 'Ana, request received and under medical review. Reference PA-2026-0455. Standard review period is 5-7 business days. We may request additional documentation if needed.', timestamp: '2026-03-28T10:00:00', threadId: 'th2', aiDigest: 'Pan-American Life acknowledged pre-auth request as PA-2026-0455. Under medical review. 5-7 business day standard review period.' },
|
||||
{ id: 'c5', type: 'call', partyId: 'p1', from: 'Ana Ramírez', body: 'Called Dr. Blanco to confirm submission. Advised that standard review is 5-7 business days. He is concerned about timing — surgery scheduled April 15 and patient has been waiting 3 months. Will escalate if no response by April 4.', timestamp: '2026-03-28T14:00:00' },
|
||||
{ id: 'c6', type: 'system', partyId: 'p3', from: 'System', body: 'Carrier status updated: Documentation Pending → Reserved. Reserve set at $23,500.', timestamp: '2026-04-02T09:00:00' },
|
||||
{ id: 'c7', type: 'note', partyId: 'p3', from: 'Ana Ramírez', body: 'Reserve set at $23,500 — this is the estimated surgery cost. No decision yet on pre-authorization. 5 business days have passed. Will follow up with Elena tomorrow if no response.', timestamp: '2026-04-03T16:00:00' },
|
||||
],
|
||||
|
||||
documents: [
|
||||
{ id: 'd1', name: 'PreAuth-Request-CLM0045.pdf', category: 'fnol', uploadedBy: 'Ana R.', uploadedAt: '2026-03-27', size: '178 KB', required: true, received: true },
|
||||
{ id: 'd2', name: 'Specialist-Referral-Letter.pdf', category: 'fnol', uploadedBy: 'Dr. Ricardo Blanco', uploadedAt: '2026-03-27', size: '95 KB', required: true, received: true },
|
||||
{ id: 'd3', name: 'Diagnostic-Imaging-KneeMRI.pdf', category: 'evidence', uploadedBy: 'Dr. Ricardo Blanco', uploadedAt: '2026-03-27', size: '15.2 MB', required: true, received: true },
|
||||
{ id: 'd4', name: 'Treatment-Plan.pdf', category: 'evidence', uploadedBy: 'Dr. Ricardo Blanco', uploadedAt: '2026-03-27', size: '240 KB', required: true, received: true },
|
||||
{ id: 'd5', name: 'PALIG-Acknowledgment.pdf', category: 'correspondence', uploadedBy: 'Ana R.', uploadedAt: '2026-03-28', size: '112 KB', required: false, received: true },
|
||||
{ id: 'd6', name: 'PreAuth-Decision-Letter.pdf', category: 'correspondence', uploadedBy: '', uploadedAt: '', size: '', required: true, received: false },
|
||||
],
|
||||
|
||||
financials: [
|
||||
{ id: 'f1', type: 'reserve_change', date: '2026-04-02', amount: 23_500, description: 'Reserve set — estimated surgery cost', annotation: 'Knee replacement at Hospital Metropolitano' },
|
||||
],
|
||||
|
||||
aiRecap: 'Solicitud de preautorización para cirugía de reemplazo de rodilla para empleada María del Carmen Vega bajo la póliza grupal de Clínica San José. Cirugía programada para el 15 de abril en Hospital Metropolitano (red confirmada).\n\nPan-American Life acusó recibo el 28 de marzo (ref PA-2026-0455). Período de revisión estándar 5-7 días hábiles. La reserva se estableció en $23,500 el 2 de abril.\n\nHan pasado 7 días hábiles sin decisión. El Dr. Blanco está preocupado por el cronograma — la paciente ha esperado 3 meses. Se necesita seguimiento urgente con la aseguradora para obtener decisión antes de la fecha de cirugía.',
|
||||
aiRecapSourceCount: 8,
|
||||
|
||||
keyDates: [
|
||||
{ label: 'Pre-Auth Submitted', date: '2026-03-27', done: true },
|
||||
{ label: 'Carrier Acknowledged', date: '2026-03-28', done: true },
|
||||
{ label: 'Review Period Ends', date: '2026-04-07', done: false },
|
||||
{ label: 'Decision Expected', date: '2026-04-09', done: false },
|
||||
{ label: 'Surgery Scheduled', date: '2026-04-15', done: false },
|
||||
],
|
||||
|
||||
reserveHistory: [
|
||||
{ date: '2026-04-02', amount: 23_500, annotation: 'Reserve set — estimated surgery cost at Hospital Metropolitano' },
|
||||
],
|
||||
intakeToken: null,
|
||||
intakeStatus: 'not_sent',
|
||||
intakeSentAt: null,
|
||||
intakeCompletedAt: null,
|
||||
generatedForms: [],
|
||||
}
|
||||
|
||||
// ── Export ───────────────────────────────────────────────────────────────────
|
||||
|
||||
export const MOCK_CLAIM_DETAILS: Record<string, ClaimDetail> = {
|
||||
'CLM-0048': clm0048,
|
||||
'CLM-0047': clm0047,
|
||||
'CLM-0043': clm0043,
|
||||
'CLM-0045': clm0045,
|
||||
}
|
||||
461
app/data/mock-customers.ts
Normal file
461
app/data/mock-customers.ts
Normal file
@@ -0,0 +1,461 @@
|
||||
/**
|
||||
* Mock customer data for visual design & demo.
|
||||
* Each client has realistic policies, claims, payments, and activity.
|
||||
*/
|
||||
|
||||
export type MockPolicy = {
|
||||
id: string
|
||||
line: string
|
||||
carrier: string
|
||||
product: string
|
||||
premium: number
|
||||
status: 'Active' | 'Pending' | 'Lapsed' | 'Cancelled'
|
||||
renewal: string
|
||||
icon: string
|
||||
details?: string
|
||||
referralChannel?: string
|
||||
}
|
||||
|
||||
export type MockClaim = {
|
||||
id: string
|
||||
policy: string
|
||||
type: string
|
||||
date: string
|
||||
amount: number
|
||||
status: 'In progress' | 'Resolved' | 'Denied' | 'Under review'
|
||||
}
|
||||
|
||||
export type MockPayment = {
|
||||
date: string
|
||||
amount: number
|
||||
policy: string
|
||||
method: string
|
||||
status: 'Paid' | 'Pending' | 'Overdue' | 'Failed'
|
||||
}
|
||||
|
||||
export type MockActivityEvent = {
|
||||
date: string
|
||||
text: string
|
||||
type: 'claim' | 'payment' | 'renewal' | 'quote' | 'note' | 'policy' | 'onboarding'
|
||||
}
|
||||
|
||||
/**
|
||||
* Customer tier — derived from data completeness & policy status:
|
||||
* quick_lead — minimal capture (name + phone/email only)
|
||||
* lead — profile info but no policies yet
|
||||
* customer — has at least one active policy
|
||||
* cancelled — had policies but all cancelled / lapsed
|
||||
*/
|
||||
export type CustomerTier = 'quick_lead' | 'lead' | 'customer' | 'cancelled'
|
||||
|
||||
export type MockCustomer = {
|
||||
id: string
|
||||
name: string
|
||||
initials: string
|
||||
type: 'Individual' | 'Corporate'
|
||||
documentId: string
|
||||
email: string
|
||||
phone: string
|
||||
birthDate: string
|
||||
gender: string
|
||||
address: string
|
||||
since: string
|
||||
agent: string
|
||||
preferredLang: string
|
||||
tags: string[]
|
||||
policies: MockPolicy[]
|
||||
claims: MockClaim[]
|
||||
payments: MockPayment[]
|
||||
activity: MockActivityEvent[]
|
||||
paymentStatus: 'Current' | 'Overdue' | 'Grace period' | 'N/A'
|
||||
}
|
||||
|
||||
/** Derive tier from customer data */
|
||||
export function customerTier(c: MockCustomer): CustomerTier {
|
||||
if (c.policies.length === 0 && (!c.documentId || c.documentId === '—') && !c.address) return 'quick_lead'
|
||||
if (c.policies.length === 0) return 'lead'
|
||||
const hasActive = c.policies.some(p => p.status === 'Active' || p.status === 'Pending')
|
||||
if (!hasActive) return 'cancelled'
|
||||
return 'customer'
|
||||
}
|
||||
|
||||
/* ────────────────────────────────────────────── */
|
||||
/* 1 · María Elena Pérez Solano */
|
||||
/* ────────────────────────────────────────────── */
|
||||
const maria: MockCustomer = {
|
||||
id: 'cust-001',
|
||||
name: 'María Elena Pérez Solano',
|
||||
initials: 'MP',
|
||||
type: 'Individual',
|
||||
documentId: '1-0456-0812',
|
||||
email: 'maria.perez@email.com',
|
||||
phone: '+506 8834-2291',
|
||||
birthDate: '1988-03-14',
|
||||
gender: 'Female',
|
||||
address: 'San José, Escazú, Trejos Montealegre',
|
||||
since: '2021-06-10',
|
||||
agent: 'Ana R.',
|
||||
preferredLang: 'Spanish',
|
||||
tags: ['VIP', 'Referral source'],
|
||||
paymentStatus: 'Current',
|
||||
policies: [
|
||||
{ id: 'POL-2024-4412', line: 'Auto', carrier: 'ASSA', product: '2023 Toyota RAV4 — SJO-4412', premium: 1840, status: 'Active', renewal: '2025-06-15', icon: 'i-heroicons-truck', details: 'Comprehensive • $500 deductible', referralChannel: 'Direct walk-in' },
|
||||
{ id: 'POL-2024-7788', line: 'Life', carrier: 'INS', product: 'Individual health plan', premium: 3200, status: 'Active', renewal: '2025-09-01', icon: 'i-heroicons-heart', details: 'Gold tier • Dental included', referralChannel: 'Direct walk-in' },
|
||||
{ id: 'POL-2023-1190', line: 'Life', carrier: 'Mapfre', product: 'Term life — 20yr, $250K', premium: 960, status: 'Active', renewal: '2026-01-10', icon: 'i-heroicons-shield-check', details: 'Beneficiary: Carlos Pérez (spouse)', referralChannel: 'Cross-sell' },
|
||||
],
|
||||
claims: [
|
||||
{ id: 'CL-2891', policy: 'POL-2024-4412', type: 'Collision', date: '2025-02-18', amount: 4200, status: 'In progress' },
|
||||
{ id: 'CL-2204', policy: 'POL-2024-7788', type: 'Medical reimbursement', date: '2024-08-05', amount: 1100, status: 'Resolved' },
|
||||
],
|
||||
payments: [
|
||||
{ date: '2025-04-01', amount: 540, policy: 'POL-2024-4412', method: 'Auto-debit', status: 'Paid' },
|
||||
{ date: '2025-04-01', amount: 267, policy: 'POL-2024-7788', method: 'Auto-debit', status: 'Paid' },
|
||||
{ date: '2025-03-01', amount: 540, policy: 'POL-2024-4412', method: 'Auto-debit', status: 'Paid' },
|
||||
{ date: '2025-03-01', amount: 267, policy: 'POL-2024-7788', method: 'Auto-debit', status: 'Paid' },
|
||||
{ date: '2025-03-01', amount: 80, policy: 'POL-2023-1190', method: 'Transfer', status: 'Paid' },
|
||||
],
|
||||
activity: [
|
||||
{ date: 'Today', text: 'Auto claim CL-2891 — adjuster report uploaded', type: 'claim' },
|
||||
{ date: 'Yesterday', text: 'Health premium payment confirmed ($267)', type: 'payment' },
|
||||
{ date: 'Mar 28', text: 'Renewal notice sent for Auto policy', type: 'renewal' },
|
||||
{ date: 'Mar 15', text: 'Quote requested: Home insurance', type: 'quote' },
|
||||
{ date: 'Feb 18', text: 'Collision claim filed — CL-2891', type: 'claim' },
|
||||
],
|
||||
}
|
||||
|
||||
/* ────────────────────────────────────────────── */
|
||||
/* 2 · Roberto Jiménez Mora */
|
||||
/* ────────────────────────────────────────────── */
|
||||
const roberto: MockCustomer = {
|
||||
id: 'cust-002',
|
||||
name: 'Roberto Jiménez Mora',
|
||||
initials: 'RJ',
|
||||
type: 'Individual',
|
||||
documentId: '3-0321-0654',
|
||||
email: 'roberto.jimenez@correo.cr',
|
||||
phone: '+506 7012-8845',
|
||||
birthDate: '1975-11-22',
|
||||
gender: 'Male',
|
||||
address: 'Heredia, Belén, La Asunción',
|
||||
since: '2019-02-15',
|
||||
agent: 'Ana R.',
|
||||
preferredLang: 'Spanish',
|
||||
tags: ['Long-term client'],
|
||||
paymentStatus: 'Current',
|
||||
policies: [
|
||||
{ id: 'POL-2023-3301', line: 'Auto', carrier: 'Qualitas', product: '2021 Hyundai Tucson — HER-9901', premium: 1520, status: 'Active', renewal: '2025-08-20', icon: 'i-heroicons-truck', details: 'Comprehensive • $750 deductible', referralChannel: 'Referral — client' },
|
||||
{ id: 'POL-2023-3302', line: 'Auto', carrier: 'Qualitas', product: '2019 Honda CRV — HER-6632', premium: 1280, status: 'Active', renewal: '2025-08-20', icon: 'i-heroicons-truck', details: 'Comprehensive • $750 deductible • Spouse vehicle', referralChannel: 'Referral — client' },
|
||||
{ id: 'POL-2022-1010', line: 'Home', carrier: 'ASSA', product: 'Homeowner — Belén residence', premium: 890, status: 'Active', renewal: '2025-11-01', icon: 'i-heroicons-home-modern', details: 'Dwelling $185K • Contents $40K • Earthquake included', referralChannel: 'Cross-sell' },
|
||||
{ id: 'POL-2024-5500', line: 'Life', carrier: 'Pan-American Life', product: 'Whole life — $150K', premium: 1440, status: 'Active', renewal: '2026-02-15', icon: 'i-heroicons-shield-check', details: 'Beneficiary: Lucía Jiménez (spouse)', referralChannel: 'Cross-sell' },
|
||||
{ id: 'POL-2024-5501', line: 'General Risk', carrier: 'INS', product: 'Personal umbrella — $1M', premium: 420, status: 'Active', renewal: '2025-12-01', icon: 'i-heroicons-shield-exclamation', details: 'Excess liability over auto + home', referralChannel: 'Cross-sell' },
|
||||
],
|
||||
claims: [
|
||||
{ id: 'CL-1840', policy: 'POL-2022-1010', type: 'Water damage', date: '2024-04-12', amount: 6800, status: 'Resolved' },
|
||||
{ id: 'CL-2105', policy: 'POL-2023-3301', type: 'Windshield', date: '2024-11-28', amount: 450, status: 'Resolved' },
|
||||
],
|
||||
payments: [
|
||||
{ date: '2025-04-01', amount: 233, policy: 'POL-2023-3301', method: 'Auto-debit', status: 'Paid' },
|
||||
{ date: '2025-04-01', amount: 197, policy: 'POL-2023-3302', method: 'Auto-debit', status: 'Paid' },
|
||||
{ date: '2025-04-01', amount: 74, policy: 'POL-2022-1010', method: 'Auto-debit', status: 'Paid' },
|
||||
{ date: '2025-04-01', amount: 120, policy: 'POL-2024-5500', method: 'Auto-debit', status: 'Paid' },
|
||||
{ date: '2025-03-01', amount: 233, policy: 'POL-2023-3301', method: 'Auto-debit', status: 'Paid' },
|
||||
{ date: '2025-03-01', amount: 197, policy: 'POL-2023-3302', method: 'Auto-debit', status: 'Paid' },
|
||||
],
|
||||
activity: [
|
||||
{ date: 'Yesterday', text: 'Monthly premium auto-debited ($624)', type: 'payment' },
|
||||
{ date: 'Mar 30', text: 'Umbrella policy annual review scheduled', type: 'renewal' },
|
||||
{ date: 'Mar 15', text: 'Quote requested: Teen driver add-on', type: 'quote' },
|
||||
{ date: 'Feb 20', text: 'Home policy endorsement — added jewelry rider', type: 'policy' },
|
||||
{ date: 'Jan 10', text: 'Windshield claim CL-2105 resolved ($450)', type: 'claim' },
|
||||
{ date: 'Dec 15', text: 'Year-end portfolio review completed', type: 'note' },
|
||||
],
|
||||
}
|
||||
|
||||
/* ────────────────────────────────────────────── */
|
||||
/* 3 · Carolina Fallas Vargas */
|
||||
/* ────────────────────────────────────────────── */
|
||||
const carolina: MockCustomer = {
|
||||
id: 'cust-003',
|
||||
name: 'Carolina Fallas Vargas',
|
||||
initials: 'CF',
|
||||
type: 'Individual',
|
||||
documentId: '2-0589-0177',
|
||||
email: 'carolina.fallas@gmail.com',
|
||||
phone: '+506 6198-3340',
|
||||
birthDate: '1992-07-30',
|
||||
gender: 'Female',
|
||||
address: 'Cartago, Paraíso, Orosí',
|
||||
since: '2023-09-05',
|
||||
agent: 'Marco V.',
|
||||
preferredLang: 'Spanish',
|
||||
tags: ['New client'],
|
||||
paymentStatus: 'Current',
|
||||
policies: [
|
||||
{ id: 'POL-2024-8810', line: 'Auto', carrier: 'INS', product: '2024 Kia Sportage — CAR-1177', premium: 1650, status: 'Active', renewal: '2025-09-05', icon: 'i-heroicons-truck', details: 'Comprehensive • $500 deductible', referralChannel: 'Facebook campaign' },
|
||||
{ id: 'POL-2024-8811', line: 'Home', carrier: 'ASSA', product: "Renter's insurance — Paraíso apt", premium: 320, status: 'Active', renewal: '2025-09-05', icon: 'i-heroicons-home-modern', details: 'Contents $25K • Liability $100K', referralChannel: 'Facebook campaign' },
|
||||
],
|
||||
claims: [],
|
||||
payments: [
|
||||
{ date: '2025-04-01', amount: 138, policy: 'POL-2024-8810', method: 'Credit card', status: 'Paid' },
|
||||
{ date: '2025-04-01', amount: 27, policy: 'POL-2024-8811', method: 'Credit card', status: 'Paid' },
|
||||
{ date: '2025-03-01', amount: 138, policy: 'POL-2024-8810', method: 'Credit card', status: 'Paid' },
|
||||
{ date: '2025-03-01', amount: 27, policy: 'POL-2024-8811', method: 'Credit card', status: 'Paid' },
|
||||
],
|
||||
activity: [
|
||||
{ date: 'Mar 25', text: 'Monthly payment processed ($165)', type: 'payment' },
|
||||
{ date: 'Mar 10', text: 'Renter policy — updated inventory list', type: 'policy' },
|
||||
{ date: 'Feb 05', text: 'Welcome call completed by Marco V.', type: 'onboarding' },
|
||||
{ date: 'Sep 05', text: 'Policies issued — Auto + Renter', type: 'policy' },
|
||||
],
|
||||
}
|
||||
|
||||
/* ────────────────────────────────────────────── */
|
||||
/* 4 · Luis Andrés Solís Calderón */
|
||||
/* ────────────────────────────────────────────── */
|
||||
const luis: MockCustomer = {
|
||||
id: 'cust-004',
|
||||
name: 'Luis Andrés Solís Calderón',
|
||||
initials: 'LS',
|
||||
type: 'Individual',
|
||||
documentId: '1-1102-0398',
|
||||
email: 'luis.solis@outlook.com',
|
||||
phone: '+506 8455-7721',
|
||||
birthDate: '1968-01-09',
|
||||
gender: 'Male',
|
||||
address: 'San José, Santa Ana, Pozos',
|
||||
since: '2017-11-20',
|
||||
agent: 'Ana R.',
|
||||
preferredLang: 'Spanish',
|
||||
tags: ['High-value', 'Referral source', 'Multi-line'],
|
||||
paymentStatus: 'Overdue',
|
||||
policies: [
|
||||
{ id: 'POL-2022-2200', line: 'Auto', carrier: 'Qualitas', product: '2022 BMW X5 — SJO-2200', premium: 3200, status: 'Active', renewal: '2025-05-01', icon: 'i-heroicons-truck', details: 'Comprehensive • $1,000 deductible', referralChannel: 'Referral — client' },
|
||||
{ id: 'POL-2022-2201', line: 'Auto', carrier: 'Qualitas', product: '2020 Mercedes GLC — SJO-7788', premium: 2800, status: 'Active', renewal: '2025-05-01', icon: 'i-heroicons-truck', details: 'Comprehensive • $1,000 deductible • Spouse vehicle', referralChannel: 'Referral — client' },
|
||||
{ id: 'POL-2020-0055', line: 'Home', carrier: 'ASSA', product: 'Homeowner — Santa Ana residence', premium: 2100, status: 'Active', renewal: '2025-07-15', icon: 'i-heroicons-home-modern', details: 'Dwelling $420K • Contents $95K • Flood + Earthquake', referralChannel: 'Cross-sell' },
|
||||
{ id: 'POL-2021-0750', line: 'Life', carrier: 'Pan-American Life', product: 'Whole life — $500K', premium: 4800, status: 'Active', renewal: '2025-11-20', icon: 'i-heroicons-shield-check', details: 'Beneficiaries: Patricia Calderón (60%), Children (40%)', referralChannel: 'Google Ads' },
|
||||
{ id: 'POL-2023-6600', line: 'Life', carrier: 'Blue Cross', product: 'Family health — Platinum', premium: 8400, status: 'Active', renewal: '2025-10-01', icon: 'i-heroicons-heart', details: '4 members • Dental + Vision • Intl coverage', referralChannel: 'Google Ads' },
|
||||
{ id: 'POL-2023-6601', line: 'General Risk', carrier: 'INS', product: 'Personal umbrella — $2M', premium: 680, status: 'Active', renewal: '2025-12-01', icon: 'i-heroicons-shield-exclamation', details: 'Excess liability over auto + home', referralChannel: 'Cross-sell' },
|
||||
],
|
||||
claims: [
|
||||
{ id: 'CL-3020', policy: 'POL-2022-2200', type: 'Collision — rear-end', date: '2025-03-08', amount: 9500, status: 'In progress' },
|
||||
{ id: 'CL-2650', policy: 'POL-2023-6600', type: 'Surgery reimbursement', date: '2024-10-15', amount: 12400, status: 'Resolved' },
|
||||
{ id: 'CL-2102', policy: 'POL-2020-0055', type: 'Storm damage — roof', date: '2024-06-22', amount: 8200, status: 'Resolved' },
|
||||
],
|
||||
payments: [
|
||||
{ date: '2025-04-01', amount: 1832, policy: 'Multiple', method: 'Auto-debit', status: 'Failed' },
|
||||
{ date: '2025-03-01', amount: 1832, policy: 'Multiple', method: 'Auto-debit', status: 'Paid' },
|
||||
{ date: '2025-02-01', amount: 1832, policy: 'Multiple', method: 'Auto-debit', status: 'Paid' },
|
||||
{ date: '2025-01-01', amount: 1832, policy: 'Multiple', method: 'Auto-debit', status: 'Paid' },
|
||||
],
|
||||
activity: [
|
||||
{ date: 'Today', text: 'ALERT: April payment failed — auto-debit declined', type: 'payment' },
|
||||
{ date: 'Yesterday', text: 'Collision claim CL-3020 — repair estimate received ($9,500)', type: 'claim' },
|
||||
{ date: 'Mar 20', text: 'Auto policies up for renewal May 1 — quote comparison started', type: 'renewal' },
|
||||
{ date: 'Mar 08', text: 'Collision claim filed — CL-3020 (BMW rear-end)', type: 'claim' },
|
||||
{ date: 'Feb 15', text: 'Annual portfolio review — recommended umbrella increase', type: 'note' },
|
||||
{ date: 'Jan 20', text: 'Health claim CL-2650 resolved — $12,400 reimbursed', type: 'claim' },
|
||||
],
|
||||
}
|
||||
|
||||
/* ────────────────────────────────────────────── */
|
||||
/* 5 · Sofía Campos Rojas */
|
||||
/* ────────────────────────────────────────────── */
|
||||
const sofia: MockCustomer = {
|
||||
id: 'cust-005',
|
||||
name: 'Sofía Campos Rojas',
|
||||
initials: 'SC',
|
||||
type: 'Individual',
|
||||
documentId: '4-0220-0561',
|
||||
email: 'sofia.campos@icloud.com',
|
||||
phone: '+506 7233-0098',
|
||||
birthDate: '1995-12-03',
|
||||
gender: 'Female',
|
||||
address: 'Guanacaste, Liberia, Centro',
|
||||
since: '2024-01-15',
|
||||
agent: 'Marco V.',
|
||||
preferredLang: 'Spanish',
|
||||
tags: ['Young professional'],
|
||||
paymentStatus: 'Grace period',
|
||||
policies: [
|
||||
{ id: 'POL-2024-9901', line: 'Auto', carrier: 'INS', product: '2024 Mazda CX-30 — GUA-0098', premium: 1380, status: 'Active', renewal: '2026-01-15', icon: 'i-heroicons-truck', details: 'Comprehensive • $500 deductible', referralChannel: 'Instagram campaign' },
|
||||
{ id: 'POL-2024-9902', line: 'Life', carrier: 'Mapfre', product: 'Term life — 10yr, $100K', premium: 360, status: 'Active', renewal: '2026-01-15', icon: 'i-heroicons-shield-check', details: 'Beneficiary: Elena Rojas (mother)', referralChannel: 'Cross-sell' },
|
||||
],
|
||||
claims: [
|
||||
{ id: 'CL-3101', policy: 'POL-2024-9901', type: 'Fender bender', date: '2025-03-20', amount: 1800, status: 'Under review' },
|
||||
],
|
||||
payments: [
|
||||
{ date: '2025-04-01', amount: 145, policy: 'POL-2024-9901', method: 'Transfer', status: 'Pending' },
|
||||
{ date: '2025-03-01', amount: 145, policy: 'POL-2024-9901', method: 'Transfer', status: 'Paid' },
|
||||
{ date: '2025-03-01', amount: 30, policy: 'POL-2024-9902', method: 'Transfer', status: 'Paid' },
|
||||
{ date: '2025-02-01', amount: 145, policy: 'POL-2024-9901', method: 'Transfer', status: 'Paid' },
|
||||
],
|
||||
activity: [
|
||||
{ date: 'Today', text: 'Grace period — April auto premium not yet received', type: 'payment' },
|
||||
{ date: 'Mar 22', text: 'Fender bender claim CL-3101 filed', type: 'claim' },
|
||||
{ date: 'Mar 01', text: 'Monthly payment received ($175)', type: 'payment' },
|
||||
{ date: 'Jan 15', text: 'Policies renewed — Auto + Life', type: 'renewal' },
|
||||
],
|
||||
}
|
||||
|
||||
/* ────────────────────────────────────────────── */
|
||||
/* 6 · Quick Lead — Diego Herrera */
|
||||
/* ────────────────────────────────────────────── */
|
||||
const diego: MockCustomer = {
|
||||
id: 'cust-006',
|
||||
name: 'Diego Herrera',
|
||||
initials: 'DH',
|
||||
type: 'Individual',
|
||||
documentId: '—',
|
||||
email: 'diego.h@gmail.com',
|
||||
phone: '+506 6100-4422',
|
||||
birthDate: '',
|
||||
gender: '',
|
||||
address: '',
|
||||
since: '2026-03-28',
|
||||
agent: 'Marco V.',
|
||||
preferredLang: 'Spanish',
|
||||
tags: ['Quick lead', 'Referral'],
|
||||
paymentStatus: 'N/A',
|
||||
policies: [],
|
||||
claims: [],
|
||||
payments: [],
|
||||
activity: [
|
||||
{ date: 'Mar 28', text: 'Quick lead captured — referred by Roberto Jiménez', type: 'onboarding' },
|
||||
],
|
||||
}
|
||||
|
||||
/* ────────────────────────────────────────────── */
|
||||
/* 7 · Quick Lead — Valeria Núñez */
|
||||
/* ────────────────────────────────────────────── */
|
||||
const valeria: MockCustomer = {
|
||||
id: 'cust-007',
|
||||
name: 'Valeria Núñez',
|
||||
initials: 'VN',
|
||||
type: 'Individual',
|
||||
documentId: '—',
|
||||
email: '',
|
||||
phone: '+506 8899-1100',
|
||||
birthDate: '',
|
||||
gender: '',
|
||||
address: '',
|
||||
since: '2026-04-01',
|
||||
agent: 'Ana R.',
|
||||
preferredLang: 'Spanish',
|
||||
tags: ['Quick lead', 'Walk-in'],
|
||||
paymentStatus: 'N/A',
|
||||
policies: [],
|
||||
claims: [],
|
||||
payments: [],
|
||||
activity: [
|
||||
{ date: 'Apr 01', text: 'Walk-in lead — interested in auto insurance', type: 'onboarding' },
|
||||
],
|
||||
}
|
||||
|
||||
/* ────────────────────────────────────────────── */
|
||||
/* 8 · Lead — Andrés Mora Villalobos */
|
||||
/* ────────────────────────────────────────────── */
|
||||
const andres: MockCustomer = {
|
||||
id: 'cust-008',
|
||||
name: 'Andrés Mora Villalobos',
|
||||
initials: 'AM',
|
||||
type: 'Individual',
|
||||
documentId: '1-1450-0221',
|
||||
email: 'andres.mora@empresa.cr',
|
||||
phone: '+506 7744-5566',
|
||||
birthDate: '1990-05-18',
|
||||
gender: 'Male',
|
||||
address: 'San José, Moravia, San Vicente',
|
||||
since: '2026-03-15',
|
||||
agent: 'Ana R.',
|
||||
preferredLang: 'Spanish',
|
||||
tags: ['Lead', 'Corporate referral'],
|
||||
paymentStatus: 'N/A',
|
||||
policies: [],
|
||||
claims: [],
|
||||
payments: [],
|
||||
activity: [
|
||||
{ date: 'Mar 15', text: 'Lead created — needs auto + health quotes', type: 'onboarding' },
|
||||
{ date: 'Mar 20', text: 'Discovery call completed — family of 3', type: 'note' },
|
||||
],
|
||||
}
|
||||
|
||||
/* ────────────────────────────────────────────── */
|
||||
/* 9 · Lead — Corporación Tecnológica del Valle */
|
||||
/* ────────────────────────────────────────────── */
|
||||
const corpTech: MockCustomer = {
|
||||
id: 'cust-009',
|
||||
name: 'Corporación Tecnológica del Valle',
|
||||
initials: 'CT',
|
||||
type: 'Corporate',
|
||||
documentId: '3-101-789456',
|
||||
email: 'rrhh@corptech.cr',
|
||||
phone: '+506 2234-8800',
|
||||
birthDate: '',
|
||||
gender: '',
|
||||
address: 'Heredia, Heredia, Zona Franca',
|
||||
since: '2026-02-10',
|
||||
agent: 'Marco V.',
|
||||
preferredLang: 'Spanish',
|
||||
tags: ['Lead', 'Corporate', 'Group health prospect'],
|
||||
paymentStatus: 'N/A',
|
||||
policies: [],
|
||||
claims: [],
|
||||
payments: [],
|
||||
activity: [
|
||||
{ date: 'Feb 10', text: 'Corporate lead — 45 employees, group health RFP', type: 'onboarding' },
|
||||
{ date: 'Mar 05', text: 'Census received — quoting in progress', type: 'quote' },
|
||||
],
|
||||
}
|
||||
|
||||
/* ────────────────────────────────────────────── */
|
||||
/* 10 · Cancelled — Fernando Arias Blanco */
|
||||
/* ────────────────────────────────────────────── */
|
||||
const fernando: MockCustomer = {
|
||||
id: 'cust-010',
|
||||
name: 'Fernando Arias Blanco',
|
||||
initials: 'FA',
|
||||
type: 'Individual',
|
||||
documentId: '1-0892-0344',
|
||||
email: 'fernando.arias@hotmail.com',
|
||||
phone: '+506 8322-0017',
|
||||
birthDate: '1982-09-14',
|
||||
gender: 'Male',
|
||||
address: 'Alajuela, San Carlos, Ciudad Quesada',
|
||||
since: '2020-04-01',
|
||||
agent: 'Ana R.',
|
||||
preferredLang: 'Spanish',
|
||||
tags: ['Cancelled', 'Win-back opportunity'],
|
||||
paymentStatus: 'N/A',
|
||||
policies: [
|
||||
{ id: 'POL-2020-1100', line: 'Auto', carrier: 'INS', product: '2018 Toyota Hilux — ALJ-4400', premium: 1200, status: 'Cancelled', renewal: '2024-04-01', icon: 'i-heroicons-truck', details: 'Cancelled — non-payment', referralChannel: 'Direct walk-in' },
|
||||
{ id: 'POL-2021-2200', line: 'Home', carrier: 'ASSA', product: 'Homeowner — Ciudad Quesada', premium: 650, status: 'Lapsed', renewal: '2024-06-15', icon: 'i-heroicons-home-modern', details: 'Lapsed — did not renew', referralChannel: 'Direct walk-in' },
|
||||
],
|
||||
claims: [
|
||||
{ id: 'CL-1200', policy: 'POL-2020-1100', type: 'Theft attempt', date: '2023-08-10', amount: 3200, status: 'Resolved' },
|
||||
],
|
||||
payments: [
|
||||
{ date: '2024-01-01', amount: 154, policy: 'POL-2020-1100', method: 'Transfer', status: 'Paid' },
|
||||
{ date: '2024-02-01', amount: 154, policy: 'POL-2020-1100', method: 'Transfer', status: 'Overdue' },
|
||||
{ date: '2024-03-01', amount: 154, policy: 'POL-2020-1100', method: 'Transfer', status: 'Overdue' },
|
||||
],
|
||||
activity: [
|
||||
{ date: 'Apr 01', text: 'Auto policy cancelled — 3 months unpaid', type: 'policy' },
|
||||
{ date: 'Jun 15', text: 'Home policy lapsed — did not renew', type: 'policy' },
|
||||
{ date: 'Aug 20', text: 'Win-back call attempted — no answer', type: 'note' },
|
||||
],
|
||||
}
|
||||
|
||||
/* ────────────────────────────────────────────── */
|
||||
/* Exports */
|
||||
/* ────────────────────────────────────────────── */
|
||||
|
||||
export const MOCK_CUSTOMERS: MockCustomer[] = [maria, roberto, carolina, luis, sofia, diego, valeria, andres, corpTech, fernando]
|
||||
|
||||
export const MOCK_CUSTOMERS_BY_ID: Record<string, MockCustomer> = Object.fromEntries(
|
||||
MOCK_CUSTOMERS.map((c) => [c.id, c])
|
||||
)
|
||||
|
||||
/** Helper to format currency */
|
||||
export function fmtMoney(n: number): string {
|
||||
return `$${n.toLocaleString()}`
|
||||
}
|
||||
660
app/data/mock-renewals.ts
Normal file
660
app/data/mock-renewals.ts
Normal file
@@ -0,0 +1,660 @@
|
||||
// ═══════════════════════════════════════════════════════════════════════════════
|
||||
// RENEWALS — Data Layer
|
||||
// ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
// --- Carrier Status ---
|
||||
export type CarrierRenewalStatus =
|
||||
| 'pending'
|
||||
| 'terms_received'
|
||||
| 'remarketing'
|
||||
| 'bound'
|
||||
| 'declined'
|
||||
| 'lapsed'
|
||||
|
||||
// --- Broker Workflow Status ---
|
||||
export type BrokerRenewalStatus =
|
||||
| 'unreviewed'
|
||||
| 'under_review'
|
||||
| 'proposal_sent'
|
||||
| 'awaiting_client_response'
|
||||
| 'awaiting_payment'
|
||||
| 'closed_renewed'
|
||||
| 'closed_remarketed'
|
||||
| 'closed_cancelled'
|
||||
| 'not_renewing'
|
||||
|
||||
export type RenewalPriority = 'critical' | 'high' | 'medium' | 'low'
|
||||
export type RetentionRisk = 'high' | 'medium' | 'low'
|
||||
|
||||
export type CancellationReason =
|
||||
| 'price'
|
||||
| 'service'
|
||||
| 'competitor'
|
||||
| 'coverage_gap'
|
||||
| 'business_closed'
|
||||
| 'non_payment'
|
||||
| 'carrier_declined'
|
||||
| 'other'
|
||||
|
||||
export interface CancellationData {
|
||||
reason: CancellationReason
|
||||
reasonDetail: string | null
|
||||
competitor: string | null
|
||||
competitorPremium: number | null
|
||||
recoverable: boolean
|
||||
exitDate: string
|
||||
}
|
||||
|
||||
export interface RenewalTask {
|
||||
id: string
|
||||
title: string
|
||||
type: 'review' | 'send_proposal' | 'follow_up' | 'collect_payment' | 'escalation'
|
||||
status: 'open' | 'in_progress' | 'overdue' | 'done'
|
||||
assignee: string
|
||||
dueDate: string
|
||||
aiGenerated: boolean
|
||||
slaPercent: number
|
||||
}
|
||||
|
||||
export interface RenewalCommunication {
|
||||
id: string
|
||||
type: 'email' | 'call' | 'note' | 'system'
|
||||
direction: 'inbound' | 'outbound' | 'internal'
|
||||
from: string
|
||||
to: string | null
|
||||
subject: string | null
|
||||
body: string
|
||||
aiDigest: string | null
|
||||
templateUsed: string | null
|
||||
timestamp: string
|
||||
partyRole: string
|
||||
}
|
||||
|
||||
export interface RenewalDocument {
|
||||
id: string
|
||||
name: string
|
||||
category: 'current_policy' | 'renewal_terms' | 'proposal_sent' |
|
||||
'client_confirmation' | 'payment_receipt' | 'loss_runs' |
|
||||
'correspondence' | 'cancellation'
|
||||
uploadedBy: string
|
||||
uploadedAt: string
|
||||
required: boolean
|
||||
fulfilled: boolean
|
||||
}
|
||||
|
||||
export interface RenewalParty {
|
||||
id: string
|
||||
role: 'insured' | 'carrier_rep' | 'producer' | 'handler' | 'ai_agent'
|
||||
name: string
|
||||
company: string | null
|
||||
phone: string | null
|
||||
email: string | null
|
||||
hasUnread: boolean
|
||||
}
|
||||
|
||||
export interface RenewalQuote {
|
||||
id: string
|
||||
carrier: string
|
||||
premium: number
|
||||
currency: 'USD' | 'CRC'
|
||||
coverageAmount: number
|
||||
deductible: number
|
||||
receivedAt: string
|
||||
recommended: boolean
|
||||
notes: string | null
|
||||
}
|
||||
|
||||
export interface CoverageLine {
|
||||
name: string
|
||||
currentAmount: number | string
|
||||
renewalAmount: number | string | null
|
||||
delta: string | null
|
||||
flag: 'increase' | 'decrease' | 'same' | 'new' | 'removed' | null
|
||||
}
|
||||
|
||||
export interface PolicyComparison {
|
||||
currentPremium: number
|
||||
renewalPremium: number | null
|
||||
premiumDelta: number | null
|
||||
currentDeductible: number
|
||||
renewalDeductible: number | null
|
||||
deductibleDelta: number | null
|
||||
coverageLines: CoverageLine[]
|
||||
aiAnalysis: string | null
|
||||
}
|
||||
|
||||
export interface EmailTemplate {
|
||||
id: string
|
||||
name: string
|
||||
subject: string
|
||||
body: string
|
||||
stage: BrokerRenewalStatus
|
||||
lob: string | 'all'
|
||||
isDefault: boolean
|
||||
}
|
||||
|
||||
export interface RenewalHistoryEntry {
|
||||
year: number
|
||||
carrier: string
|
||||
premium: number
|
||||
outcome: 'renewed' | 'remarketed' | 'cancelled' | 'new'
|
||||
}
|
||||
|
||||
// --- List item ---
|
||||
export interface Renewal {
|
||||
id: string
|
||||
policyId: string
|
||||
policyNumber: string
|
||||
customerId: string
|
||||
customerName: string
|
||||
customerType: 'individual' | 'corporate'
|
||||
carrier: string
|
||||
lob: string
|
||||
currentPremium: number
|
||||
renewalPremium: number | null
|
||||
premiumDelta: number | null
|
||||
currency: 'USD' | 'CRC'
|
||||
expiryDate: string
|
||||
daysUntilExpiry: number
|
||||
carrierStatus: CarrierRenewalStatus
|
||||
brokerStatus: BrokerRenewalStatus
|
||||
priority: RenewalPriority
|
||||
retentionRisk: RetentionRisk
|
||||
lossRatio: number
|
||||
yearsAsClient: number
|
||||
openClaims: number
|
||||
assignedTo: string
|
||||
lastContactDate: string | null
|
||||
slaPercent: number
|
||||
outstandingBalance: number
|
||||
paymentStatus: 'current' | 'overdue' | 'grace_period'
|
||||
}
|
||||
|
||||
// --- Detail ---
|
||||
export interface RenewalDetail extends Renewal {
|
||||
claimIds: string[]
|
||||
parties: RenewalParty[]
|
||||
tasks: RenewalTask[]
|
||||
communications: RenewalCommunication[]
|
||||
documents: RenewalDocument[]
|
||||
comparison: PolicyComparison | null
|
||||
quotes: RenewalQuote[]
|
||||
renewalHistory: RenewalHistoryEntry[]
|
||||
cancellationData: CancellationData | null
|
||||
commissionRate: number
|
||||
commissionAmount: number
|
||||
aiRenewalBrief: string | null
|
||||
aiTalkTrack: string[] | null
|
||||
aiRetentionFactors: string[] | null
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════════
|
||||
// Label Maps
|
||||
// ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
export const carrierStatusLabels: Record<CarrierRenewalStatus, string> = {
|
||||
pending: 'Pendiente',
|
||||
terms_received: 'Términos Recibidos',
|
||||
remarketing: 'En Remarketing',
|
||||
bound: 'Vinculada',
|
||||
declined: 'Declinada',
|
||||
lapsed: 'Vencida',
|
||||
}
|
||||
|
||||
export const brokerStatusLabels: Record<BrokerRenewalStatus, string> = {
|
||||
unreviewed: 'Sin Revisar',
|
||||
under_review: 'En Revisión',
|
||||
proposal_sent: 'Propuesta Enviada',
|
||||
awaiting_client_response: 'Esperando Cliente',
|
||||
awaiting_payment: 'Esperando Pago',
|
||||
closed_renewed: 'Renovada',
|
||||
closed_remarketed: 'Remarketing Exitoso',
|
||||
closed_cancelled: 'Cancelada',
|
||||
not_renewing: 'No Renueva',
|
||||
}
|
||||
|
||||
export const priorityLabels: Record<RenewalPriority, string> = {
|
||||
critical: 'Crítica',
|
||||
high: 'Alta',
|
||||
medium: 'Media',
|
||||
low: 'Baja',
|
||||
}
|
||||
|
||||
export const retentionRiskLabels: Record<RetentionRisk, string> = {
|
||||
high: 'Alto',
|
||||
medium: 'Medio',
|
||||
low: 'Bajo',
|
||||
}
|
||||
|
||||
export const cancellationReasonLabels: Record<CancellationReason, string> = {
|
||||
price: 'Precio',
|
||||
service: 'Servicio',
|
||||
competitor: 'Competencia',
|
||||
coverage_gap: 'Cobertura insuficiente',
|
||||
business_closed: 'Cierre de negocio',
|
||||
non_payment: 'Falta de pago',
|
||||
carrier_declined: 'Aseguradora declinó',
|
||||
other: 'Otro',
|
||||
}
|
||||
|
||||
export const expiryBuckets = {
|
||||
expired: { label: 'Vencidas', min: -Infinity, max: -1 },
|
||||
this_week: { label: 'Esta semana', min: 0, max: 7 },
|
||||
thirty_days: { label: '30 días', min: 8, max: 30 },
|
||||
sixty_days: { label: '60 días', min: 31, max: 60 },
|
||||
ninety_days: { label: '90 días', min: 61, max: 90 },
|
||||
future: { label: '90+ días', min: 91, max: Infinity },
|
||||
}
|
||||
|
||||
export const templateMergeFields = [
|
||||
'{{customer_name}}', '{{policy_number}}', '{{lob}}', '{{carrier}}',
|
||||
'{{current_premium}}', '{{renewal_premium}}', '{{premium_delta}}',
|
||||
'{{expiry_date}}', '{{coverage_amount}}', '{{deductible}}',
|
||||
'{{producer_name}}', '{{producer_phone}}', '{{producer_email}}',
|
||||
'{{company_name}}', '{{loss_ratio}}', '{{years_as_client}}',
|
||||
]
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════════
|
||||
// Helpers
|
||||
// ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
export function slaColor(percent: number): 'green' | 'amber' | 'red' {
|
||||
if (percent >= 100) return 'red'
|
||||
if (percent >= 75) return 'amber'
|
||||
return 'green'
|
||||
}
|
||||
|
||||
export function expiryBucket(days: number): string {
|
||||
for (const [key, b] of Object.entries(expiryBuckets)) {
|
||||
if (days >= b.min && days <= b.max) return key
|
||||
}
|
||||
return 'future'
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════════
|
||||
// Mock Email Templates
|
||||
// ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
export const MOCK_EMAIL_TEMPLATES: EmailTemplate[] = [
|
||||
{
|
||||
id: 'tpl-1', name: 'Aviso de Renovación', stage: 'under_review', lob: 'all', isDefault: true,
|
||||
subject: 'Su póliza {{policy_number}} próxima a vencer',
|
||||
body: 'Estimado/a {{customer_name}},\n\nLe informamos que su póliza {{policy_number}} de {{lob}} con {{carrier}} vence el {{expiry_date}}.\n\nPrima actual: {{current_premium}}\n\nNos pondremos en contacto próximamente con los términos de renovación.\n\nSaludos cordiales,\n{{producer_name}}',
|
||||
},
|
||||
{
|
||||
id: 'tpl-2', name: 'Propuesta de Renovación', stage: 'proposal_sent', lob: 'all', isDefault: true,
|
||||
subject: 'Términos de renovación — {{policy_number}}',
|
||||
body: 'Estimado/a {{customer_name}},\n\nAdjunto los términos de renovación para su póliza {{policy_number}}:\n\n• Prima actual: {{current_premium}}\n• Prima renovación: {{renewal_premium}} ({{premium_delta}})\n• Cobertura: {{coverage_amount}}\n• Deducible: {{deductible}}\n\nPor favor confirme si desea proceder con la renovación.\n\nQuedamos atentos,\n{{producer_name}}\n{{producer_phone}}',
|
||||
},
|
||||
{
|
||||
id: 'tpl-3', name: 'Seguimiento #1', stage: 'awaiting_client_response', lob: 'all', isDefault: true,
|
||||
subject: 'Recordatorio: renovación de póliza {{policy_number}}',
|
||||
body: 'Estimado/a {{customer_name}},\n\nLe recordamos que estamos a la espera de su confirmación para renovar la póliza {{policy_number}} que vence el {{expiry_date}}.\n\nPor favor responda a este correo o comuníquese al {{producer_phone}} para evitar cualquier lapso en su cobertura.\n\nSaludos,\n{{producer_name}}',
|
||||
},
|
||||
{
|
||||
id: 'tpl-4', name: 'Seguimiento #2', stage: 'awaiting_client_response', lob: 'all', isDefault: true,
|
||||
subject: 'Segundo aviso: su póliza {{policy_number}} vence el {{expiry_date}}',
|
||||
body: 'Estimado/a {{customer_name}},\n\nEste es un segundo aviso sobre la renovación de su póliza {{policy_number}}. La fecha de vencimiento es {{expiry_date}} y necesitamos su confirmación a la brevedad posible.\n\nSin su confirmación, la póliza podría vencer sin renovación, dejándole sin cobertura.\n\nPor favor contáctenos de inmediato.\n\n{{producer_name}}\n{{producer_email}} | {{producer_phone}}',
|
||||
},
|
||||
{
|
||||
id: 'tpl-5', name: 'Confirmación de Pago', stage: 'awaiting_payment', lob: 'all', isDefault: true,
|
||||
subject: 'Pago pendiente — renovación {{policy_number}}',
|
||||
body: 'Estimado/a {{customer_name}},\n\nGracias por confirmar la renovación de su póliza {{policy_number}}.\n\nPara completar el proceso, le solicitamos realizar el pago de {{renewal_premium}} a la brevedad.\n\nUna vez recibido el pago, procederemos con la emisión de su nueva póliza.\n\nSaludos,\n{{producer_name}}',
|
||||
},
|
||||
{
|
||||
id: 'tpl-6', name: 'Renovación Completada', stage: 'closed_renewed', lob: 'all', isDefault: true,
|
||||
subject: 'Confirmación de renovación — {{policy_number}}',
|
||||
body: 'Estimado/a {{customer_name}},\n\nNos complace confirmar que su póliza {{policy_number}} ha sido renovada exitosamente con {{carrier}}.\n\nNueva vigencia: {{expiry_date}}\nPrima: {{renewal_premium}}\n\nAdjunto encontrará su nueva póliza. No dude en contactarnos para cualquier consulta.\n\nGracias por su confianza,\n{{producer_name}}\n{{company_name}}',
|
||||
},
|
||||
]
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════════
|
||||
// Mock Renewals (Pipeline List)
|
||||
// ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
export const MOCK_RENEWALS: Renewal[] = [
|
||||
{
|
||||
id: 'REN-001', policyId: 'POL-0955', policyNumber: 'PROP-2024-HP-001',
|
||||
customerId: 'CUS-001', customerName: 'Hotel Pacífico Resort', customerType: 'corporate',
|
||||
carrier: 'ASSA', lob: 'Auto', currentPremium: 18500, renewalPremium: 22570,
|
||||
premiumDelta: 22, currency: 'USD', expiryDate: '2026-04-11', daysUntilExpiry: 3,
|
||||
carrierStatus: 'terms_received', brokerStatus: 'awaiting_client_response',
|
||||
priority: 'critical', retentionRisk: 'high', lossRatio: 0.42, yearsAsClient: 5,
|
||||
openClaims: 1, assignedTo: 'Marco V.', lastContactDate: '2026-04-03',
|
||||
slaPercent: 95, outstandingBalance: 0, paymentStatus: 'current',
|
||||
},
|
||||
{
|
||||
id: 'REN-002', policyId: 'POL-1034', policyNumber: 'GR-2024-CM-001',
|
||||
customerId: 'CUS-002', customerName: 'Constructora Montes', customerType: 'corporate',
|
||||
carrier: 'Mapfre', lob: 'General Risk', currentPremium: 32000, renewalPremium: null,
|
||||
premiumDelta: null, currency: 'USD', expiryDate: '2026-04-22', daysUntilExpiry: 14,
|
||||
carrierStatus: 'pending', brokerStatus: 'under_review',
|
||||
priority: 'high', retentionRisk: 'medium', lossRatio: 0.15, yearsAsClient: 3,
|
||||
openClaims: 0, assignedTo: 'Ana R.', lastContactDate: '2026-04-01',
|
||||
slaPercent: 55, outstandingBalance: 0, paymentStatus: 'current',
|
||||
},
|
||||
{
|
||||
id: 'REN-003', policyId: 'POL-1077', policyNumber: 'LIFE-2024-CR-001',
|
||||
customerId: 'CUS-003', customerName: 'Carmen Ruiz', customerType: 'individual',
|
||||
carrier: 'Pan-American Life', lob: 'Life', currentPremium: 2800, renewalPremium: 2940,
|
||||
premiumDelta: 5, currency: 'USD', expiryDate: '2026-04-15', daysUntilExpiry: 7,
|
||||
carrierStatus: 'terms_received', brokerStatus: 'awaiting_payment',
|
||||
priority: 'medium', retentionRisk: 'low', lossRatio: 0, yearsAsClient: 8,
|
||||
openClaims: 0, assignedTo: 'Ana R.', lastContactDate: '2026-04-06',
|
||||
slaPercent: 30, outstandingBalance: 0, paymentStatus: 'current',
|
||||
},
|
||||
{
|
||||
id: 'REN-004', policyId: 'POL-1110', policyNumber: 'AUTO-2024-ABC-001',
|
||||
customerId: 'CUS-004', customerName: 'Empresa ABC S.A.', customerType: 'corporate',
|
||||
carrier: 'Qualitas', lob: 'Auto', currentPremium: 22400, renewalPremium: null,
|
||||
premiumDelta: null, currency: 'USD', expiryDate: '2026-05-08', daysUntilExpiry: 30,
|
||||
carrierStatus: 'pending', brokerStatus: 'unreviewed',
|
||||
priority: 'low', retentionRisk: 'low', lossRatio: 0.08, yearsAsClient: 2,
|
||||
openClaims: 0, assignedTo: 'Unassigned', lastContactDate: null,
|
||||
slaPercent: 10, outstandingBalance: 0, paymentStatus: 'current',
|
||||
},
|
||||
{
|
||||
id: 'REN-005', policyId: 'POL-0888', policyNumber: 'HEALTH-2024-CSJ-001',
|
||||
customerId: 'CUS-005', customerName: 'Clínica San José', customerType: 'corporate',
|
||||
carrier: 'ASSA', lob: 'Health', currentPremium: 45000, renewalPremium: null,
|
||||
premiumDelta: null, currency: 'USD', expiryDate: '2026-04-01', daysUntilExpiry: -7,
|
||||
carrierStatus: 'lapsed', brokerStatus: 'closed_cancelled',
|
||||
priority: 'high', retentionRisk: 'high', lossRatio: 0.65, yearsAsClient: 4,
|
||||
openClaims: 0, assignedTo: 'Marco V.', lastContactDate: '2026-03-28',
|
||||
slaPercent: 100, outstandingBalance: 8500, paymentStatus: 'overdue',
|
||||
},
|
||||
{
|
||||
id: 'REN-006', policyId: 'POL-1200', policyNumber: 'GR-2024-TN-001',
|
||||
customerId: 'CUS-006', customerName: 'Transportes del Norte', customerType: 'corporate',
|
||||
carrier: 'ASSA', lob: 'General Risk', currentPremium: 38000, renewalPremium: null,
|
||||
premiumDelta: null, currency: 'USD', expiryDate: '2026-06-07', daysUntilExpiry: 60,
|
||||
carrierStatus: 'pending', brokerStatus: 'unreviewed',
|
||||
priority: 'high', retentionRisk: 'high', lossRatio: 0.55, yearsAsClient: 6,
|
||||
openClaims: 1, assignedTo: 'Unassigned', lastContactDate: null,
|
||||
slaPercent: 15, outstandingBalance: 21000, paymentStatus: 'overdue',
|
||||
},
|
||||
]
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════════
|
||||
// Mock Renewal Details
|
||||
// ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
const ren001Detail: RenewalDetail = {
|
||||
...MOCK_RENEWALS[0],
|
||||
claimIds: ['CLM-0048'],
|
||||
parties: [
|
||||
{ id: 'rp-1', role: 'insured', name: 'Carlos Montero', company: 'Hotel Pacífico Resort', phone: '+507 6700-1234', email: 'cmontero@hotelpacífico.com', hasUnread: true },
|
||||
{ id: 'rp-2', role: 'carrier_rep', name: 'Lucía Vargas', company: 'ASSA', phone: '+507 6600-9876', email: 'lvargas@assa.com', hasUnread: false },
|
||||
{ id: 'rp-3', role: 'handler', name: 'Marco V.', company: null, phone: null, email: 'marco@segur-os.com', hasUnread: false },
|
||||
],
|
||||
tasks: [
|
||||
{ id: 'rt-1', title: 'Follow up with client — no response in 5 days', type: 'follow_up', status: 'overdue', assignee: 'Marco V.', dueDate: '2026-04-06', aiGenerated: true, slaPercent: 110 },
|
||||
{ id: 'rt-2', title: 'Prepare counter-proposal (premium increase justification)', type: 'send_proposal', status: 'open', assignee: 'Marco V.', dueDate: '2026-04-09', aiGenerated: false, slaPercent: 80 },
|
||||
{ id: 'rt-3', title: 'Review loss runs before presenting to client', type: 'review', status: 'done', assignee: 'Marco V.', dueDate: '2026-04-02', aiGenerated: false, slaPercent: 20 },
|
||||
],
|
||||
communications: [
|
||||
{ id: 'rc-1', type: 'email', direction: 'outbound', from: 'Marco V.', to: 'Carlos Montero', subject: 'Términos de renovación — PROP-2024-HP-001', body: 'Estimado Carlos, adjunto los términos de renovación de su póliza de auto. La prima pasa de $18,500 a $22,570 (+22%) debido al reclamo abierto y al ajuste de mercado. Quedo atento a su respuesta.', aiDigest: null, templateUsed: 'tpl-2', timestamp: '2026-04-03T10:30:00', partyRole: 'insured' },
|
||||
{ id: 'rc-2', type: 'email', direction: 'inbound', from: 'Lucía Vargas', to: 'Marco V.', subject: 'RE: Renewal terms HP-001', body: 'Marco, adjunto los términos definitivos para Hotel Pacífico. El aumento refleja el siniestro abierto CLM-0048 y el ajuste de tarifa general para flota comercial.', aiDigest: 'ASSA confirma aumento de 22% justificado por siniestro abierto y ajuste de tarifa.', templateUsed: null, timestamp: '2026-04-02T15:45:00', partyRole: 'carrier_rep' },
|
||||
{ id: 'rc-3', type: 'note', direction: 'internal', from: 'Marco V.', to: null, subject: null, body: 'Client not responding to emails. Called twice, went to voicemail. Need to escalate if no response by Apr 8.', aiDigest: null, templateUsed: null, timestamp: '2026-04-06T09:00:00', partyRole: 'handler' },
|
||||
{ id: 'rc-4', type: 'system', direction: 'internal', from: 'System', to: null, subject: null, body: 'AI escalation: Client non-response exceeds 5 days. Recommended action: send Seguimiento #1 template.', aiDigest: null, templateUsed: null, timestamp: '2026-04-08T08:00:00', partyRole: 'ai_agent' },
|
||||
],
|
||||
documents: [
|
||||
{ id: 'rd-1', name: 'Póliza actual — PROP-2024-HP-001.pdf', category: 'current_policy', uploadedBy: 'System', uploadedAt: '2026-03-01', required: true, fulfilled: true },
|
||||
{ id: 'rd-2', name: 'Términos renovación ASSA 2026.pdf', category: 'renewal_terms', uploadedBy: 'Lucía Vargas', uploadedAt: '2026-04-02', required: true, fulfilled: true },
|
||||
{ id: 'rd-3', name: 'Propuesta enviada a cliente.pdf', category: 'proposal_sent', uploadedBy: 'Marco V.', uploadedAt: '2026-04-03', required: true, fulfilled: true },
|
||||
{ id: 'rd-4', name: 'Loss runs 2023-2025.pdf', category: 'loss_runs', uploadedBy: 'ASSA', uploadedAt: '2026-04-01', required: true, fulfilled: true },
|
||||
{ id: 'rd-5', name: 'Client confirmation', category: 'client_confirmation', uploadedBy: '', uploadedAt: '', required: true, fulfilled: false },
|
||||
{ id: 'rd-6', name: 'Payment receipt', category: 'payment_receipt', uploadedBy: '', uploadedAt: '', required: true, fulfilled: false },
|
||||
],
|
||||
comparison: {
|
||||
currentPremium: 18500, renewalPremium: 22570, premiumDelta: 22,
|
||||
currentDeductible: 500, renewalDeductible: 750, deductibleDelta: 50,
|
||||
coverageLines: [
|
||||
{ name: 'Responsabilidad Civil', currentAmount: 100000, renewalAmount: 100000, delta: '=', flag: 'same' },
|
||||
{ name: 'Daños Propios', currentAmount: 45000, renewalAmount: 45000, delta: '=', flag: 'same' },
|
||||
{ name: 'Robo Total', currentAmount: 45000, renewalAmount: 40000, delta: '-11%', flag: 'decrease' },
|
||||
{ name: 'Asistencia Vial', currentAmount: 'Incluida', renewalAmount: 'Incluida', delta: '=', flag: 'same' },
|
||||
{ name: 'Vidrios', currentAmount: 2000, renewalAmount: 2500, delta: '+25%', flag: 'increase' },
|
||||
],
|
||||
aiAnalysis: 'El aumento de 22% se justifica por el siniestro abierto CLM-0048 ($128K reservado) y el ajuste de tarifa general de ASSA para flotas comerciales (+8% promedio). El deducible subió 50%. La cobertura de Robo Total baja 11% — recomendar al cliente mantener nivel actual. Se detecta oportunidad de negociar Vidrios si se acepta deducible mayor.',
|
||||
},
|
||||
quotes: [],
|
||||
renewalHistory: [
|
||||
{ year: 2025, carrier: 'ASSA', premium: 18500, outcome: 'renewed' },
|
||||
{ year: 2024, carrier: 'ASSA', premium: 16200, outcome: 'renewed' },
|
||||
{ year: 2023, carrier: 'Qualitas', premium: 15800, outcome: 'remarketed' },
|
||||
{ year: 2022, carrier: 'Qualitas', premium: 14500, outcome: 'renewed' },
|
||||
],
|
||||
cancellationData: null,
|
||||
commissionRate: 15, commissionAmount: 3385.50,
|
||||
aiRenewalBrief: 'Hotel Pacífico es un cliente corporativo de 5 años con prima actual de $18,500 en Auto. ASSA ofrece renovación a $22,570 (+22%), justificado por siniestro abierto CLM-0048 con $128K reservados y ajuste de tarifa de flota. El cliente no ha respondido en 5 días. El deducible sube de $500 a $750. Loss ratio de 42% está por encima del promedio para esta línea. Comisión proyectada: $3,385. Riesgo de retención ALTO.',
|
||||
aiTalkTrack: [
|
||||
'Abrir con empatía: reconocer que un aumento de 22% es significativo y que entendemos su preocupación.',
|
||||
'Explicar el contexto: el siniestro abierto impacta directamente la tarificación. ASSA subió tarifas de flota 8% en general.',
|
||||
'Destacar valor: 5 años como cliente, historial mayormente limpio. Hemos negociado mantener la cobertura de RC en $100K sin cambio.',
|
||||
'Proponer alternativa: si acepta deducible de $1,000 en vez de $750, podemos negociar bajar prima a ~$21,500.',
|
||||
'Urgencia: la póliza vence el 11 de abril. Sin confirmación antes del 9, hay riesgo de lapso.',
|
||||
],
|
||||
aiRetentionFactors: [
|
||||
'5 años como cliente — relación establecida',
|
||||
'Siniestro abierto CLM-0048 dificulta remarketing',
|
||||
'Flota comercial con cobertura especializada — pocas opciones en mercado local',
|
||||
'Balance al día, historial de pago puntual',
|
||||
'Riesgo: aumento de 22% puede motivar búsqueda de alternativas',
|
||||
],
|
||||
}
|
||||
|
||||
const ren005Detail: RenewalDetail = {
|
||||
...MOCK_RENEWALS[4],
|
||||
claimIds: [],
|
||||
parties: [
|
||||
{ id: 'rp-10', role: 'insured', name: 'Dr. Alejandro Solís', company: 'Clínica San José', phone: '+507 6500-3456', email: 'asolis@clinicasanjose.com', hasUnread: false },
|
||||
{ id: 'rp-11', role: 'handler', name: 'Marco V.', company: null, phone: null, email: 'marco@segur-os.com', hasUnread: false },
|
||||
],
|
||||
tasks: [
|
||||
{ id: 'rt-10', title: 'Document cancellation reason', type: 'review', status: 'done', assignee: 'Marco V.', dueDate: '2026-04-02', aiGenerated: false, slaPercent: 100 },
|
||||
{ id: 'rt-11', title: 'Win-back outreach — 30 day follow-up', type: 'follow_up', status: 'open', assignee: 'Marco V.', dueDate: '2026-05-01', aiGenerated: true, slaPercent: 20 },
|
||||
],
|
||||
communications: [
|
||||
{ id: 'rc-10', type: 'email', direction: 'inbound', from: 'Dr. Alejandro Solís', to: 'Marco V.', subject: 'Decisión sobre renovación', body: 'Marco, lamentablemente hemos decidido no renovar con ASSA. Recibimos una oferta más competitiva de Mapfre a $38,500 con mejores términos de copago. Agradecemos el servicio durante estos 4 años.', aiDigest: 'Cliente cancela por oferta competidora de Mapfre a $38,500 (vs $45,000 actual). Menciona mejores copagos.', templateUsed: null, timestamp: '2026-03-28T11:00:00', partyRole: 'insured' },
|
||||
{ id: 'rc-11', type: 'note', direction: 'internal', from: 'Marco V.', to: null, subject: null, body: 'Lost to Mapfre. Client says their copay terms are better. ASSA was unable to match. Client open to reconsidering in 12 months if terms change. Marked as recoverable.', aiDigest: null, templateUsed: null, timestamp: '2026-03-29T09:00:00', partyRole: 'handler' },
|
||||
],
|
||||
documents: [
|
||||
{ id: 'rd-10', name: 'Póliza actual — HEALTH-2024-CSJ-001.pdf', category: 'current_policy', uploadedBy: 'System', uploadedAt: '2026-02-15', required: true, fulfilled: true },
|
||||
{ id: 'rd-11', name: 'Cancellation email from client.pdf', category: 'cancellation', uploadedBy: 'Marco V.', uploadedAt: '2026-03-28', required: false, fulfilled: true },
|
||||
],
|
||||
comparison: null,
|
||||
quotes: [],
|
||||
renewalHistory: [
|
||||
{ year: 2025, carrier: 'ASSA', premium: 45000, outcome: 'cancelled' },
|
||||
{ year: 2024, carrier: 'ASSA', premium: 42000, outcome: 'renewed' },
|
||||
{ year: 2023, carrier: 'ASSA', premium: 38000, outcome: 'renewed' },
|
||||
{ year: 2022, carrier: 'ASSA', premium: 35000, outcome: 'new' },
|
||||
],
|
||||
cancellationData: {
|
||||
reason: 'competitor',
|
||||
reasonDetail: 'Mapfre offered better copay terms and lower premium',
|
||||
competitor: 'Mapfre',
|
||||
competitorPremium: 38500,
|
||||
recoverable: true,
|
||||
exitDate: '2026-04-01',
|
||||
},
|
||||
commissionRate: 12, commissionAmount: 0,
|
||||
aiRenewalBrief: 'Clínica San José — cliente corporativo de 4 años, póliza de Salud Grupal con ASSA por $45,000. Cancelada por competencia: Mapfre ofreció $38,500 con mejores copagos. Loss ratio 65% (alto). El cliente expresó apertura a reconsiderar en 12 meses. Marcado como recuperable para win-back.',
|
||||
aiTalkTrack: null,
|
||||
aiRetentionFactors: [
|
||||
'Loss ratio de 65% — difícil competir en precio',
|
||||
'Mapfre ofreció $6,500 menos con mejores copagos',
|
||||
'Cliente indica apertura a reconsiderar en 12 meses',
|
||||
'Balance pendiente de $8,500 complica relación',
|
||||
],
|
||||
}
|
||||
|
||||
const ren002Detail: RenewalDetail = {
|
||||
...MOCK_RENEWALS[1],
|
||||
claimIds: [],
|
||||
parties: [
|
||||
{ id: 'rp-20', role: 'insured', name: 'Ing. Ricardo Montes', company: 'Constructora Montes', phone: '+507 6800-2222', email: 'rmontes@constructoramontes.com', hasUnread: false },
|
||||
{ id: 'rp-21', role: 'carrier_rep', name: 'Fernando Gil', company: 'Mapfre', phone: '+507 6600-3333', email: 'fgil@mapfre.com', hasUnread: false },
|
||||
{ id: 'rp-22', role: 'handler', name: 'Ana R.', company: null, phone: null, email: 'ana@segur-os.com', hasUnread: false },
|
||||
],
|
||||
tasks: [
|
||||
{ id: 'rt-20', title: 'Request renewal terms from Mapfre', type: 'review', status: 'in_progress', assignee: 'Ana R.', dueDate: '2026-04-10', aiGenerated: false, slaPercent: 55 },
|
||||
{ id: 'rt-21', title: 'Review last year loss runs', type: 'review', status: 'open', assignee: 'Ana R.', dueDate: '2026-04-12', aiGenerated: false, slaPercent: 40 },
|
||||
],
|
||||
communications: [
|
||||
{ id: 'rc-20', type: 'email', direction: 'outbound', from: 'Ana R.', to: 'Fernando Gil', subject: 'Solicitud de términos — GR-2024-CM-001', body: 'Fernando, buen día. Solicitamos los términos de renovación para la póliza GR-2024-CM-001 de Constructora Montes, vigente hasta el 22 de abril. Agradecemos envío a la brevedad.', aiDigest: null, templateUsed: null, timestamp: '2026-04-01T14:00:00', partyRole: 'carrier_rep' },
|
||||
],
|
||||
documents: [
|
||||
{ id: 'rd-20', name: 'Póliza actual — GR-2024-CM-001.pdf', category: 'current_policy', uploadedBy: 'System', uploadedAt: '2026-03-15', required: true, fulfilled: true },
|
||||
{ id: 'rd-21', name: 'Loss runs 2024-2025.pdf', category: 'loss_runs', uploadedBy: 'Mapfre', uploadedAt: '2026-03-20', required: true, fulfilled: true },
|
||||
{ id: 'rd-22', name: 'Renewal terms', category: 'renewal_terms', uploadedBy: '', uploadedAt: '', required: true, fulfilled: false },
|
||||
],
|
||||
comparison: null,
|
||||
quotes: [],
|
||||
renewalHistory: [
|
||||
{ year: 2025, carrier: 'Mapfre', premium: 32000, outcome: 'renewed' },
|
||||
{ year: 2024, carrier: 'Mapfre', premium: 29000, outcome: 'renewed' },
|
||||
{ year: 2023, carrier: 'ASSA', premium: 27500, outcome: 'remarketed' },
|
||||
],
|
||||
cancellationData: null,
|
||||
commissionRate: 12, commissionAmount: 3840,
|
||||
aiRenewalBrief: 'Constructora Montes — cliente corporativo de 3 años, General Risk con Mapfre por $32,000. Términos de renovación aún no recibidos. Loss ratio bajo (15%). Sin reclamos abiertos. Buena relación con carrier. Se espera renovación sin complicaciones pero se necesitan los términos antes del 15 de abril para cumplir SLA.',
|
||||
aiTalkTrack: null,
|
||||
aiRetentionFactors: [
|
||||
'Loss ratio de 15% — excelente para la línea',
|
||||
'Sin reclamos abiertos',
|
||||
'3 años como cliente, relación estable',
|
||||
'Riesgo moderado: constructora puede buscar cotizaciones competitivas',
|
||||
],
|
||||
}
|
||||
|
||||
const ren003Detail: RenewalDetail = {
|
||||
...MOCK_RENEWALS[2],
|
||||
claimIds: [],
|
||||
parties: [
|
||||
{ id: 'rp-30', role: 'insured', name: 'Carmen Ruiz', company: null, phone: '+507 6400-5555', email: 'carmen.ruiz@gmail.com', hasUnread: false },
|
||||
{ id: 'rp-31', role: 'handler', name: 'Ana R.', company: null, phone: null, email: 'ana@segur-os.com', hasUnread: false },
|
||||
],
|
||||
tasks: [
|
||||
{ id: 'rt-30', title: 'Collect payment — client confirmed renewal', type: 'collect_payment', status: 'open', assignee: 'Ana R.', dueDate: '2026-04-12', aiGenerated: false, slaPercent: 30 },
|
||||
],
|
||||
communications: [
|
||||
{ id: 'rc-30', type: 'email', direction: 'outbound', from: 'Ana R.', to: 'Carmen Ruiz', subject: 'Confirmación de pago — LIFE-2024-CR-001', body: 'Estimada Carmen, gracias por confirmar la renovación de su póliza de vida. La prima para el nuevo período es de $2,940. Por favor realice la transferencia para completar el proceso.', aiDigest: null, templateUsed: 'tpl-5', timestamp: '2026-04-06T10:00:00', partyRole: 'insured' },
|
||||
{ id: 'rc-31', type: 'email', direction: 'inbound', from: 'Carmen Ruiz', to: 'Ana R.', subject: 'RE: Renovación vida', body: 'Ana, confirmo que deseo renovar. Haré la transferencia esta semana.', aiDigest: 'Cliente confirma renovación, promete pago esta semana.', templateUsed: null, timestamp: '2026-04-05T16:30:00', partyRole: 'insured' },
|
||||
],
|
||||
documents: [
|
||||
{ id: 'rd-30', name: 'Póliza actual — LIFE-2024-CR-001.pdf', category: 'current_policy', uploadedBy: 'System', uploadedAt: '2026-03-01', required: true, fulfilled: true },
|
||||
{ id: 'rd-31', name: 'Términos Pan-American Life 2026.pdf', category: 'renewal_terms', uploadedBy: 'Pan-American Life', uploadedAt: '2026-03-25', required: true, fulfilled: true },
|
||||
{ id: 'rd-32', name: 'Propuesta enviada.pdf', category: 'proposal_sent', uploadedBy: 'Ana R.', uploadedAt: '2026-03-28', required: true, fulfilled: true },
|
||||
{ id: 'rd-33', name: 'Client confirmation email.pdf', category: 'client_confirmation', uploadedBy: 'Ana R.', uploadedAt: '2026-04-05', required: true, fulfilled: true },
|
||||
{ id: 'rd-34', name: 'Payment receipt', category: 'payment_receipt', uploadedBy: '', uploadedAt: '', required: true, fulfilled: false },
|
||||
],
|
||||
comparison: {
|
||||
currentPremium: 2800, renewalPremium: 2940, premiumDelta: 5,
|
||||
currentDeductible: 0, renewalDeductible: 0, deductibleDelta: 0,
|
||||
coverageLines: [
|
||||
{ name: 'Vida Individual', currentAmount: 100000, renewalAmount: 100000, delta: '=', flag: 'same' },
|
||||
{ name: 'Muerte Accidental', currentAmount: 50000, renewalAmount: 50000, delta: '=', flag: 'same' },
|
||||
{ name: 'Incapacidad Total', currentAmount: 100000, renewalAmount: 100000, delta: '=', flag: 'same' },
|
||||
],
|
||||
aiAnalysis: 'Aumento de 5% es estándar para ajuste de edad en seguro de vida. Coberturas sin cambio. Renovación rutinaria sin complicaciones.',
|
||||
},
|
||||
quotes: [],
|
||||
renewalHistory: [
|
||||
{ year: 2025, carrier: 'Pan-American Life', premium: 2800, outcome: 'renewed' },
|
||||
{ year: 2024, carrier: 'Pan-American Life', premium: 2650, outcome: 'renewed' },
|
||||
{ year: 2023, carrier: 'Pan-American Life', premium: 2500, outcome: 'renewed' },
|
||||
{ year: 2022, carrier: 'Pan-American Life', premium: 2350, outcome: 'renewed' },
|
||||
{ year: 2021, carrier: 'Pan-American Life', premium: 2200, outcome: 'renewed' },
|
||||
{ year: 2020, carrier: 'Pan-American Life', premium: 2050, outcome: 'renewed' },
|
||||
{ year: 2019, carrier: 'Pan-American Life', premium: 1900, outcome: 'renewed' },
|
||||
{ year: 2018, carrier: 'Pan-American Life', premium: 1750, outcome: 'new' },
|
||||
],
|
||||
cancellationData: null,
|
||||
commissionRate: 20, commissionAmount: 588,
|
||||
aiRenewalBrief: 'Carmen Ruiz — cliente individual de 8 años, póliza de Vida con Pan-American Life. Aumento de 5% por ajuste de edad, estándar. Cliente confirmó renovación, pendiente cobro de $2,940. Excelente historial de retención. Sin reclamos.',
|
||||
aiTalkTrack: null,
|
||||
aiRetentionFactors: ['8 años como cliente — altamente leal', 'Sin reclamos, loss ratio 0%', 'Aumento de 5% es mínimo y esperado'],
|
||||
}
|
||||
|
||||
const ren004Detail: RenewalDetail = {
|
||||
...MOCK_RENEWALS[3],
|
||||
claimIds: [],
|
||||
parties: [
|
||||
{ id: 'rp-40', role: 'insured', name: 'Lic. Patricia Vega', company: 'Empresa ABC S.A.', phone: '+507 6300-7777', email: 'pvega@empresaabc.com', hasUnread: false },
|
||||
],
|
||||
tasks: [
|
||||
{ id: 'rt-40', title: 'Assign handler and begin review', type: 'review', status: 'open', assignee: 'Unassigned', dueDate: '2026-04-15', aiGenerated: true, slaPercent: 10 },
|
||||
],
|
||||
communications: [],
|
||||
documents: [
|
||||
{ id: 'rd-40', name: 'Póliza actual — AUTO-2024-ABC-001.pdf', category: 'current_policy', uploadedBy: 'System', uploadedAt: '2026-04-01', required: true, fulfilled: true },
|
||||
],
|
||||
comparison: null,
|
||||
quotes: [],
|
||||
renewalHistory: [
|
||||
{ year: 2025, carrier: 'Qualitas', premium: 22400, outcome: 'renewed' },
|
||||
{ year: 2024, carrier: 'Qualitas', premium: 21000, outcome: 'new' },
|
||||
],
|
||||
cancellationData: null,
|
||||
commissionRate: 15, commissionAmount: 3360,
|
||||
aiRenewalBrief: 'Empresa ABC S.A. — flota Auto con Qualitas por $22,400. Renovación sin asignar, 30 días hasta vencimiento. Sin reclamos, loss ratio 8%. Necesita asignación inmediata para cumplir SLA.',
|
||||
aiTalkTrack: null,
|
||||
aiRetentionFactors: ['Loss ratio bajo (8%)', '2 años como cliente', 'Sin complicaciones previas'],
|
||||
}
|
||||
|
||||
const ren006Detail: RenewalDetail = {
|
||||
...MOCK_RENEWALS[5],
|
||||
claimIds: ['CLM-0043'],
|
||||
parties: [
|
||||
{ id: 'rp-60', role: 'insured', name: 'Gerardo Núñez', company: 'Transportes del Norte', phone: '+507 6200-8888', email: 'gnunez@transportesnorte.com', hasUnread: true },
|
||||
],
|
||||
tasks: [
|
||||
{ id: 'rt-60', title: 'Assign handler — high-risk renewal', type: 'review', status: 'open', assignee: 'Unassigned', dueDate: '2026-04-20', aiGenerated: true, slaPercent: 15 },
|
||||
{ id: 'rt-61', title: 'Address $21K outstanding balance before renewal', type: 'escalation', status: 'open', assignee: 'Unassigned', dueDate: '2026-04-18', aiGenerated: true, slaPercent: 20 },
|
||||
],
|
||||
communications: [
|
||||
{ id: 'rc-60', type: 'system', direction: 'internal', from: 'System', to: null, subject: null, body: 'AI alert: Transportes del Norte has $21,000 outstanding balance and an open claim (CLM-0043). This renewal requires early attention due to high retention risk.', aiDigest: null, templateUsed: null, timestamp: '2026-04-08T08:00:00', partyRole: 'ai_agent' },
|
||||
],
|
||||
documents: [
|
||||
{ id: 'rd-60', name: 'Póliza actual — GR-2024-TN-001.pdf', category: 'current_policy', uploadedBy: 'System', uploadedAt: '2026-03-15', required: true, fulfilled: true },
|
||||
],
|
||||
comparison: null,
|
||||
quotes: [],
|
||||
renewalHistory: [
|
||||
{ year: 2025, carrier: 'ASSA', premium: 38000, outcome: 'renewed' },
|
||||
{ year: 2024, carrier: 'ASSA', premium: 35000, outcome: 'renewed' },
|
||||
{ year: 2023, carrier: 'ASSA', premium: 32000, outcome: 'renewed' },
|
||||
{ year: 2022, carrier: 'ASSA', premium: 28000, outcome: 'renewed' },
|
||||
{ year: 2021, carrier: 'ASSA', premium: 25000, outcome: 'renewed' },
|
||||
{ year: 2020, carrier: 'ASSA', premium: 22000, outcome: 'new' },
|
||||
],
|
||||
cancellationData: null,
|
||||
commissionRate: 12, commissionAmount: 4560,
|
||||
aiRenewalBrief: 'Transportes del Norte — cliente corporativo de 6 años, General Risk con ASSA por $38,000. ALERTA: balance pendiente de $21,000 y reclamo abierto CLM-0043 ($45K reservado). Loss ratio de 55% dificulta la negociación. Necesita atención temprana a pesar de tener 60 días hasta vencimiento. Comisión en riesgo: $4,560.',
|
||||
aiTalkTrack: [
|
||||
'Primero resolver el tema del balance pendiente de $21K antes de hablar de renovación.',
|
||||
'Reconocer que es un cliente de 6 años con historial generalmente positivo.',
|
||||
'El reclamo abierto CLM-0043 impactará los términos — preparar al cliente para posible aumento.',
|
||||
'Proponer plan de pago para el balance pendiente como condición para negociar mejores términos de renovación.',
|
||||
'Si ASSA sube prima significativamente, tener plan B de remarketing con Mapfre.',
|
||||
],
|
||||
aiRetentionFactors: [
|
||||
'6 años como cliente — relación de largo plazo',
|
||||
'Balance pendiente de $21K — señal de alerta',
|
||||
'Reclamo abierto CLM-0043 por $45K reservado',
|
||||
'Loss ratio 55% — por encima del promedio',
|
||||
'Comisión de $4,560 en riesgo',
|
||||
'Flota de transporte — pocas opciones en mercado local',
|
||||
],
|
||||
}
|
||||
|
||||
export const MOCK_RENEWAL_DETAILS: Record<string, RenewalDetail> = {
|
||||
'REN-001': ren001Detail,
|
||||
'REN-002': ren002Detail,
|
||||
'REN-003': ren003Detail,
|
||||
'REN-004': ren004Detail,
|
||||
'REN-005': ren005Detail,
|
||||
'REN-006': ren006Detail,
|
||||
}
|
||||
699
app/data/mock-support.ts
Normal file
699
app/data/mock-support.ts
Normal file
@@ -0,0 +1,699 @@
|
||||
// ─── 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 },
|
||||
]
|
||||
20
app/data/pdf-field-mappings.json
Normal file
20
app/data/pdf-field-mappings.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"version": 1,
|
||||
"mappings": [
|
||||
{
|
||||
"catalogFormId": 33,
|
||||
"fields": {
|
||||
"full_name": "txtNombreCompleto",
|
||||
"document_id": "txtCedula"
|
||||
}
|
||||
},
|
||||
{
|
||||
"catalogFormId": 39,
|
||||
"fields": {
|
||||
"plate": "txtPlaca",
|
||||
"vin": "txtChasis",
|
||||
"declared_value": "numValor"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
214
app/data/quotes-overview.mock.ts
Normal file
214
app/data/quotes-overview.mock.ts
Normal file
@@ -0,0 +1,214 @@
|
||||
/**
|
||||
* Mock pipeline data for Quotes overview (mission control). Replace with API when ready.
|
||||
*/
|
||||
|
||||
export type QuotePipelineScopeFilter = 'global' | 'corporate' | 'personal'
|
||||
|
||||
export type QuoteOverviewLob = 'auto' | 'health' | 'life' | 'general_risk' | 'custom'
|
||||
|
||||
export type QuotePipelineStageId = 'intake' | 'quoted' | 'proposal' | 'bind' | 'handoff'
|
||||
|
||||
/**
|
||||
* Unified pipeline stage IDs — mirrors PipelineStage from useSalesPipeline.
|
||||
* Used by the quotes overview kanban so both views share one vocabulary.
|
||||
*/
|
||||
export type UnifiedStageId =
|
||||
| 'customer'
|
||||
| 'get_quotes'
|
||||
| 'waiting_carriers'
|
||||
| 'present_quotes'
|
||||
| 'waiting_client'
|
||||
| 'solicitud'
|
||||
| 'emission'
|
||||
|
||||
export type MockPipelineQuote = {
|
||||
id: string
|
||||
customerLabel: string
|
||||
/** Corporate vs personal — drives pipeline scope filters */
|
||||
party: 'corporate' | 'personal'
|
||||
lob: QuoteOverviewLob
|
||||
/** Sub-path: single, comparativo, fleet, collective, etc. */
|
||||
pathLabel: string
|
||||
stage: QuotePipelineStageId
|
||||
/** Unified pipeline stage — same vocabulary as sales pipeline */
|
||||
unifiedStage: UnifiedStageId
|
||||
owner: string
|
||||
formsDone: number
|
||||
formsTotal: number
|
||||
/** Customer has been notified / has portal activity (mock) */
|
||||
customerInformed: boolean
|
||||
}
|
||||
|
||||
export const QUOTE_PIPELINE_STAGES: { id: QuotePipelineStageId; label: string; hint: string }[] = [
|
||||
{ id: 'intake', label: 'Customer Profile', hint: 'Qualify & rate inputs' },
|
||||
{ id: 'quoted', label: 'Quote Prep', hint: 'Options with carrier' },
|
||||
{ id: 'proposal', label: 'Acceptance Pending', hint: 'Out to customer' },
|
||||
{ id: 'bind', label: 'Emission Pending', hint: 'Submit & conditions' },
|
||||
{ id: 'handoff', label: 'Going Live!', hint: 'Policy / solicitud' }
|
||||
]
|
||||
|
||||
/** Unified pipeline stages — same as sales pipeline. Used in overview chart. */
|
||||
export const UNIFIED_PIPELINE_STAGES: { id: UnifiedStageId; label: string; isWaiting: boolean }[] = [
|
||||
{ id: 'customer', label: 'Customer', isWaiting: false },
|
||||
{ id: 'get_quotes', label: 'Get Quotes', isWaiting: false },
|
||||
{ id: 'waiting_carriers', label: 'Awaiting Carriers', isWaiting: true },
|
||||
{ id: 'present_quotes', label: 'Present Quotes', isWaiting: false },
|
||||
{ id: 'waiting_client', label: 'Awaiting Client', isWaiting: true },
|
||||
{ id: 'solicitud', label: 'Solicitud', isWaiting: false },
|
||||
{ id: 'emission', label: 'Emission', isWaiting: false },
|
||||
]
|
||||
|
||||
export const QUOTE_LOB_OPTIONS: { value: QuoteOverviewLob | 'all'; label: string }[] = [
|
||||
{ value: 'all', label: 'All lines' },
|
||||
{ value: 'auto', label: 'Auto' },
|
||||
{ value: 'health', label: 'Health' },
|
||||
{ value: 'life', label: 'Life' },
|
||||
{ value: 'general_risk', label: 'General risk' },
|
||||
{ value: 'custom', label: 'Custom' }
|
||||
]
|
||||
|
||||
export const MOCK_PIPELINE_QUOTES: MockPipelineQuote[] = [
|
||||
{
|
||||
id: 'q-101',
|
||||
customerLabel: 'Transportes Delta S.A.',
|
||||
party: 'corporate',
|
||||
lob: 'auto',
|
||||
pathLabel: 'Fleet',
|
||||
stage: 'quoted',
|
||||
unifiedStage: 'waiting_carriers',
|
||||
owner: 'A. Morales',
|
||||
formsDone: 2,
|
||||
formsTotal: 5,
|
||||
customerInformed: true
|
||||
},
|
||||
{
|
||||
id: 'q-102',
|
||||
customerLabel: 'María Fernández',
|
||||
party: 'personal',
|
||||
lob: 'auto',
|
||||
pathLabel: 'Comparativo',
|
||||
stage: 'proposal',
|
||||
unifiedStage: 'present_quotes',
|
||||
owner: 'L. Chen',
|
||||
formsDone: 4,
|
||||
formsTotal: 4,
|
||||
customerInformed: true
|
||||
},
|
||||
{
|
||||
id: 'q-103',
|
||||
customerLabel: 'J. Pérez',
|
||||
party: 'personal',
|
||||
lob: 'auto',
|
||||
pathLabel: 'Single',
|
||||
stage: 'intake',
|
||||
unifiedStage: 'customer',
|
||||
owner: 'L. Chen',
|
||||
formsDone: 0,
|
||||
formsTotal: 3,
|
||||
customerInformed: false
|
||||
},
|
||||
{
|
||||
id: 'q-201',
|
||||
customerLabel: 'Clínica Norte',
|
||||
party: 'corporate',
|
||||
lob: 'health',
|
||||
pathLabel: 'Collective',
|
||||
stage: 'bind',
|
||||
unifiedStage: 'solicitud',
|
||||
owner: 'R. Vega',
|
||||
formsDone: 6,
|
||||
formsTotal: 8,
|
||||
customerInformed: true
|
||||
},
|
||||
{
|
||||
id: 'q-202',
|
||||
customerLabel: 'Familia Ortega',
|
||||
party: 'personal',
|
||||
lob: 'health',
|
||||
pathLabel: 'Family',
|
||||
stage: 'quoted',
|
||||
unifiedStage: 'get_quotes',
|
||||
owner: 'A. Morales',
|
||||
formsDone: 3,
|
||||
formsTotal: 6,
|
||||
customerInformed: true
|
||||
},
|
||||
{
|
||||
id: 'q-203',
|
||||
customerLabel: 'Startup Labs',
|
||||
party: 'corporate',
|
||||
lob: 'health',
|
||||
pathLabel: 'Travel',
|
||||
stage: 'intake',
|
||||
unifiedStage: 'customer',
|
||||
owner: 'R. Vega',
|
||||
formsDone: 1,
|
||||
formsTotal: 4,
|
||||
customerInformed: false
|
||||
},
|
||||
{
|
||||
id: 'q-301',
|
||||
customerLabel: 'Holdings Centro',
|
||||
party: 'corporate',
|
||||
lob: 'life',
|
||||
pathLabel: 'Key person',
|
||||
stage: 'proposal',
|
||||
unifiedStage: 'waiting_client',
|
||||
owner: 'L. Chen',
|
||||
formsDone: 2,
|
||||
formsTotal: 5,
|
||||
customerInformed: true
|
||||
},
|
||||
{
|
||||
id: 'q-302',
|
||||
customerLabel: 'Carlos Méndez',
|
||||
party: 'personal',
|
||||
lob: 'life',
|
||||
pathLabel: 'Individual',
|
||||
stage: 'handoff',
|
||||
unifiedStage: 'emission',
|
||||
owner: 'A. Morales',
|
||||
formsDone: 5,
|
||||
formsTotal: 5,
|
||||
customerInformed: true
|
||||
},
|
||||
{
|
||||
id: 'q-401',
|
||||
customerLabel: 'Retail Plaza',
|
||||
party: 'corporate',
|
||||
lob: 'general_risk',
|
||||
pathLabel: 'Corporate',
|
||||
stage: 'quoted',
|
||||
unifiedStage: 'waiting_carriers',
|
||||
owner: 'R. Vega',
|
||||
formsDone: 3,
|
||||
formsTotal: 7,
|
||||
customerInformed: false
|
||||
},
|
||||
{
|
||||
id: 'q-402',
|
||||
customerLabel: 'Ana Ríos',
|
||||
party: 'personal',
|
||||
lob: 'general_risk',
|
||||
pathLabel: 'Personal',
|
||||
stage: 'intake',
|
||||
unifiedStage: 'get_quotes',
|
||||
owner: 'L. Chen',
|
||||
formsDone: 1,
|
||||
formsTotal: 4,
|
||||
customerInformed: true
|
||||
},
|
||||
{
|
||||
id: 'q-501',
|
||||
customerLabel: 'Phone-in — manual rate',
|
||||
party: 'personal',
|
||||
lob: 'custom',
|
||||
pathLabel: 'Manual entry',
|
||||
stage: 'proposal',
|
||||
unifiedStage: 'present_quotes',
|
||||
owner: 'R. Vega',
|
||||
formsDone: 0,
|
||||
formsTotal: 2,
|
||||
customerInformed: false
|
||||
}
|
||||
]
|
||||
35
app/data/roles-seguros.ts
Normal file
35
app/data/roles-seguros.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import type { RoleRow, SegurosPermissionKey } from '~/types/roles'
|
||||
|
||||
function all(v: boolean): Record<SegurosPermissionKey, boolean> {
|
||||
return {
|
||||
profile: v,
|
||||
portfolio: v,
|
||||
layers: v,
|
||||
tasks: v,
|
||||
billing: v,
|
||||
analytics: v,
|
||||
support: v
|
||||
}
|
||||
}
|
||||
|
||||
export const ROLES_SEGUROS_SEED: RoleRow[] = [
|
||||
{ id: 5, description: 'Agente de Ventas', active: true, seguros: all(true) },
|
||||
{ id: 4, description: 'Supervisor de Ventas', active: true, seguros: all(true) },
|
||||
{ id: 3, description: 'Configurador', active: true, seguros: all(false) },
|
||||
{ id: 2, description: 'Supervisor', active: true, seguros: all(false) },
|
||||
{ id: 1, description: 'Superadministrator', active: true, seguros: all(false) }
|
||||
]
|
||||
|
||||
export const SEGUROS_PERMISSION_COLUMNS: {
|
||||
key: SegurosPermissionKey
|
||||
icon: string
|
||||
label: string
|
||||
}[] = [
|
||||
{ key: 'profile', icon: 'i-heroicons-user', label: 'Perfil' },
|
||||
{ key: 'portfolio', icon: 'i-heroicons-folder', label: 'Cartera / pólizas' },
|
||||
{ key: 'layers', icon: 'i-heroicons-squares-2x2', label: 'Capas / duplicados' },
|
||||
{ key: 'tasks', icon: 'i-heroicons-clipboard-document-check', label: 'Tareas / checklist' },
|
||||
{ key: 'billing', icon: 'i-heroicons-currency-dollar', label: 'Cobros / primas' },
|
||||
{ key: 'analytics', icon: 'i-heroicons-chart-pie', label: 'Indicadores' },
|
||||
{ key: 'support', icon: 'i-heroicons-chat-bubble-left-right', label: 'Soporte' }
|
||||
]
|
||||
34
app/data/taxonomy.ts
Normal file
34
app/data/taxonomy.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
export const INSURER_SLUGS = [
|
||||
'acerta',
|
||||
'assa',
|
||||
'ancon',
|
||||
'fedpa',
|
||||
'mapfre',
|
||||
'optima',
|
||||
'palig'
|
||||
] as const
|
||||
|
||||
export type InsurerSlug = (typeof INSURER_SLUGS)[number]
|
||||
|
||||
export const PRODUCT_LINE_SLUGS = [
|
||||
'life',
|
||||
'health_local',
|
||||
'health_international',
|
||||
'auto_full_coverage',
|
||||
'auto_dat_liability',
|
||||
'home',
|
||||
'general_liability',
|
||||
'any'
|
||||
] as const
|
||||
|
||||
export type ProductLineSlug = (typeof PRODUCT_LINE_SLUGS)[number]
|
||||
|
||||
export const INSURER_LABEL: Record<string, string> = {
|
||||
acerta: 'ACERTA',
|
||||
assa: 'ASSA',
|
||||
ancon: 'ANCON',
|
||||
fedpa: 'FEDPA',
|
||||
mapfre: 'MAPFRE',
|
||||
optima: 'OPTIMA',
|
||||
palig: 'PALIG'
|
||||
}
|
||||
Reference in New Issue
Block a user