WIP jordan
This commit is contained in:
234
app/pages/registration/policy.vue
Normal file
234
app/pages/registration/policy.vue
Normal file
@@ -0,0 +1,234 @@
|
||||
<script setup lang="ts">
|
||||
import type { PolicyRegistration } from '~/types/brokerage-registration'
|
||||
import { POLICY_DRAFT_STORAGE_KEY } from '~/types/brokerage-registration'
|
||||
import {
|
||||
createEmptyPolicyRegistration,
|
||||
rebuildInstallmentSchedule,
|
||||
setFinOneYearAfterInicio,
|
||||
usePolicyDraftPersistence
|
||||
} from '~/composables/usePolicyRegistrationModel'
|
||||
|
||||
definePageMeta({ ssr: false })
|
||||
usePageTitle('Policy registration')
|
||||
|
||||
const toast = useToast()
|
||||
const form = ref<PolicyRegistration>(createEmptyPolicyRegistration())
|
||||
usePolicyDraftPersistence(form)
|
||||
|
||||
watch(
|
||||
() => form.value.inicioVigencia,
|
||||
() => setFinOneYearAfterInicio(form.value)
|
||||
)
|
||||
|
||||
function refreshSchedule() {
|
||||
form.value.cuotas = rebuildInstallmentSchedule(form.value)
|
||||
}
|
||||
|
||||
watch(
|
||||
() => [form.value.numCuotas, form.value.primaBruta, form.value.inicioVigencia] as const,
|
||||
() => refreshSchedule(),
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
refreshSchedule()
|
||||
})
|
||||
|
||||
const draftSavedAt = ref<string | null>(null)
|
||||
|
||||
function saveDraft() {
|
||||
try {
|
||||
localStorage.setItem(POLICY_DRAFT_STORAGE_KEY, JSON.stringify(form.value))
|
||||
draftSavedAt.value = new Date().toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' })
|
||||
toast.add({ title: 'Borrador guardado', color: 'success' })
|
||||
} catch {
|
||||
toast.add({ title: 'No se pudo guardar', color: 'error' })
|
||||
}
|
||||
}
|
||||
|
||||
function clearDraft() {
|
||||
form.value = createEmptyPolicyRegistration()
|
||||
refreshSchedule()
|
||||
try {
|
||||
localStorage.removeItem(POLICY_DRAFT_STORAGE_KEY)
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
toast.add({ title: 'Borrador borrado', color: 'success' })
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="min-h-screen space-y-8 bg-gray-50 p-8">
|
||||
<div class="flex flex-wrap items-start justify-between gap-4">
|
||||
<div class="flex items-center gap-4">
|
||||
<NuxtLink to="/policies">
|
||||
<UButton icon="i-heroicons-arrow-left" color="neutral" variant="ghost">Back</UButton>
|
||||
</NuxtLink>
|
||||
<div>
|
||||
<h1 class="text-2xl font-semibold tracking-tight text-[var(--text-primary)]">Nuevo registro · Póliza</h1>
|
||||
<p class="text-[13px] text-[var(--text-muted)]">
|
||||
Condiciones particulares, plan de pagos y referencias. Draft persists in this browser until an API is
|
||||
wired.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<UButton color="neutral" variant="soft" @click="saveDraft">Guardar borrador</UButton>
|
||||
<span v-if="draftSavedAt" class="text-[11px] text-emerald-600 font-medium">
|
||||
<UIcon name="i-heroicons-check-circle" style="width: 13px; height: 13px; vertical-align: -2px;" /> Saved at {{ draftSavedAt }}
|
||||
</span>
|
||||
<UButton color="neutral" variant="ghost" @click="clearDraft">Limpiar</UButton>
|
||||
<NuxtLink to="/onboarding/policy-upload/new">
|
||||
<UButton color="primary" variant="soft">Manual policy upload</UButton>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<UCard class="max-w-5xl">
|
||||
<template #header>
|
||||
<span class="font-semibold text-[var(--text-primary)]">Identificación y ramo</span>
|
||||
</template>
|
||||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||||
<UFormField label="Número póliza Mint">
|
||||
<UInput v-model="form.mintPolicyNumber" disabled class="w-full" />
|
||||
</UFormField>
|
||||
<UFormField label="ID contratante">
|
||||
<UInput v-model="form.contratanteId" class="w-full" />
|
||||
</UFormField>
|
||||
<UFormField label="Ramo">
|
||||
<UInput v-model="form.ramo" class="w-full" />
|
||||
</UFormField>
|
||||
<UFormField label="Sub ramo">
|
||||
<UInput v-model="form.subRamo" class="w-full" />
|
||||
</UFormField>
|
||||
<UFormField label="Aseguradora">
|
||||
<UInput v-model="form.aseguradora" class="w-full" />
|
||||
</UFormField>
|
||||
<UFormField label="Producto">
|
||||
<UInput v-model="form.producto" class="w-full" />
|
||||
</UFormField>
|
||||
<UFormField label="Agencia">
|
||||
<UInput v-model="form.agencia" class="w-full" />
|
||||
</UFormField>
|
||||
<UFormField label="Nº póliza proveedor">
|
||||
<UInput v-model="form.numeroPolizaProveedor" class="w-full" />
|
||||
</UFormField>
|
||||
<UFormField label="Acreedor">
|
||||
<UInput v-model="form.acreedor" class="w-full" />
|
||||
</UFormField>
|
||||
</div>
|
||||
</UCard>
|
||||
|
||||
<UCard class="max-w-5xl">
|
||||
<template #header>
|
||||
<span class="font-semibold text-[var(--text-primary)]">Vigencia y comisiones</span>
|
||||
</template>
|
||||
<div class="mb-6 grid grid-cols-1 gap-4 sm:grid-cols-3">
|
||||
<UFormField label="Fecha emisión">
|
||||
<UInput v-model="form.fechaEmision" type="datetime-local" class="w-full" />
|
||||
</UFormField>
|
||||
<UFormField label="Inicio vigencia">
|
||||
<UInput v-model="form.inicioVigencia" type="datetime-local" class="w-full" />
|
||||
</UFormField>
|
||||
<UFormField label="Fin vigencia">
|
||||
<UInput v-model="form.finVigencia" type="datetime-local" class="w-full" />
|
||||
</UFormField>
|
||||
</div>
|
||||
<p class="mb-2 text-xs text-[var(--text-muted)]">Comisiones agente (%)</p>
|
||||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-3">
|
||||
<div v-for="row in form.comisiones" :key="row.idx" class="flex items-end gap-2">
|
||||
<UFormField :label="`Agente ${row.idx}`" class="flex-1">
|
||||
<UInput v-model="row.agenteId" placeholder="ID" class="w-full" />
|
||||
</UFormField>
|
||||
<UFormField label="%" class="w-24">
|
||||
<UInput v-model="row.porcentaje" class="w-full" />
|
||||
</UFormField>
|
||||
</div>
|
||||
</div>
|
||||
</UCard>
|
||||
|
||||
<UCard class="max-w-5xl">
|
||||
<template #header>
|
||||
<span class="font-semibold text-[var(--text-primary)]">Primas y forma de pago</span>
|
||||
</template>
|
||||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||||
<UFormField label="Forma de pago">
|
||||
<UInput v-model="form.formaPago" class="w-full" />
|
||||
</UFormField>
|
||||
<UFormField label="Valor asegurado">
|
||||
<UInput v-model="form.valorAsegurado" class="w-full" />
|
||||
</UFormField>
|
||||
<UFormField label="Prima bruta">
|
||||
<UInput v-model="form.primaBruta" class="w-full" />
|
||||
</UFormField>
|
||||
<UFormField label="Impuesto %">
|
||||
<UInput v-model="form.impuestoPct" class="w-full" />
|
||||
</UFormField>
|
||||
<UFormField label="Prima neta">
|
||||
<UInput v-model="form.primaNeta" class="w-full" />
|
||||
</UFormField>
|
||||
<UFormField label="Número de cuotas">
|
||||
<UInput v-model.number="form.numCuotas" type="number" min="1" max="60" class="w-full" />
|
||||
</UFormField>
|
||||
</div>
|
||||
</UCard>
|
||||
|
||||
<UCard class="max-w-5xl">
|
||||
<template #header>
|
||||
<div class="flex w-full items-center justify-between gap-4">
|
||||
<span class="font-semibold text-[var(--text-primary)]">Plan de pagos</span>
|
||||
<UButton size="xs" color="neutral" variant="soft" @click="refreshSchedule">Regenerar cuotas</UButton>
|
||||
</div>
|
||||
</template>
|
||||
<div class="overflow-x-auto rounded-lg border border-[var(--card-border)] bg-[var(--surface)]">
|
||||
<table class="min-w-full text-sm">
|
||||
<thead>
|
||||
<tr class="border-b border-[var(--card-border)] bg-[var(--surface)] text-left text-[var(--text-muted)]">
|
||||
<th class="px-3 py-2 font-medium">#</th>
|
||||
<th class="px-3 py-2 font-medium">Fecha vencimiento</th>
|
||||
<th class="px-3 py-2 font-medium">Prima</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="row in form.cuotas"
|
||||
:key="row.n"
|
||||
class="border-b border-[var(--divider)] last:border-0"
|
||||
>
|
||||
<td class="px-3 py-2 text-[var(--text-muted)]">{{ row.n }}</td>
|
||||
<td class="px-3 py-2">
|
||||
<UInput v-model="row.fechaVencimiento" type="datetime-local" size="sm" />
|
||||
</td>
|
||||
<td class="px-3 py-2">
|
||||
<UInput v-model="row.prima" size="sm" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</UCard>
|
||||
|
||||
<UCard class="max-w-5xl">
|
||||
<template #header>
|
||||
<span class="font-semibold text-[var(--text-primary)]">Referencias y notas</span>
|
||||
</template>
|
||||
<div class="space-y-4">
|
||||
<UFormField label="Cotización Mint ID">
|
||||
<UInput v-model="form.cotizacionMintId" class="w-full" />
|
||||
</UFormField>
|
||||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||
<UFormField label="PDF cotización (nombre)">
|
||||
<UInput v-model="form.pdfCotizacionNombre" class="w-full" />
|
||||
</UFormField>
|
||||
<UFormField label="PDF póliza (nombre)">
|
||||
<UInput v-model="form.pdfPolizaNombre" class="w-full" />
|
||||
</UFormField>
|
||||
</div>
|
||||
<UFormField label="Notas">
|
||||
<UTextarea v-model="form.notas" :rows="4" class="w-full" />
|
||||
</UFormField>
|
||||
</div>
|
||||
</UCard>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user