// Turn a raw record/detail-view field value into a display string. The Zino // view APIs return heterogeneous shapes — scalars, phone objects, file blobs, // {label,value} option objects, and arrays (grids) — so normalize them here. interface PhoneLike { phone_with_dial_code?: string; phone?: string; dial_code?: string; } function isObject(v: unknown): v is Record { return typeof v === 'object' && v !== null && !Array.isArray(v); } /** Best-effort single-line display string for a field value. */ export function formatValue(value: unknown): string { if (value == null || value === '') return '—'; if (typeof value === 'boolean') return value ? 'Yes' : 'No'; if (typeof value === 'number' || typeof value === 'string') return String(value); if (Array.isArray(value)) { if (value.length === 0) return '—'; return `${value.length} item${value.length === 1 ? '' : 's'}`; } if (isObject(value)) { const o = value as PhoneLike & Record; // Phone if (o.phone_with_dial_code) return String(o.phone_with_dial_code); if (o.phone) return `${o.dial_code ?? ''}${o.phone}`.trim(); // Option / lookup {label,value} if ('label' in o && o.label != null) return String(o.label); // File / image blob if ('original_name' in o && o.original_name != null) return String(o.original_name); if ('url' in o && o.url != null) return String(o.url); if ('name' in o && o.name != null) return String(o.name); if ('value' in o && o.value != null) return String(o.value); // Custom workflow lookups if ('business_name_2' in o && o.business_name_2 != null) return String(o.business_name_2); if ('business_name_3' in o && o.business_name_3 != null) return String(o.business_name_3); if ('business_name' in o && o.business_name != null) return String(o.business_name); } try { return JSON.stringify(value); } catch { return String(value); } } /** Number with Indian-locale grouping; falls back to the raw string. */ export function formatNumber(value: unknown): string { const n = typeof value === 'number' ? value : Number(value); return Number.isFinite(n) ? n.toLocaleString('en-IN') : formatValue(value); }