57 lines
1.6 KiB
TypeScript
57 lines
1.6 KiB
TypeScript
export type GroupableDoc = {
|
|
id: string;
|
|
documentDate?: string | null;
|
|
sender?: { displayName: string } | null;
|
|
receivers?: { displayName: string }[];
|
|
};
|
|
|
|
export type DocumentGroup<T extends GroupableDoc> = {
|
|
label: string;
|
|
documents: T[];
|
|
};
|
|
|
|
const GROUPABLE_SORTS = ['DATE', 'SENDER', 'RECEIVER'] as const;
|
|
type GroupableSort = (typeof GROUPABLE_SORTS)[number];
|
|
|
|
export function groupDocuments<T extends GroupableDoc>(
|
|
docs: T[],
|
|
sort: string,
|
|
fallbackLabel: string
|
|
): DocumentGroup<T>[] {
|
|
if (docs.length === 0) return [];
|
|
if (!GROUPABLE_SORTS.includes(sort as GroupableSort)) {
|
|
return [{ label: '', documents: [...docs] }];
|
|
}
|
|
|
|
const groupMap = new Map<string, T[]>();
|
|
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<T extends GroupableDoc>(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 [];
|
|
}
|