const formatSize = (size) => { if (size === undefined || size === null) return '—' if (size === 0) return '0 B' const units = ['B', 'KB', 'MB', 'GB'] const index = Math.min(units.length - 1, Math.floor(Math.log(size) / Math.log(1024))) const formatted = size / Math.pow(1024, index) return `${formatted.toFixed(1)} ${units[index]}` } const renderPrintField = (label, value, fallback = '—') => { const display = value !== undefined && value !== null && value !== '' ? value : fallback return `` } const renderPrintCustomFields = (fields = [], title, sectionClass = 'print-section') => { if (!fields.length) return '' const items = fields .map((field) => ``) .join('') return `

${title}

` } const renderPrintDocuments = (documents = [], title, sectionClass = 'print-section') => { if (!documents.length) return '' const rows = documents .map((doc) => `${doc.name}${doc.type}${doc.size}`) .join('') return `

${title}

${rows}
` } const renderPrintPieces = ( pieces = [], title = 'Pièces indépendantes', sectionClass = 'print-section print-section--pieces', ) => { if (!pieces.length) return '' const cards = pieces .map((piece, idx) => { const indexLabel = piece.indexPath ? piece.indexPath.join('.') : `${idx + 1}` const constructeurBadge = piece.constructeur?.name ? `Constructeur: ${piece.constructeur.name}` : '' const customFields = (piece.customFields || []) .filter((field) => field.value && field.value !== '—' && field.value !== '') .map( (field) => `
  • ${field.label} ${field.value}
  • `, ) .join('') const customFieldsBlock = customFields ? `` : '' const documentsBlock = (piece.documents || []).length ? `` : '' return ` ` }) .join('') return `

    ${title}

    ` } const renderPrintComponents = (components = [], depth = 0, indexPath = []) => { if (!components.length) return '' return components .map((component, idx) => { const badges = [] if (component.constructeur?.name) { badges.push(`Constructeur: ${component.constructeur.name}`) } const sectionClass = `print-section print-section--component print-section-depth-${Math.min(depth, 3)}` const currentIndex = [...indexPath, idx + 1] const indexLabel = currentIndex.join('.') return `

    ${indexLabel} Composant : ${component.name}

    ${component.description ? `` : ''} ${badges.length ? `
    ${badges.map((badge) => `${badge}`).join('')}
    ` : ''} ${renderPrintCustomFields( component.customFields, 'Champs personnalisés', 'print-section print-subsection print-section--custom-fields', )} ${renderPrintPieces( (component.pieces || []).map((piece, pieceIdx) => ({ ...piece, indexPath: [...currentIndex, pieceIdx + 1] })), 'Pièces du composant', 'print-section print-subsection print-section--pieces', )} ${renderPrintDocuments( component.documents, 'Documents du composant', 'print-section print-subsection print-section--documents', )} ${renderPrintComponents(component.subComponents || [], depth + 1, currentIndex)}
    ` }) .join('') } const normalizeDocuments = (docs = []) => { return docs.map((doc) => ({ id: doc.id, name: doc.name || doc.filename || 'Document', type: doc.mimeType || doc.type || '—', size: formatSize(doc.size), })) } const normalizeCustomFields = (values = []) => { return values.map((value) => ({ id: value.id, label: value.customField?.name || 'Champ', value: value.value || value.customField?.defaultValue || '—', })) } const normalizeConstructeur = (constructeur) => { if (!constructeur) return null return { name: constructeur.name || '—', contact: [constructeur.email, constructeur.phone].filter(Boolean).join(' • ') || '—', } } const normalizePiece = (piece) => ({ id: piece.id, name: piece.name || 'Pièce sans nom', description: piece.description || '', reference: piece.reference || '', customFields: normalizeCustomFields(piece.customFieldValues || []), documents: normalizeDocuments(piece.documents || []), constructeur: normalizeConstructeur(piece.constructeur), indexPath: piece.indexPath || null, }) const normalizeComponent = (component) => ({ id: component.id, name: component.name || 'Composant sans nom', description: component.description || '', customFields: normalizeCustomFields(component.customFieldValues || []), documents: normalizeDocuments(component.documents || []), pieces: (component.pieces || []).map(normalizePiece), subComponents: (component.sousComposants || component.subComponents || []).map(normalizeComponent), constructeur: normalizeConstructeur(component.constructeur), }) export const buildMachinePrintContext = ({ machine, machineName, machineReference, machineEmplacement, machinePieces = [], components = [], selection, }) => { const selectionState = selection || {} const machineSelection = selectionState.machine || {} const componentSelection = selectionState.components || {} const pieceSelection = selectionState.pieces || {} const includeMachineInfo = machineSelection.info !== false const includeMachineCustomFields = machineSelection.customFields !== false const includeMachineDocuments = machineSelection.documents !== false const isComponentSelected = (id) => { if (!id) return true if (Object.prototype.hasOwnProperty.call(componentSelection, id)) { return componentSelection[id] } return true } const isPieceSelected = (id) => { if (!id) return true if (Object.prototype.hasOwnProperty.call(pieceSelection, id)) { return pieceSelection[id] } return true } const machineBadges = [] if (machine?.typeMachine?.category) { machineBadges.push(machine.typeMachine.category) } if (machine?.site?.name) { machineBadges.push(`Site: ${machine.site.name}`) } if (machineReference) { machineBadges.push(`Ref: ${machineReference}`) } const normalizedPieces = machinePieces .map(normalizePiece) .filter((piece) => isPieceSelected(piece.id)) .map((piece, idx) => ({ ...piece, indexPath: [idx + 1], })) const normalizedComponents = components.map(normalizeComponent) const filterComponentTree = (component) => { const filteredPieces = (component.pieces || []).filter((piece) => isPieceSelected(piece.id)) const filteredSubComponents = (component.subComponents || []) .map(filterComponentTree) .filter(Boolean) const includeSelf = isComponentSelected(component.id) const shouldInclude = includeSelf || filteredPieces.length > 0 || filteredSubComponents.length > 0 if (!shouldInclude) { return null } return { ...component, pieces: filteredPieces, subComponents: filteredSubComponents, } } const filteredComponents = normalizedComponents .map(filterComponentTree) .filter(Boolean) return { generatedAt: new Date().toLocaleString('fr-FR'), machine: { id: machine?.id || null, name: machineName, description: machine?.description || '', typeDescription: machine?.typeMachine?.description || '', reference: machineReference, emplacement: machineEmplacement, site: machine?.site?.name || '', category: machine?.typeMachine?.category || '', badges: machineBadges, constructeur: normalizeConstructeur(machine?.constructeur), includeInfo: includeMachineInfo, customFields: includeMachineCustomFields ? normalizeCustomFields(machine?.customFieldValues || []) : [], documents: includeMachineDocuments ? normalizeDocuments(machine?.documents || []) : [], }, components: filteredComponents, pieces: normalizedPieces, } } export const buildMachinePrintHtml = (context, styles) => { const title = context.machine.name ? `Impression - ${context.machine.name}` : 'Impression machine' const badgesHtml = context.machine.badges .map((badge) => `${badge}`) .join('') const sections = [] sections.push(` `) if (context.machine.includeInfo) { sections.push(` `) } const customFieldsSection = renderPrintCustomFields( context.machine.customFields, 'Champs personnalisés de la machine', 'print-section print-section--custom-fields', ) if (customFieldsSection) { sections.push(customFieldsSection) } const documentsSection = renderPrintDocuments( context.machine.documents, 'Documents liés à la machine', 'print-section print-section--documents', ) if (documentsSection) { sections.push(documentsSection) } const componentsSection = renderPrintComponents(context.components) if (componentsSection) { sections.push(componentsSection) } const piecesSection = renderPrintPieces( context.pieces, 'Pièces indépendantes', 'print-section print-section--pieces', ) if (piecesSection) { sections.push(piecesSection) } sections.push(` `) const content = sections.join('\n') return ` ${title} ${styles} ` }