100 lines
2.7 KiB
Vue
100 lines
2.7 KiB
Vue
<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>
|