feat(14-03): add kind prop + PAX8_COMPANY_GROUPS to DetailModal

- Add optional kind?: 'ticket' | 'company' | 'pax8_company' prop to DetailModalProps
- Add PAX8_COMPANY_GROUPS field-group set (Identity + System, camelCase keys)
- detectGroups() checks kind === 'pax8_company' first, before existing sniff branches
- TICKET_GROUPS/COMPANY_GROUPS and their detection branches unchanged
This commit is contained in:
lorentz 2026-07-11 14:28:15 -04:00
parent d2dfc341da
commit 3492a16176

View file

@ -131,6 +131,34 @@ const COMPANY_GROUPS: FieldGroup[] = [
},
];
// PAX8 company drill-down (kind="pax8_company") — additive only, does not
// touch TICKET_GROUPS/COMPANY_GROUPS or their existing detection branches.
// Field keys are camelCase because the /pax8 page passes an already-
// transformed object (see 14-03-PLAN.md interfaces block).
const PAX8_COMPANY_GROUPS: FieldGroup[] = [
{
label: 'Identity',
paired: 'System',
fields: [
{ key: 'name', label: 'Name' },
{ key: 'status', label: 'Status' },
{ key: 'city', label: 'City' },
{ key: 'stateOrProvince', label: 'State/Province' },
{ key: 'country', label: 'Country' },
{ key: 'website', label: 'Website', type: 'url' },
],
},
{
label: 'System',
paired: 'Identity',
fields: [
{ key: 'id', label: 'Record ID', type: 'id' },
{ key: 'syncedAt', label: 'Synced At', type: 'date' },
{ key: 'isDeleted', label: 'Deleted', type: 'bool' },
],
},
];
// ── Helpers ────────────────────────────────────────────────────────────────────
function resolveLabel(key: string, value: any, type: FieldType | undefined, lookups: Lookups, tz: string): { display: React.ReactNode; isEmpty: boolean } {
@ -253,7 +281,8 @@ function resolveLabel(key: string, value: any, type: FieldType | undefined, look
return { display: <span className="text-sm">{String(value)}</span>, isEmpty: false };
}
function detectGroups(data: Record<string, any>): FieldGroup[] {
function detectGroups(data: Record<string, any>, kind?: 'ticket' | 'company' | 'pax8_company'): FieldGroup[] {
if (kind === 'pax8_company') return PAX8_COMPANY_GROUPS;
if ('ticket_number' in data) return TICKET_GROUPS;
if ('company_name' in data) return COMPANY_GROUPS;
return [{ label: 'Fields', fields: Object.keys(data).map(k => ({ key: k, label: k })) }];
@ -269,9 +298,10 @@ interface DetailModalProps {
title: string;
data: Record<string, any> | null;
fields?: Array<{ key: string; label: string; render?: (value: any) => React.ReactNode }>;
kind?: 'ticket' | 'company' | 'pax8_company';
}
export default function DetailModal({ open, onOpenChange, title, data, fields }: DetailModalProps) {
export default function DetailModal({ open, onOpenChange, title, data, fields, kind }: DetailModalProps) {
const tz = useUserTimezone();
const [copiedField, setCopiedField] = useState<string | null>(null);
const [lookups, setLookups] = useState<Lookups>(EMPTY_LOOKUPS);
@ -328,7 +358,7 @@ export default function DetailModal({ open, onOpenChange, title, data, fields }:
setTimeout(() => setCopiedField(null), 2000);
};
const groups = detectGroups(data);
const groups = detectGroups(data, kind);
// Raw tab: all fields
const rawFields = fields || Object.keys(data).map(k => ({ key: k, label: k, render: undefined }));