import type { PieceModelProduct, PieceModelStructure } from '~/shared/types/inventory' /** * Extract the products array from a piece model structure, defaulting to []. */ export const getStructureProducts = (structure: PieceModelStructure | null): PieceModelProduct[] => Array.isArray(structure?.products) ? structure.products : [] /** * Build a human-readable label for a single product requirement. */ export const describeProductRequirement = (requirement: PieceModelProduct, index: number): string => { if (!requirement) { return `Produit ${index + 1}` } const parts: string[] = [] if (requirement.role) { parts.push(requirement.role) } if (requirement.typeProductLabel) { parts.push(requirement.typeProductLabel) } else if (requirement.typeProductId) { parts.push(`Catégorie #${requirement.typeProductId}`) } if (requirement.familyCode) { parts.push(`Famille ${requirement.familyCode}`) } if (parts.length === 0) { parts.push(`Produit ${index + 1}`) } return parts.join(' • ') } /** * Build description strings for every product requirement in a structure. */ export const buildProductRequirementDescriptions = ( products: PieceModelProduct[], ): string[] => products.map((requirement, index) => describeProductRequirement(requirement, index)) /** * Build the entry objects used to render product selection inputs. */ export const buildProductRequirementEntries = ( products: PieceModelProduct[], keyPrefix: string, ) => products.map((requirement, index) => ({ index, key: `${keyPrefix}-${index}-${requirement?.typeProductId || 'any'}`, label: describeProductRequirement(requirement, index), typeProductId: requirement?.typeProductId ? String(requirement.typeProductId) : null, })) /** * Resize the selections array to match the expected count, preserving existing values. */ export const resizeProductSelections = ( current: (string | null)[], count: number, ): (string | null)[] => Array.from({ length: count }, (_, index) => current[index] ?? null) /** * Return true when all required product slots have a non-empty string value, * or when no product selection is required. */ export const areProductSelectionsFilled = ( requiresSelection: boolean, entries: { index: number }[], selections: (string | null)[], ): boolean => !requiresSelection || entries.every((entry) => { const value = selections[entry.index] return typeof value === 'string' && value.trim().length > 0 }) /** * Set a single product selection by index, returning a new array. */ export const applyProductSelection = ( current: (string | null)[], index: number, value: string | null, ): (string | null)[] => { const normalized = typeof value === 'string' ? value : null const next = [...current] next[index] = normalized return next } /** * Extract normalized product IDs from the current selections based on requirement entries. */ export const collectNormalizedProductIds = ( entries: { index: number }[], selections: (string | null)[], ): string[] => entries .map((entry) => selections[entry.index]) .filter((value): value is string => typeof value === 'string' && value.trim().length > 0) .map((value) => value.trim())