import type { FlooringPlan, PieceKey, PlanFocus, PlanMaterial, Project, SkirtingPlan, } from './types'; import type { CutData } from './cut-list'; export const pieceKey = (material: PlanMaterial, id: string): PieceKey => `${material}:${id}`; export const boardKey = (material: PlanMaterial, id: string) => `${material === 'flooring' ? 'floor' : 'skirting'}:${id}`; export interface BoardMatches { pieceKeys: Set; roomIds: string[]; boardKeys: Set; materials: Set; } /** User text searches cut codes or room names. Location is explicit, never encoded as a query. */ export function findBoardMatches( project: Project, flooring: FlooringPlan, skirting: SkirtingPlan, query: string, focus: PlanFocus | null = null, ): BoardMatches { const text = query.trim().toLowerCase().replace(/\s+/g, ' '); const result: BoardMatches = { pieceKeys: new Set(), roomIds: [], boardKeys: new Set(), materials: new Set(), }; if (!text && !focus) return result; const codes = new Set(text.split(/\s*[+,]\s*/)); const matchingRooms = new Set( project.rooms .filter((room) => room.name.toLowerCase().replace(/\s+/g, ' ').includes(text)) .map((room) => room.id), ); const roomIds = new Set(); for (const [material, pieces] of [ ['flooring', flooring.pieces], ['skirting', skirting.pieces], ] as const) { for (const piece of pieces) { const matches = focus ? material === focus.material && (focus.kind === 'board' ? piece.stockId : piece.id) === focus.id : codes.has(piece.id.toLowerCase()) || matchingRooms.has(piece.roomId); if (!matches) continue; result.pieceKeys.add(pieceKey(material, piece.id)); roomIds.add(piece.roomId); result.boardKeys.add(boardKey(material, piece.stockId)); result.materials.add(material); } } result.roomIds = project.rooms.filter((room) => roomIds.has(room.id)).map((room) => room.id); return result; } export function focusLabel(focus: PlanFocus, cuts: CutData): string { if (focus.kind === 'piece') return focus.id; const group = (focus.material === 'flooring' ? cuts.floorGroups : cuts.skirtGroups).get(focus.id); return ( group?.map((piece) => piece.id).join(' + ') || (focus.material === 'flooring' ? 'Uncut floorboard' : 'Uncut skirting board') ); }