import type { ProsthesisCatalogEntry } from '@/types/treatment-catalog'; import { splitProsthesisGroupCode } from '@/components/treatment/prosthesisTypeDisplay'; /** Non-breaking spaces so the gap around · does not collapse between inline spans. */ export const PROSTHESIS_JOB_PATH_SEP = '\u00a0·\u00a0'; type CatalogLite = readonly Pick< ProsthesisCatalogEntry, 'code' | 'label' | 'category' | 'subcategory' >[]; export type ProsthesisMessageFn = (key: string) => string; function sameLabel(a: string, b: string): boolean { return a.localeCompare(b, undefined, { sensitivity: 'accent' }) === 0; } function leafFromCatalogLabel(label: string): string { const parts = label .split(/\s*·\s*/) .map((part) => part.trim()) .filter(Boolean); return parts.length > 1 ? parts[parts.length - 1] : label; } function humanizeCode(code: string): string { return code .split('_') .filter(Boolean) .map((part) => part.charAt(0).toUpperCase() + part.slice(1)) .join(' '); } /** Picker root whose title is a slash-joined list of its children (redundant in job titles). */ const SKIP_CATEGORY_IN_JOB_PATH = new Set(['indirect']); /** Category → subcategory → last picker node for one catalog code. */ export function prosthesisJobPathParts( code: string, catalog: CatalogLite, t: ProsthesisMessageFn, ): { ancestors: string[]; leaf: string } { const entry = catalog.find((item) => item.code === code); if (!entry) { return { ancestors: [], leaf: humanizeCode(code) }; } const ancestors: string[] = []; const subcategory = entry.subcategory?.trim() ?? ''; const skipCategory = SKIP_CATEGORY_IN_JOB_PATH.has(entry.category); if (entry.category && !skipCategory) { ancestors.push(t(`category_${entry.category}`)); } if (subcategory) { ancestors.push(t(`sub_${subcategory}`)); } const leaf = leafFromCatalogLabel(entry.label) || entry.label || code; const uniqueAncestors: string[] = []; for (const ancestor of ancestors) { if (!ancestor || sameLabel(ancestor, leaf)) continue; if (uniqueAncestors.some((existing) => sameLabel(existing, ancestor))) continue; uniqueAncestors.push(ancestor); } return { ancestors: uniqueAncestors, leaf }; } function formatProsthesisJobPath( parts: { ancestors: string[]; leaf: string }, ): string { return [...parts.ancestors, parts.leaf].filter(Boolean).join(PROSTHESIS_JOB_PATH_SEP); } /** Full picker path for a type or stacked `code+code` group. */ export function prosthesisJobPathLabel( code: string, catalog: CatalogLite, t: ProsthesisMessageFn, ): string { return splitProsthesisGroupCode(code) .map((part) => formatProsthesisJobPath(prosthesisJobPathParts(part, catalog, t))) .join(' + '); }