import { formatPhone } from '~/utils/formatters/phone'; export interface ConstructeurSummary { id: string; name?: string | null; email?: string | null; phone?: string | null; } export interface ConstructeurLinkEntry { linkId?: string; constructeurId: string; constructeur?: ConstructeurSummary | null; supplierReference: string | null; } export const constructeurIdsFromLinks = (links: ConstructeurLinkEntry[]): string[] => links.map(l => l.constructeurId).filter(Boolean); export const parseConstructeurLinksFromApi = ( apiLinks: any[], ): ConstructeurLinkEntry[] => { if (!Array.isArray(apiLinks)) return []; return apiLinks .filter(link => link && typeof link === 'object') .map(link => ({ linkId: link.id || (typeof link['@id'] === 'string' ? link['@id'].split('/').pop() : undefined), constructeurId: typeof link.constructeur === 'string' ? link.constructeur.split('/').pop()! : link.constructeur?.id || '', constructeur: typeof link.constructeur === 'object' ? link.constructeur : null, supplierReference: link.supplierReference ?? null, })); }; const isObject = (value: unknown): value is Record => Boolean(value) && typeof value === 'object' && !Array.isArray(value); const toStringId = (value: unknown): string | null => { if (typeof value !== 'string') { return null; } const trimmed = value.trim(); if (!trimmed) { return null; } if (trimmed.includes('/')) { const parts = trimmed.split('/').filter(Boolean); return parts.length ? (parts[parts.length - 1] ?? null) : null; } return trimmed; }; export const uniqueConstructeurIds = (...sources: unknown[]): string[] => { const ids = new Set(); const pushId = (value: unknown) => { const id = toStringId(value); if (id) { ids.add(id); } }; const explore = (value: unknown): void => { if (!value) { return; } if (Array.isArray(value)) { value.forEach(explore); return; } if (typeof value === 'string') { pushId(value); return; } if (isObject(value)) { if (Array.isArray(value.constructeurIds)) { value.constructeurIds.forEach(pushId); } if (value.constructeurId) { pushId(value.constructeurId); } if (Array.isArray(value.constructeurs)) { value.constructeurs.forEach(explore); } if (value.constructeur) { explore(value.constructeur); } // Extract ID from constructeur-like objects, but skip component/piece/product entities if (typeof value.id === 'string' && !value.typeComposant && !value.typePiece && !value.typeProduct) { pushId(value.id); } return; } }; sources.forEach(explore); return Array.from(ids); }; export const resolveConstructeurs = ( ids: string[], ...candidatePools: Array ): ConstructeurSummary[] => { if (!Array.isArray(ids) || ids.length === 0) { return []; } const index = new Map(); const register = (pool?: ConstructeurSummary[] | null) => { if (!Array.isArray(pool)) { return; } pool.forEach((entry) => { if (entry && typeof entry === 'object' && typeof entry.id === 'string') { index.set(entry.id, entry); } }); }; candidatePools.forEach(register); return ids .map((id) => index.get(id)) .filter((item): item is ConstructeurSummary => Boolean(item)) .map((item) => ({ ...item })); }; export const formatConstructeurContact = ( constructeur?: ConstructeurSummary | null, ): string => { if (!constructeur) { return ''; } const formattedPhone = formatPhone(constructeur.phone); const phone = formattedPhone || constructeur.phone || null; return [constructeur.email, phone].filter(Boolean).join(' • '); };