import type { Template } from '@pdfme/common'; import type { PipelineData } from '@/lib/services/report-generators'; export const pipelineReportTemplate: Template = { basePdf: 'BLANK_PDF' as unknown as string, schemas: [ [ { name: 'reportTitle', type: 'text', position: { x: 20, y: 15 }, width: 170, height: 12, fontSize: 20, }, { name: 'portName', type: 'text', position: { x: 20, y: 30 }, width: 130, height: 8, fontSize: 11, }, { name: 'generatedAt', type: 'text', position: { x: 140, y: 30 }, width: 50, height: 8, fontSize: 9, }, { name: 'summaryText', type: 'text', position: { x: 20, y: 50 }, width: 170, height: 100, fontSize: 10, }, { name: 'detailsText', type: 'text', position: { x: 20, y: 160 }, width: 170, height: 100, fontSize: 9, }, ], ], }; export function buildPipelineInputs( data: PipelineData, portName?: string, ): Record[] { const stageOrder = [ 'open', 'details_sent', 'in_communication', 'eoi_sent', 'eoi_signed', 'deposit_10pct', 'contract_sent', 'contract_signed', 'completed', ]; const summaryLines = stageOrder .filter((stage) => (data.stageCounts[stage] ?? 0) > 0) .map((stage) => { const label = stage.replace(/_/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase()); return `${label}: ${data.stageCounts[stage] ?? 0} interest(s)`; }); // Include stages not in standard order const unknownStages = Object.keys(data.stageCounts).filter((s) => !stageOrder.includes(s)); for (const stage of unknownStages) { summaryLines.push(`${stage}: ${data.stageCounts[stage]} interest(s)`); } const totalInterests = Object.values(data.stageCounts).reduce((a, b) => a + b, 0); summaryLines.unshift(`Total Active Interests: ${totalInterests}`); summaryLines.unshift('Pipeline Stage Breakdown'); summaryLines.unshift('─────────────────────'); const detailLines = ['Top Interests by Value', '─────────────────────']; if (data.topInterests.length === 0) { detailLines.push('No interests with linked berths found.'); } else { data.topInterests.forEach((interest, i) => { const price = interest.berthPrice ? `Berth Price: ${Number(interest.berthPrice).toLocaleString()}` : 'No berth linked'; const stage = interest.pipelineStage .replace(/_/g, ' ') .replace(/\b\w/g, (c) => c.toUpperCase()); detailLines.push(`${i + 1}. Stage: ${stage} | ${price}`); }); } return [ { reportTitle: 'Pipeline Summary Report', portName: portName ?? 'Port Nimara', generatedAt: `Generated: ${new Date(data.generatedAt).toLocaleString('en-GB')}`, summaryText: summaryLines.join('\n'), detailsText: detailLines.join('\n'), }, ]; }