Mobile PWA port of the desktop console: bottom-sheet modals, card-list record views, bottom tab nav, vite-plugin-pwa (manifest, service worker, icons). API layer, workflow UIDs, and design tokens reused verbatim.
56 lines
2.2 KiB
TypeScript
56 lines
2.2 KiB
TypeScript
// 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<string, unknown> {
|
|
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<string, unknown>;
|
|
// 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);
|
|
}
|