169 lines
7.7 KiB
Vue
169 lines
7.7 KiB
Vue
<script setup lang="ts">
|
|
import type { QuoteComparativeView } from '~/types/quote-view-model'
|
|
|
|
defineProps<{
|
|
model: QuoteComparativeView
|
|
}>()
|
|
|
|
function fmtUsd(n: number) {
|
|
return new Intl.NumberFormat('en-US', {
|
|
style: 'currency',
|
|
currency: 'USD',
|
|
maximumFractionDigits: 0
|
|
}).format(n)
|
|
}
|
|
|
|
function fmtDate(iso: string) {
|
|
try {
|
|
return new Intl.DateTimeFormat('es-PA', { dateStyle: 'long' }).format(new Date(`${iso}T12:00:00`))
|
|
} catch {
|
|
return iso
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="quote-comparative space-y-8 text-[var(--text-primary)]">
|
|
<div
|
|
class="flex flex-wrap items-start justify-between gap-4 rounded-xl border border-[var(--card-border)] bg-gradient-to-br from-[var(--surface)] to-white p-6 shadow-sm"
|
|
>
|
|
<div class="min-w-0">
|
|
<p class="text-xs font-semibold uppercase tracking-wide text-[var(--brand)]">{{ model.title }}</p>
|
|
<h2 class="mt-1 text-2xl font-bold tracking-tight text-[var(--text-primary)]">{{ model.subtitle }}</h2>
|
|
<p class="mt-1 text-sm text-[var(--text-muted)]">{{ model.tagline }}</p>
|
|
</div>
|
|
<div class="rounded-lg border border-[var(--brand-soft)] bg-[var(--brand-faint)] px-4 py-2 text-right text-sm">
|
|
<p class="text-[var(--text-muted)]">Cotización</p>
|
|
<p class="font-medium text-[var(--text-primary)]">{{ fmtDate(model.quoteDateIso) }}</p>
|
|
<UBadge color="primary" variant="soft" class="mt-1">Válida {{ model.validDays }} días</UBadge>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="overflow-hidden rounded-xl border border-[var(--card-border)] bg-[var(--surface)] shadow-sm">
|
|
<div
|
|
class="border-b border-[var(--brand-soft)] bg-gradient-to-r from-[var(--brand)] to-[var(--brand)] px-5 py-2 text-sm font-semibold text-white"
|
|
>
|
|
1 · Cliente y cotización solicitada
|
|
</div>
|
|
<div class="grid gap-6 p-5 md:grid-cols-2">
|
|
<div>
|
|
<h3 class="mb-3 text-xs font-bold uppercase tracking-wide text-[var(--text-muted)]">Datos del cliente</h3>
|
|
<dl class="grid grid-cols-[8rem_1fr] gap-x-3 gap-y-2 text-sm">
|
|
<dt class="text-[var(--text-muted)]">Nombre</dt>
|
|
<dd class="font-medium">{{ model.client.name }}</dd>
|
|
<dt class="text-[var(--text-muted)]">Edad</dt>
|
|
<dd>{{ model.client.ageYears }} años</dd>
|
|
<dt class="text-[var(--text-muted)]">Género</dt>
|
|
<dd>{{ model.client.gender }}</dd>
|
|
<dt class="text-[var(--text-muted)]">Fumador/a</dt>
|
|
<dd>{{ model.client.smoker ? 'Sí' : 'No' }}</dd>
|
|
<dt class="text-[var(--text-muted)]">Clasificación</dt>
|
|
<dd>{{ model.client.riskClass }}</dd>
|
|
<dt class="text-[var(--text-muted)]">Ocupación</dt>
|
|
<dd>{{ model.client.occupation }}</dd>
|
|
</dl>
|
|
</div>
|
|
<div>
|
|
<h3 class="mb-3 text-xs font-bold uppercase tracking-wide text-[var(--text-muted)]">Lo que cotizamos</h3>
|
|
<p class="text-3xl font-bold text-[var(--text-primary)]">{{ fmtUsd(model.request.sumAssuredUsd) }}</p>
|
|
<p class="text-sm text-[var(--text-muted)]">Suma asegurada</p>
|
|
<p class="mt-4 text-2xl font-semibold text-[var(--brand)]">
|
|
{{ fmtUsd(model.request.monthlyPremiumUsd) }}
|
|
<span class="text-base font-normal text-[var(--text-muted)]">/ mes</span>
|
|
</p>
|
|
<p class="text-sm text-[var(--text-muted)]">
|
|
Prima anual equivalente: {{ fmtUsd(model.request.annualPremiumUsd) }} / año
|
|
</p>
|
|
<dl class="mt-4 space-y-1 text-sm">
|
|
<div class="flex justify-between gap-4">
|
|
<dt class="text-[var(--text-muted)]">Tipo de beneficio</dt>
|
|
<dd>{{ model.request.benefitTypeLabel }}</dd>
|
|
</div>
|
|
<div class="flex justify-between gap-4">
|
|
<dt class="text-[var(--text-muted)]">Coberturas adicionales</dt>
|
|
<dd>{{ model.request.additionalCoverageLabel }}</dd>
|
|
</div>
|
|
<div class="flex justify-between gap-4">
|
|
<dt class="text-[var(--text-muted)]">Depósito inicial</dt>
|
|
<dd>{{ model.request.initialDepositLabel }}</dd>
|
|
</div>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<section class="space-y-6">
|
|
<h3 class="text-sm font-bold uppercase tracking-wide text-[var(--text-muted)]">
|
|
2 · Comparativo de valores (rescate / ahorro)
|
|
</h3>
|
|
<div
|
|
v-for="(row, idx) in model.carriers"
|
|
:key="idx"
|
|
class="overflow-hidden rounded-xl border border-[var(--card-border)] bg-[var(--surface)] shadow-sm"
|
|
>
|
|
<div
|
|
class="border-b px-4 py-2 text-sm font-semibold text-white"
|
|
:class="idx % 2 === 0 ? 'bg-slate-800' : 'bg-orange-600'"
|
|
>
|
|
{{ row.carrierName }} · {{ row.productName }}
|
|
</div>
|
|
<div class="p-4 text-xs text-[var(--text-muted)]">{{ row.ratesLine }}</div>
|
|
<div class="overflow-x-auto px-2 pb-4">
|
|
<table class="min-w-full text-center text-xs sm:text-sm">
|
|
<thead>
|
|
<tr class="border-b border-[var(--card-border)] text-[var(--text-muted)]">
|
|
<th class="px-2 py-2">Suma asegurada</th>
|
|
<th v-for="(c, ci) in row.cells" :key="ci" class="px-2 py-2">
|
|
{{ c.yearLabel }}
|
|
<span class="block text-[10px] font-normal text-[var(--text-muted)] opacity-70">Edad {{ c.ageLabel }}</span>
|
|
</th>
|
|
<th class="px-2 py-2 text-[var(--brand)]">Destacado</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr class="border-b border-[var(--divider)]">
|
|
<td class="px-2 py-3 font-mono text-xs">{{ fmtUsd(row.sumAssuredUsd) }}</td>
|
|
<td v-for="(c, ci) in row.cells" :key="ci" class="px-2 py-3 align-top">
|
|
<span class="block text-base font-bold text-[var(--text-primary)]">{{ fmtUsd(c.guaranteed) }}</span>
|
|
<span class="text-xs text-[var(--brand)]">{{ fmtUsd(c.projected) }}</span>
|
|
</td>
|
|
<td class="bg-[var(--surface)] px-3 py-3 align-top text-left text-xs text-[var(--text-primary)]">
|
|
<p v-if="row.highlightProjectedUsd != null" class="text-lg font-bold text-[var(--text-primary)]">
|
|
{{ fmtUsd(row.highlightProjectedUsd) }}
|
|
</p>
|
|
<p v-if="row.highlightNote" class="mt-1 text-[10px] text-amber-800">
|
|
{{ row.highlightNote }}
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<p v-if="row.footnote" class="border-t border-[var(--divider)] px-4 py-2 text-[10px] text-[var(--text-muted)]">
|
|
{{ row.footnote }}
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<div class="rounded-xl border border-amber-200 bg-amber-50/50 p-4 text-sm">
|
|
<p class="font-semibold text-[var(--text-primary)]">Primas acumuladas pagadas (referencia)</p>
|
|
<div class="mt-2 flex flex-wrap gap-4 font-mono text-xs text-[var(--text-primary)]">
|
|
<span v-for="(p, i) in model.accumulatedPremiumsUsd" :key="i">Hito {{ i + 1 }}: {{ fmtUsd(p) }}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="overflow-hidden rounded-xl border border-slate-800 bg-slate-900 text-white shadow-md">
|
|
<div class="border-b border-slate-700 px-5 py-2 text-sm font-semibold">Análisis del asesor</div>
|
|
<div class="grid gap-4 p-5 md:grid-cols-3">
|
|
<div
|
|
v-for="(col, i) in model.advisorColumns"
|
|
:key="i"
|
|
class="rounded-lg bg-[var(--surface)]/5 p-3 text-xs leading-relaxed text-[var(--text-muted)] opacity-50"
|
|
>
|
|
{{ col }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|