big refactor

This commit is contained in:
2026-04-29 16:25:11 -05:00
parent 6c411ce2b6
commit 8265fb689a
156 changed files with 15845 additions and 50373 deletions

View File

@@ -0,0 +1,148 @@
<script setup lang="ts">
interface Plan {
provider_id: string
plan_id: string
name: string
premium: number
}
interface Props {
open: boolean
plan: Plan | null
loading?: boolean
}
const props = withDefaults(defineProps<Props>(), {
loading: false
})
const emit = defineEmits<{
'update:open': [value: boolean]
accept: []
cancel: []
}>()
function close() {
emit('update:open', false)
emit('cancel')
}
</script>
<template>
<Teleport to="body">
<Transition
enter-active-class="transition duration-200 ease-out"
enter-from-class="opacity-0"
enter-to-class="opacity-100"
leave-active-class="transition duration-150 ease-in"
leave-from-class="opacity-100"
leave-to-class="opacity-0"
>
<div v-if="open" class="confirm-modal-overlay" @click.self="close">
<Transition
enter-active-class="transition duration-200 ease-out"
enter-from-class="opacity-0 scale-95 translate-y-2"
enter-to-class="opacity-100 scale-100 translate-y-0"
leave-active-class="transition duration-150 ease-in"
leave-from-class="opacity-100 scale-100 translate-y-0"
leave-to-class="opacity-0 scale-95 translate-y-2"
>
<div v-if="open" class="confirm-modal">
<div class="confirm-modal-head">
<h3 class="text-lg font-semibold text-[var(--text-primary)]">Accept Quote</h3>
<button type="button" class="confirm-modal-close" @click="close">
<UIcon name="i-heroicons-x-mark" style="width: 16px; height: 16px;" />
</button>
</div>
<div class="confirm-modal-body">
<div v-if="plan" class="space-y-3">
<div class="bg-gray-50 rounded-lg p-4">
<div class="text-sm text-gray-500">Selected Plan</div>
<div class="text-lg font-semibold text-[var(--text-primary)] mt-1">{{ plan.name }}</div>
<div class="text-2xl font-bold text-green-600 mt-2">${{ plan.premium?.toLocaleString() }}</div>
<div class="text-xs text-gray-500 mt-1">Provider: {{ plan.provider_id }}</div>
</div>
<p class="text-sm text-gray-600">
Are you sure you want to accept this plan? This will trigger the solicitation process.
</p>
</div>
</div>
<div class="confirm-modal-foot">
<div class="flex justify-end gap-3">
<UButton color="gray" variant="soft" @click="close">Cancel</UButton>
<UButton color="primary" :loading="loading" @click="emit('accept')">Accept</UButton>
</div>
</div>
</div>
</Transition>
</div>
</Transition>
</Teleport>
</template>
<style scoped>
/* Modal overlay */
.confirm-modal-overlay {
position: fixed;
inset: 0;
z-index: 100;
background: rgba(0, 0, 0, 0.25);
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
backdrop-filter: blur(2px);
}
/* Modal container */
.confirm-modal {
width: 100%;
max-width: 480px;
border-radius: 12px;
background: #ffffff;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15), 0 4px 16px rgba(0, 0, 0, 0.08);
overflow: hidden;
}
/* Modal header */
.confirm-modal-head {
display: flex;
align-items: center;
justify-content: space-between;
padding: 18px 20px 0;
flex-shrink: 0;
}
/* Modal body */
.confirm-modal-body {
padding: 16px 20px;
display: flex;
flex-direction: column;
}
/* Modal footer */
.confirm-modal-foot {
padding: 12px 20px 16px;
border-top: 1px solid rgba(0, 0, 0, 0.06);
}
/* Close button */
.confirm-modal-close {
display: flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
border-radius: 6px;
border: none;
background: transparent;
color: #8a8a86;
cursor: pointer;
transition: all 150ms ease;
}
.confirm-modal-close:hover {
background: rgba(0, 0, 0, 0.05);
color: var(--text-primary);
}
</style>

View File

@@ -0,0 +1,99 @@
<script setup lang="ts">
interface PlanItem {
provider_id: string
quote_id: string
valid_until: string | null
received_at: string
plan_id: string
name: string
premium: number
coverage_details: string
deductible?: number
coverage_limit?: number
}
interface Props {
items: PlanItem[]
selectedPlanId: string | null
policyApplicationId: string
loading?: boolean
}
const props = withDefaults(defineProps<Props>(), {
loading: false
})
const emit = defineEmits<{
select: [planId: string]
}>()
function formatPremium(value: number): string {
return '$' + value.toLocaleString()
}
function formatDate(dateStr: string | null): string {
if (!dateStr) return ''
return new Date(dateStr).toLocaleDateString('es-PA', {
day: '2-digit',
month: 'short',
year: 'numeric'
})
}
function handleSelect(planId: string) {
if (props.loading) return
emit('select', planId)
}
</script>
<template>
<div class="quote-selection-board grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
<div
v-for="item in items"
:key="item.plan_id"
class="quote-card rounded-xl border px-3.5 py-3 shadow-sm transition cursor-pointer"
:class="selectedPlanId === item.plan_id
? 'border-primary ring-2 ring-primary/30 bg-primary/5'
: 'border-[var(--card-border)] bg-[var(--surface)] hover:border-[var(--brand)]/30 hover:shadow-md'"
@click="handleSelect(item.plan_id)"
>
<!-- Provider ID -->
<p class="text-[11px] font-mono text-gray-500 truncate">{{ item.provider_id }}</p>
<!-- Plan name -->
<p class="text-sm font-semibold text-[var(--text-primary)] mt-1 truncate">{{ item.name }}</p>
<!-- Premium -->
<p class="text-lg font-bold text-green-600 mt-2">{{ formatPremium(item.premium) }}</p>
<!-- Valid until -->
<p v-if="item.valid_until" class="text-[11px] text-gray-500 mt-1">
Valid until {{ formatDate(item.valid_until) }}
</p>
<!-- Coverage details preview -->
<p v-if="item.coverage_details" class="text-xs text-gray-600 mt-2 line-clamp-2">
{{ item.coverage_details }}
</p>
<!-- Footer -->
<div class="mt-3 flex justify-end">
<UBadge v-if="selectedPlanId === item.plan_id" color="green" variant="soft" size="xs">Selected</UBadge>
<UButton v-else-if="!loading" size="xs" color="primary" @click.stop="handleSelect(item.plan_id)">Select</UButton>
<UBadge v-else color="gray" variant="soft" size="xs">Processing...</UBadge>
</div>
</div>
</div>
</template>
<style scoped>
.quote-card {
transition: all 0.15s ease;
display: flex;
flex-direction: column;
}
.quote-card:hover {
transform: translateY(-1px);
}
</style>