init
This commit is contained in:
45
src/data.ts
Normal file
45
src/data.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import type { BuyerDocument, PersonGroup } from "./types.ts";
|
||||
|
||||
const text = (value: unknown) => typeof value === "string" ? value.trim() : "";
|
||||
const normalize = (value: unknown) => text(value).toLocaleLowerCase();
|
||||
|
||||
export function validateDocuments(value: unknown): BuyerDocument[] {
|
||||
if (!Array.isArray(value)) throw new Error("JSON root must be an array.");
|
||||
return value.map((item, index) => {
|
||||
if (!item || typeof item !== "object") throw new Error(`Record ${index + 1} is not an object.`);
|
||||
const doc = item as Partial<BuyerDocument>;
|
||||
if (!text(doc.file_name) || !text(doc.name_from_filename) || !text(doc._letter)) {
|
||||
throw new Error(`Record ${index + 1} is missing file_name, name_from_filename, or _letter.`);
|
||||
}
|
||||
return doc as BuyerDocument;
|
||||
});
|
||||
}
|
||||
|
||||
export function groupDocuments(documents: BuyerDocument[]): PersonGroup[] {
|
||||
const groups = new Map<string, BuyerDocument[]>();
|
||||
for (const doc of documents) {
|
||||
const key = doc.name_from_filename.trim();
|
||||
const bucket = groups.get(key) ?? [];
|
||||
bucket.push(doc);
|
||||
groups.set(key, bucket);
|
||||
}
|
||||
|
||||
return [...groups.entries()]
|
||||
.map(([key, docs]) => {
|
||||
docs.sort((a, b) => a.file_name.localeCompare(b.file_name));
|
||||
const preferred = docs.find((d) => text(d.prospective_buyer))?.prospective_buyer;
|
||||
const searchText = normalize([
|
||||
key,
|
||||
preferred,
|
||||
...docs.flatMap((d) => [d.types_of_business_raw, d.notes_business_raw, d.address]),
|
||||
].filter(Boolean).join("\n"));
|
||||
return { key, displayName: text(preferred) || key, documents: docs, searchText };
|
||||
})
|
||||
.sort((a, b) => a.key.localeCompare(b.key));
|
||||
}
|
||||
|
||||
export function filterGroups(groups: PersonGroup[], query: string): PersonGroup[] {
|
||||
const terms = normalize(query).split(/\s+/).filter(Boolean);
|
||||
if (!terms.length) return groups;
|
||||
return groups.filter((group) => terms.every((term) => group.searchText.includes(term)));
|
||||
}
|
||||
Reference in New Issue
Block a user