Preview:
const handleDownloadReport = async () => {
        setIsGeneratingReport(true); setForecastError('');
        try {
            const res = await axios.get('http://localhost:5000/api/generate-report-data', { withCredentials: true });
            setReportData({ ...res.data, historicalLabels: filteredData.map(d => d.timestamp) });

            setTimeout(async () => {
                const pdf = new jsPDF('p', 'mm', 'a4');
                const margin = 15;
                const pdfWidth = pdf.internal.pageSize.getWidth();
                const textWidth = pdfWidth - (margin * 2);
                let currentY = margin;

                pdf.setFontSize(22).setFont('helvetica', 'bold');
                pdf.text('SuDS Performance & Forecast Report', pdfWidth / 2, currentY, { align: 'center' });
                currentY += 10;
                pdf.setFontSize(14).setFont('helvetica', 'normal');
                pdf.text(`Generated on: ${new Date().toLocaleDateString('en-GB')}`, pdfWidth / 2, currentY, { align: 'center' });
                currentY += 15;
                const firstDate = new Date(filteredData[0].timestamp).toLocaleDateString('en-GB');
                const lastDate = new Date(filteredData[filteredData.length - 1].timestamp).toLocaleDateString('en-GB');
                const introText = `This report analyzes the performance of a Sustainable Drainage System (SuDS) using historical data from ${firstDate} to ${lastDate}, and provides a 24-hour forecast. The system is evaluated on three key performance metrics:`;
                const splitIntro = pdf.splitTextToSize(introText, textWidth);
                pdf.setFontSize(12).setFont('helvetica', 'normal');
                pdf.text(splitIntro, margin, currentY);
                currentY += (splitIntro.length * 5) + 5;
                const bulletPoints = ["Rainfall (mm): Measures the amount of rain entering the system.","Water Level (cm): Measures the height of water collected within the SuDS infrastructure.","Flow Rate (lps): Measures the volume of water the system is discharging."];
                pdf.setFontSize(11).setFont('helvetica', 'normal');
                bulletPoints.forEach(point => { pdf.text(`\u2022 ${point}`, margin + 5, currentY); currentY += 7; });
                currentY += 5;
                const conclusionText = `To provide a robust outlook, two different forecasting methods were used: a traditional statistical model and a modern machine learning model. \nThis dual-model approach allows for a comprehensive evaluation of potential future system behavior.`;
                const splitConclusion = pdf.splitTextToSize(conclusionText, textWidth);
                pdf.setFontSize(12).setFont('helvetica', 'normal');
                pdf.text(splitConclusion, margin, currentY);
                currentY += (splitConclusion.length * 5) + 10;
                
                const chart1_canvas = reportRefs.chart1Ref.current.canvas;
                const chart1_img = chart1_canvas.toDataURL('image/png', 2.5);
                const chart1_img_height = (chart1_canvas.height * (pdfWidth - margin*2)) / chart1_canvas.width;
                pdf.addImage(chart1_img, 'PNG', margin, currentY, pdfWidth - (margin*2), chart1_img_height);
                
                pdf.addPage();
                currentY = margin;
                const chart2_canvas = reportRefs.chart2Ref.current.canvas;
                const chart2_img = chart2_canvas.toDataURL('image/png', 2.5);
                const chart2_img_height = (chart2_canvas.height * (pdfWidth - margin*2)) / chart2_canvas.width;
                pdf.addImage(chart2_img, 'PNG', margin, currentY, pdfWidth - (margin*2), chart2_img_height);
                currentY += chart2_img_height + 10;

                const chart3_canvas = reportRefs.chart3Ref.current.canvas;
                const chart3_img = chart3_canvas.toDataURL('image/png', 2.5);
                const chart3_img_height = (chart3_canvas.height * (pdfWidth - margin*2)) / chart3_canvas.width;
                pdf.addImage(chart3_img, 'PNG', margin, currentY, pdfWidth - (margin*2), chart3_img_height);
                
                pdf.save("SuDS_Forecast_Report.pdf");
                setReportData(null);
                setIsGeneratingReport(false);
            }, 500);
        } catch (err) { setForecastError("Failed to generate report data."); setIsGeneratingReport(false); }
    };
downloadDownload PNG downloadDownload JPEG downloadDownload SVG

Tip: You can change the style, width & colours of the snippet with the inspect tool before clicking Download!

Click to optimize width for Twitter