Add nuxt-skills and update auto quotes to use new policy API structure
- Add nuxt-skills (vue, nuxt, nuxt-ui) to .claude/skills/ - Create useCustomerSelection() composable for managing insured/buyer selection - Create usePolicyApi() composable for policy API operations - Update auto quote components to use insured/buyer instead of client - Update vehicle fields: remove valorVehiculo, add market_value, requested_value, rc_limits - Make chassis_number and engine_number optional - Update auto quote types and composables to match new API structure - Update auto quote page to submit to policy API with new structure
This commit is contained in:
@@ -4,13 +4,8 @@ export function emptyAutoQuoteDraft(): AutoQuoteDraft {
|
||||
return {
|
||||
quoteMode: null,
|
||||
segment: null,
|
||||
client: {
|
||||
fullName: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
documentId: '',
|
||||
organizationName: ''
|
||||
},
|
||||
insured: null,
|
||||
buyer: null,
|
||||
vehicle: {
|
||||
subRamo: '',
|
||||
clase: '',
|
||||
@@ -20,7 +15,11 @@ export function emptyAutoQuoteDraft(): AutoQuoteDraft {
|
||||
placa: '',
|
||||
year: '',
|
||||
capacidadPasajeros: '',
|
||||
valorVehiculo: ''
|
||||
rc_limits: '',
|
||||
market_value: 0,
|
||||
requested_value: 0,
|
||||
chassis_number: '',
|
||||
engine_number: ''
|
||||
},
|
||||
solicit: {
|
||||
carrierIds: [],
|
||||
|
||||
137
app/composables/useCustomerSelection.ts
Normal file
137
app/composables/useCustomerSelection.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* Composable for managing customer selection in quote flows
|
||||
* Handles insured and buyer selection with validation
|
||||
*/
|
||||
export function useCustomerSelection() {
|
||||
const selectedCustomer = ref<any>(null) // Auto-generated type from useCustomer
|
||||
const useSameForBuyer = ref(true)
|
||||
const selectedBuyer = ref<any>(null)
|
||||
|
||||
/**
|
||||
* Convert customer-service customer to policy-service insured/buyer
|
||||
* Maps customer fields to policy-service structure
|
||||
*/
|
||||
const toPolicyPerson = (customer: any) => {
|
||||
if (customer.customer_type === 'corporate') {
|
||||
return {
|
||||
type: 'corporate',
|
||||
company_name: customer.legal_name,
|
||||
ruc: customer.ruc,
|
||||
legal_rep_name: customer.legal_rep_name,
|
||||
legal_rep_document: customer.legal_rep_document_id,
|
||||
email: customer.email,
|
||||
phone: customer.phone,
|
||||
address: customer.address
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'individual',
|
||||
name: `${customer.first_name} ${customer.last_name}`.trim(),
|
||||
date_of_birth: customer.birth_date,
|
||||
document_id: customer.document_id,
|
||||
email: customer.email,
|
||||
phone: customer.phone,
|
||||
address: customer.address
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get insured person from selected customer
|
||||
*/
|
||||
const insured = computed(() => {
|
||||
if (!selectedCustomer.value) return null
|
||||
return toPolicyPerson(selectedCustomer.value)
|
||||
})
|
||||
|
||||
/**
|
||||
* Get buyer person (either same as insured or different)
|
||||
*/
|
||||
const buyer = computed(() => {
|
||||
if (useSameForBuyer.value) {
|
||||
return insured.value
|
||||
}
|
||||
if (!selectedBuyer.value) return null
|
||||
return toPolicyPerson(selectedBuyer.value)
|
||||
})
|
||||
|
||||
/**
|
||||
* Validate customer has required fields for policy submission
|
||||
*/
|
||||
const validateCustomer = (customer: any) => {
|
||||
const missing: string[] = []
|
||||
|
||||
if (customer.customer_type === 'corporate') {
|
||||
if (!customer.legal_name) missing.push('legal_name')
|
||||
if (!customer.ruc) missing.push('ruc')
|
||||
if (!customer.legal_rep_name) missing.push('legal_rep_name')
|
||||
if (!customer.legal_rep_document_id) missing.push('legal_rep_document_id')
|
||||
} else {
|
||||
if (!customer.first_name) missing.push('first_name')
|
||||
if (!customer.last_name) missing.push('last_name')
|
||||
if (!customer.birth_date) missing.push('birth_date')
|
||||
if (!customer.document_id) missing.push('document_id')
|
||||
}
|
||||
|
||||
return { valid: missing.length === 0, missing }
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if insured is valid
|
||||
*/
|
||||
const isInsuredValid = computed(() => {
|
||||
if (!selectedCustomer.value) return false
|
||||
return validateCustomer(selectedCustomer.value).valid
|
||||
})
|
||||
|
||||
/**
|
||||
* Check if buyer is valid
|
||||
*/
|
||||
const isBuyerValid = computed(() => {
|
||||
if (useSameForBuyer.value) {
|
||||
return isInsuredValid.value
|
||||
}
|
||||
if (!selectedBuyer.value) return false
|
||||
return validateCustomer(selectedBuyer.value).valid
|
||||
})
|
||||
|
||||
/**
|
||||
* Get validation errors
|
||||
*/
|
||||
const validationErrors = computed(() => {
|
||||
const errors: { insured: string[]; buyer: string[] } = { insured: [], buyer: [] }
|
||||
|
||||
if (selectedCustomer.value) {
|
||||
const validation = validateCustomer(selectedCustomer.value)
|
||||
errors.insured = validation.missing
|
||||
}
|
||||
|
||||
if (!useSameForBuyer.value && selectedBuyer.value) {
|
||||
const validation = validateCustomer(selectedBuyer.value)
|
||||
errors.buyer = validation.missing
|
||||
}
|
||||
|
||||
return errors
|
||||
})
|
||||
|
||||
/**
|
||||
* Reset selection
|
||||
*/
|
||||
function reset() {
|
||||
selectedCustomer.value = null
|
||||
selectedBuyer.value = null
|
||||
useSameForBuyer.value = true
|
||||
}
|
||||
|
||||
return {
|
||||
selectedCustomer,
|
||||
selectedBuyer,
|
||||
useSameForBuyer,
|
||||
insured,
|
||||
buyer,
|
||||
isInsuredValid,
|
||||
isBuyerValid,
|
||||
validationErrors,
|
||||
reset
|
||||
}
|
||||
}
|
||||
67
app/composables/usePolicyApi.ts
Normal file
67
app/composables/usePolicyApi.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Composable for policy API operations
|
||||
* Handles quote submission and acceptance
|
||||
*/
|
||||
export function usePolicyApi() {
|
||||
const { $policy } = useNuxtApp()
|
||||
const toast = useToast()
|
||||
const router = useRouter()
|
||||
|
||||
/**
|
||||
* Submit a policy quote request
|
||||
*/
|
||||
async function submitPolicyQuote(payload: {
|
||||
policy_type: 'car' | 'life' | 'fire_structure' | 'fire_contents'
|
||||
insured: any
|
||||
buyer: any
|
||||
policy_details: any
|
||||
selected_providers: Array<{ provider_id: string; email: string }>
|
||||
}) {
|
||||
try {
|
||||
const data = await $policy('/policies', {
|
||||
method: 'POST',
|
||||
body: payload
|
||||
}) as any
|
||||
|
||||
toast.add({ title: 'Quote submitted successfully', color: 'green' })
|
||||
return data
|
||||
} catch (e: any) {
|
||||
toast.add({
|
||||
title: 'Failed to submit quote',
|
||||
description: e?.data?.error ?? e.message,
|
||||
color: 'red'
|
||||
})
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept a quote plan and trigger solicitation
|
||||
*/
|
||||
async function acceptQuote(applicationId: string, acceptedPlanId: string, acceptedBy: string) {
|
||||
try {
|
||||
const data = await $policy(`/policies/${applicationId}/accept`, {
|
||||
method: 'POST',
|
||||
body: {
|
||||
accepted_plan_id: acceptedPlanId,
|
||||
accepted_by: acceptedBy
|
||||
}
|
||||
}) as any
|
||||
|
||||
toast.add({ title: 'Plan accepted successfully', color: 'green' })
|
||||
return data
|
||||
} catch (e: any) {
|
||||
toast.add({
|
||||
title: 'Failed to accept plan',
|
||||
description: e?.data?.error ?? e.message,
|
||||
color: 'red'
|
||||
})
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
submitPolicyQuote,
|
||||
acceptQuote
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user