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,189 @@
<script setup lang="ts">
const props = defineProps<{
modelValue: {
selectedCustomer: any
useSameForBuyer: boolean
selectedBuyer: any
}
search: string
}>()
const emit = defineEmits<{
'update:modelValue': [value: {
selectedCustomer: any
useSameForBuyer: boolean
selectedBuyer: any
}]
'update:search': [value: string]
}>()
const customerPage = ref(1)
const localSearch = ref(props.search)
const debouncedSearch = refDebounced(localSearch, 300)
watch(() => props.search, (newVal) => {
localSearch.value = newVal
})
const { data: customersData, pending: customersPending } = useCustomer('/customers', {
query: computed(() => ({
'page_size': 12,
'page': customerPage.value,
...(debouncedSearch.value && {
'filters[0][field]': 'search',
'filters[0][op]': '==',
'filters[0][value]': debouncedSearch.value
})
}))
})
function customerDisplayName(c: any) {
if (!c) return ''
return c.customer_type === 'corporate'
? (c.commercial_name || c.legal_name)
: `${c.first_name} ${c.last_name}`
}
function customerSubtitle(c: any) {
if (!c) return ''
return c.customer_type === 'corporate' ? c.ruc : c.email
}
function updateSelectedCustomer(customer: any) {
emit('update:modelValue', {
...props.modelValue,
selectedCustomer: customer,
selectedBuyer: props.modelValue.useSameForBuyer ? customer : props.modelValue.selectedBuyer
})
}
function updateSelectedBuyer(customer: any) {
emit('update:modelValue', {
...props.modelValue,
selectedBuyer: customer
})
}
function updateUseSameForBuyer(value: boolean) {
emit('update:modelValue', {
...props.modelValue,
useSameForBuyer: value,
selectedBuyer: value ? props.modelValue.selectedCustomer : props.modelValue.selectedBuyer
})
}
function onSearchInput(value: string) {
localSearch.value = value
emit('update:search', value)
}
</script>
<template>
<div class="space-y-6">
<!-- Insured Section -->
<div>
<label class="block text-sm font-medium text-[var(--text-primary)] mb-2">Insured</label>
<p class="text-sm text-[var(--text-muted)] mb-4">Person or entity being insured</p>
<div v-if="!modelValue.selectedCustomer">
<UInput
:model-value="localSearch"
@update:model-value="onSearchInput"
placeholder="Search by name, email, RUC..."
size="lg"
icon="i-heroicons-magnifying-glass"
/>
<div v-if="customersPending" class="mt-4 text-center text-[var(--text-muted)]">
Loading customers...
</div>
<div v-else-if="customersData?.data && customersData.data.length > 0" class="mt-4 space-y-2">
<div
v-for="c in customersData.data"
:key="c.id"
class="p-4 border border-[var(--card-border)] rounded-lg cursor-pointer hover:bg-[var(--card-border)] transition-colors"
@click="updateSelectedCustomer(c)"
>
<div class="flex items-center gap-3">
<UBadge :color="c.customer_type === 'corporate' ? 'purple' : 'blue'" variant="soft" size="sm">
{{ c.customer_type === 'corporate' ? 'Corp' : 'Ind' }}
</UBadge>
<span class="font-medium text-[var(--text-primary)]">{{ customerDisplayName(c) }}</span>
</div>
<div class="text-sm text-[var(--text-muted)] mt-1">{{ customerSubtitle(c) }}</div>
</div>
</div>
<div v-else class="mt-4 text-center text-[var(--text-muted)]">
No customers found. Try a different search term.
</div>
</div>
<div v-else class="p-4 bg-[var(--brand-soft)] border border-[var(--brand)] rounded-lg">
<div class="flex items-center justify-between">
<div>
<div class="flex items-center gap-3">
<UBadge :color="modelValue.selectedCustomer.customer_type === 'corporate' ? 'purple' : 'blue'" variant="soft" size="sm">
{{ modelValue.selectedCustomer.customer_type === 'corporate' ? 'Corp' : 'Ind' }}
</UBadge>
<span class="font-medium text-[var(--text-primary)]">{{ customerDisplayName(modelValue.selectedCustomer) }}</span>
</div>
<div class="text-sm text-[var(--brand)] mt-1">{{ customerSubtitle(modelValue.selectedCustomer) }}</div>
</div>
<UButton size="sm" color="neutral" variant="outline" @click="updateSelectedCustomer(null)">Change</UButton>
</div>
</div>
</div>
<!-- Buyer Section -->
<div>
<div class="flex items-center gap-3 mb-2">
<label class="block text-sm font-medium text-[var(--text-primary)]">Buyer</label>
<div class="flex items-center gap-2">
<UToggle :model-value="modelValue.useSameForBuyer" @update:model-value="updateUseSameForBuyer" />
<span class="text-sm text-[var(--text-muted)]">Same as insured</span>
</div>
</div>
<p v-if="modelValue.useSameForBuyer" class="text-sm text-[var(--text-muted)]">
Using same person as insured
</p>
<div v-else>
<UInput
:model-value="localSearch"
@update:model-value="onSearchInput"
placeholder="Search by name, email, RUC..."
size="lg"
icon="i-heroicons-magnifying-glass"
/>
<div v-if="customersPending" class="mt-4 text-center text-[var(--text-muted)]">
Loading customers...
</div>
<div v-else-if="customersData?.data && customersData.data.length > 0" class="mt-4 space-y-2">
<div
v-for="c in customersData.data"
:key="c.id"
class="p-4 border border-[var(--card-border)] rounded-lg cursor-pointer hover:bg-[var(--card-border)] transition-colors"
@click="updateSelectedBuyer(c)"
>
<div class="flex items-center gap-3">
<UBadge :color="c.customer_type === 'corporate' ? 'purple' : 'blue'" variant="soft" size="sm">
{{ c.customer_type === 'corporate' ? 'Corp' : 'Ind' }}
</UBadge>
<span class="font-medium text-[var(--text-primary)]">{{ customerDisplayName(c) }}</span>
</div>
<div class="text-sm text-[var(--text-muted)] mt-1">{{ customerSubtitle(c) }}</div>
</div>
</div>
<div v-else class="mt-4 text-center text-[var(--text-muted)]">
No customers found. Try a different search term.
</div>
</div>
</div>
</div>
</template>