190 lines
6.5 KiB
Vue
190 lines
6.5 KiB
Vue
<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>
|