export type GroupableDoc = { id: string; documentDate?: string | null; sender?: { displayName: string } | null; receivers?: { displayName: string }[]; }; export type DocumentGroup = { label: string; documents: T[]; }; const GROUPABLE_SORTS = ['DATE', 'SENDER', 'RECEIVER'] as const; type GroupableSort = (typeof GROUPABLE_SORTS)[number]; export function groupDocuments( docs: T[], sort: string, fallbackLabel: string ): DocumentGroup[] { if (docs.length === 0) return []; if (!GROUPABLE_SORTS.includes(sort as GroupableSort)) { return [{ label: '', documents: [...docs] }]; } const groupMap = new Map(); const fallbackDocs: T[] = []; for (const doc of docs) { const keys = extractGroupKeys(doc, sort as GroupableSort); if (keys.length === 0) { fallbackDocs.push(doc); } else { for (const key of keys) { if (!groupMap.has(key)) groupMap.set(key, []); groupMap.get(key)!.push(doc); } } } const groups = [...groupMap.entries()].map(([label, documents]) => ({ label, documents })); if (fallbackDocs.length > 0) groups.push({ label: fallbackLabel, documents: fallbackDocs }); return groups; } function extractGroupKeys(doc: T, sort: GroupableSort): string[] { if (sort === 'DATE') { const year = doc.documentDate ? String(new Date(doc.documentDate + 'T12:00:00').getFullYear()) : null; return year ? [year] : []; } if (sort === 'SENDER') return doc.sender ? [doc.sender.displayName] : []; if (sort === 'RECEIVER') return (doc.receivers ?? []).map((r) => r.displayName); return []; }