// Activity metadata + the per-state "next action" map. Field schemas are no // longer mirrored here — fetches them live from the form-screens // endpoint (see api/schema.ts), so the form layout never drifts from config. export type FieldType = | 'text' | 'email' | 'phone' | 'number' | 'date' | 'datetime' | 'longtext' | 'select' | 'multiselect' | 'boolean' | 'lookup' | 'ocr' | 'file'; export interface FieldOption { value: string; label: string; } export interface OcrMapping { extraction_key: string; target_field: string; } /** A renderable form field. Built at runtime by api/schema.ts from the live * form-screens config; consumed by and the bespoke screens. */ export interface FieldDef { id: string; label: string; type: FieldType; required?: boolean; options?: FieldOption[]; prefix?: string; placeholder?: string; /** Companion/record key to seed from (defaults to id minus the _input suffix). */ seedKey?: string; // lookup lookupTemplate?: string; lookupDisplay?: string[]; // columns shown in the label lookupStorage?: string[]; // columns persisted on submit // ocr docLabel?: string; // "PAN" / "Aadhaar" ocrMappings?: OcrMapping[]; } /** Activity display copy + uid. Fields come from the schema, not from here. */ export interface ActivityMeta { uid: string; name: string; submitLabel: string; /** Past-tense confirmation, e.g. "advanced to Qualified". */ done: string; } // Activity keys are stable, human-readable handles used by STATE_NEXT. export const ACTIVITY_META = { capture: { uid: 'cc1a73d5-61e1-4416-af30-2b1eeb623a58', name: 'Capture Lead', submitLabel: 'Create lead', done: 'created — added to the pipeline as a New Lead', }, qualify: { uid: '6b741e44-37f2-4bb0-90ab-ed139f03b7b3', name: 'Qualify Lead', submitLabel: 'Qualify lead', done: 'advanced to Qualified', }, assign: { uid: 'da61aaa1-003b-4601-9f42-f93ff230497f', name: 'Assign Lead', submitLabel: 'Assign lead', done: 'advanced to Assigned', }, contact: { uid: 'fea6b3a8-846d-4f6f-8e92-033c4cf4b6e2', name: 'Log First Contact', submitLabel: 'Log contact', done: 'advanced to Contacted', }, schedule: { uid: 'c444d32f-ed6a-4e36-b8b7-b82e73a141d4', name: 'Schedule Meeting', submitLabel: 'Schedule meeting', done: 'advanced to Meeting Scheduled', }, assess: { uid: 'ba3d3e7f-0d3f-49f2-a156-6cace33c228a', name: 'Assess Eligibility', submitLabel: 'Submit assessment', done: 'advanced to Eligibility Assessed', }, underwrite: { uid: 'ed8ec0dc-4c2c-4d9e-b798-757f6a9d4730', name: 'Submit Underwriting', submitLabel: 'Submit underwriting', done: 'advanced to Underwriting', }, issue: { uid: '7b8fb734-a780-4c6a-837b-c5e7ca28e489', name: 'Issue Policy', submitLabel: 'Issue policy', done: 'advanced to Policy Issued', }, onboard: { uid: 'ae415f4e-a33e-432e-882f-733238de8bcc', name: 'Onboard Customer', submitLabel: 'Complete onboarding', done: 'advanced to Customer 360', }, disqualify: { uid: 'ea99fc60-caba-45c1-afc1-7386a2fa9220', name: 'Disqualify', submitLabel: 'Disqualify lead', done: 'moved to Disqualified', }, } satisfies Record; export type ActivityKey = keyof typeof ACTIVITY_META; // OCR field configs for Collect Documents (extraction → mapped target inputs). export const OCR_FIELDS: Record = { pan: { id: 'pan_ocr_2', docLabel: 'PAN', mappings: [{ extraction_key: 'pan_number', target_field: 'pan_number_input' }], }, aadhaar: { id: 'aadhar_ocr_2', docLabel: 'Aadhaar', mappings: [{ extraction_key: 'aadhaar_number', target_field: 'aadhaar_number_input' }], }, }; // Per-state next action. `route` → dedicated rich screen; else inline form. // Routed steps (recommend / documents / underwriting / issue) render their own // screen, so `activity` is only set when the step renders an inline form. export interface NextAction { activity?: ActivityKey; route?: string; /** Button label for routed steps. */ label?: string; } export const STATE_NEXT: Record = { 'New Lead': { activity: 'qualify' }, Qualified: { activity: 'assign', route: '/assign', label: 'Assign lead' }, Assigned: { activity: 'contact' }, Contacted: { activity: 'schedule' }, 'Meeting Scheduled': { route: '/recommend', label: 'Recommend product' }, 'Product Recommended': { route: '/documents', label: 'Collect documents' }, 'Documents Collected': { activity: 'assess' }, 'Eligibility Assessed': { route: '/underwriting', label: 'Submit underwriting' }, Underwriting: { route: '/issue', label: 'Issue policy' }, 'Policy Issued': { activity: 'onboard' }, }; // States from which Disqualify is a valid (secondary) action. export const DISQUALIFY_STATES = new Set([ 'New Lead', 'Qualified', 'Assigned', 'Contacted', 'Meeting Scheduled', 'Product Recommended', 'Documents Collected', 'Eligibility Assessed', 'Underwriting', ]);