import type { CostCentreGroup } from "@/app/(portal)/po/new/new-po-form"; type VesselLike = { id: string; name: string; code: string; siteId: string | null }; type SiteLike = { id: string; name: string }; /** * Builds the grouped cost-centre list used by PO form dropdowns. * Each group = one site (as an optgroup), with the site itself as a selectable * option followed by its vessels. * Vessels with no site appear under an "Unassigned Vessels" group at the end. */ export function buildCostCentreGroups( vessels: VesselLike[], sites: SiteLike[] ): CostCentreGroup[] { const groups: CostCentreGroup[] = sites.map((s) => ({ siteId: s.id, siteName: s.name, siteRef: `s:${s.id}`, vessels: vessels .filter((v) => v.siteId === s.id) .map((v) => ({ ref: `v:${v.id}`, label: `${v.code} — ${v.name}` })), })); const unassigned = vessels.filter((v) => !v.siteId); if (unassigned.length > 0) { groups.push({ siteId: null, siteName: "Unassigned Vessels", siteRef: null, vessels: unassigned.map((v) => ({ ref: `v:${v.id}`, label: `${v.code} — ${v.name}` })), }); } return groups; } /** * Builds grouped accounting codes for the SearchableSelect component. * Only returns leaf items (no children), grouped by sub-category. */ export function buildAccountGroups( leafAccounts: { id: string; code: string; name: string; parent: { name: string; code: string; parent: { name: string; code: string } | null } | null; }[] ) { const map = new Map(); for (const a of leafAccounts) { const subLabel = a.parent ? `${a.parent.code} — ${a.parent.name}` : "Uncategorised"; const topLabel = a.parent?.parent ? `${a.parent.parent.name} › ` : ""; const key = `${topLabel}${subLabel}`; if (!map.has(key)) map.set(key, []); map.get(key)!.push({ id: a.id, code: a.code, name: a.name }); } return Array.from(map.entries()).map(([group, items]) => ({ group, items })); }