import { useEffect, useMemo, useState } from 'react'; import { useNavigate, useSearchParams } from 'react-router-dom'; import { CheckCircle2 } from 'lucide-react'; import { AIDecisionCard, Avatar, Button, Card, formatINR, Input, MultiSelect, RupeeAmount, Select, } from '../components'; import { LookupField } from '../components/form'; import type { LookupValue } from '../components/form'; import { useQuery, useZino } from '../api/provider'; import { useLeads } from '../api/leads'; import { decisionToCard, regionOf } from '../api/adapters'; import { fieldFromSchema } from '../api/schema'; import { ACTIVITIES } from '../api/config'; import type { LeadRecord } from '../api/types'; const F = ACTIVITIES.RECOMMEND_PRODUCT.fields; // Crude indicative premium — rate per sum assured, adjusted by frequency. function indicativePremium(sum: number, freq: string): number { const base = Math.round(sum * 0.00142); switch (freq) { case 'monthly': return Math.round((base / 12) * 1.04); case 'half_yearly': return Math.round((base / 2) * 1.02); case 'quarterly': return Math.round((base / 4) * 1.03); default: return base; } } function toRiderValues(raw: LeadRecord['riders']): string[] { if (!raw) return []; if (Array.isArray(raw)) return raw as string[]; return String(raw) .split(',') .map((s) => s.trim()) .filter(Boolean); } export function RecommendScreen() { const { client } = useZino(); const navigate = useNavigate(); const [params] = useSearchParams(); const instanceParam = params.get('instance'); const { records, refetch } = useLeads(); // Field config (product lookup template, frequency + rider options) from the // live form schema, not hardcoded. const schemaQ = useQuery(() => client.formSchema(ACTIVITIES.RECOMMEND_PRODUCT.uid), []); const productField = useMemo(() => fieldFromSchema(schemaQ.data, F.product), [schemaQ.data]); const freqOptions = useMemo(() => fieldFromSchema(schemaQ.data, F.premiumFrequency)?.options ?? [], [schemaQ.data]); const riderOptions = useMemo(() => fieldFromSchema(schemaQ.data, F.riders)?.options ?? [], [schemaQ.data]); // Leads where Recommend Product is valid (state = Meeting Scheduled). const eligible = useMemo( () => records.filter((r) => r.current_state_name === 'Meeting Scheduled'), [records], ); const [selectedId, setSelectedId] = useState(''); useEffect(() => { if (instanceParam) setSelectedId(instanceParam); else if (!selectedId && eligible[0]) setSelectedId(String(eligible[0].instance_id)); }, [instanceParam, eligible, selectedId]); const record = useMemo( () => records.find((r) => String(r.instance_id) === selectedId), [records, selectedId], ); // Form state — seeded from the instance's existing values when present. const [product, setProduct] = useState(null); const [sum, setSum] = useState(2000000); const [freq, setFreq] = useState('annual'); const [premium, setPremium] = useState(0); const [premiumTouched, setPremiumTouched] = useState(false); const [riders, setRiders] = useState(['critical_illness', 'accidental_death']); const [notes, setNotes] = useState(''); useEffect(() => { if (!record) return; setProduct((record.recommended_product as LookupValue) ?? null); setSum(record.sum_assured || 2000000); setFreq(record.premium_frequency || 'annual'); setRiders(toRiderValues(record.riders)); setNotes(record.recommendation_notes || ''); setPremiumTouched(false); if (record.premium_amount) { setPremium(record.premium_amount); setPremiumTouched(true); } }, [record]); const computed = indicativePremium(sum, freq); const effectivePremium = premiumTouched ? premium : computed; const [submitting, setSubmitting] = useState(false); const [result, setResult] = useState<{ ok: boolean; msg: string } | null>(null); async function submit() { if (!record) return; if (!product) { setResult({ ok: false, msg: 'Pick a product from the catalogue.' }); return; } setSubmitting(true); setResult(null); try { await client.performActivity(record.instance_id, ACTIVITIES.RECOMMEND_PRODUCT.uid, { [F.product]: product, [F.sumAssured]: sum, [F.premiumAmount]: effectivePremium, [F.premiumFrequency]: freq, [F.riders]: riders, [F.notes]: notes, }); setResult({ ok: true, msg: 'Recommendation submitted — lead advanced to Product Recommended.' }); refetch(); } catch (e) { setResult({ ok: false, msg: e instanceof Error ? e.message : ((e as { message?: string })?.message ?? 'Submit failed') }); } finally { setSubmitting(false); } } const lead = record; const incomeMultiple = lead?.annual_income ? (sum / lead.annual_income).toFixed(1) : '—'; return (
{/* context strip + lead picker */}
{lead ? ( <>
{lead.lead_name ?? `Lead ${lead.instance_id}`} · #{lead.instance_id}
{regionOf(lead.assigned_region) ?? lead.city ?? '—'} · {lead.product_interest ?? 'No stated interest'} · income ₹ {formatINR(lead.annual_income ?? 0)}
) : (
Select a lead at the Meeting Scheduled stage.
)} setSum(Number(e.target.value) || 0)} /> { setPremium(Number(e.target.value) || 0); setPremiumTouched(true); }} />