/** * Document Generation API * Services for PDF, Excel, Word, and label generation. * Phase 9 — runtime deps (@react-pdf/renderer, exceljs, docx) added when installed. * This file provides the API surface; implementations use dynamic imports. */ export function createDocumentGeneratorApi() { return { /** * Generate a PDF document (member card, invoice, certificate, etc.) * Uses @react-pdf/renderer or jspdf at runtime. */ async generatePdf(params: { title: string; content: Record; format?: 'A4' | 'A5' | 'letter'; orientation?: 'portrait' | 'landscape'; }): Promise { // Dynamic import to avoid bundle bloat in SSR // Actual implementation will use @react-pdf/renderer throw new Error( 'PDF generation requires @react-pdf/renderer. Install it and implement the renderer in pdf-generator.service.ts', ); }, /** * Generate an Excel workbook (reports, data exports) * Uses exceljs at runtime. */ async generateExcel(params: { title: string; sheets: Array<{ name: string; columns: Array<{ header: string; key: string; width?: number }>; rows: Array>; }>; }): Promise { throw new Error( 'Excel generation requires exceljs. Install it and implement in excel-generator.service.ts', ); }, /** * Generate a Word document (mail merge, letters) * Uses docx at runtime. */ async generateWord(params: { title: string; templateContent: string; mergeFields: Record; }): Promise { throw new Error( 'Word generation requires docx. Install it and implement in word-generator.service.ts', ); }, /** * Generate address labels in Avery format * Pure implementation — no external deps needed. */ generateLabelsHtml(params: { labelFormat: string; records: Array<{ line1: string; line2?: string; line3?: string; line4?: string; }>; }): string { const { records } = params; // Avery L7163 = 14 labels per page, 2 columns x 7 rows const labelsPerPage = 14; const pages: string[] = []; for (let i = 0; i < records.length; i += labelsPerPage) { const pageRecords = records.slice(i, i + labelsPerPage); const labels = pageRecords .map( (r) => `
${r.line1}
${r.line2 ? `
${r.line2}
` : ''} ${r.line3 ? `
${r.line3}
` : ''} ${r.line4 ? `
${r.line4}
` : ''}
`, ) .join(''); pages.push(`
${labels}
`); } return `${pages.join('')}`; }, }; }