River Pollution Report Generator

River Pollution Report Generator

Report Sections (Editable)

Water Quality Data

River & Sampling Details

Water Quality Test Data

Collected Data

No data collected. Add test results in the Configuration tab.

"; } else { const tableEl = document.createElement("div"); tableEl.innerHTML = `
Parameter
Measured Value
Standard Limit
Status
`; testData.forEach(item => { // Add placeholder values for standard and status for editing const row = document.createElement('div'); row.className = 'rprg-table-row'; row.dataset.id = item.id; row.innerHTML = ` `; tableEl.appendChild(row); }); dashboardDataTable.appendChild(tableEl); } showTab("rprg-tab-dashboard"); } /** * Handles removal of rows directly from the dashboard table */ function handleDashboardRemove(e) { if (e.target.dataset.action === "remove") { const rowEl = e.target.closest(".rprg-table-row"); if (rowEl) { const id = rowEl.dataset.id; // Remove from master state testData = testData.filter(item => item.id !== id); // Remove from dashboard view and config view rowEl.remove(); updateConfigTestDisplay(); if (testData.length === 0) { handleGenerateDashboard(); // Re-render to show empty state } } } } /** * Generates a PDF report from the dashboard data (CRITICAL FUNCTION) */ function downloadPDF() { // 1. PDF Library Check if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF.autoTable === 'undefined') { alert("Error: PDF libraries could not be loaded. Please try again."); return; } // 2. Get potentially edited values from dashboard const title = dashTitle.value || "River Pollution Report"; const summary = dashSummary.value || "No summary provided."; const findings = dashFindings.value || "No findings recorded."; const recommendations = dashRecommendations.value || "No recommendations recorded."; const river = configRiver.value || "Water Body"; const date = configDate.value || "N/A"; const reporter = configReporter.value || "N/A"; const { jsPDF } = window.jspdf; const doc = new jsPDF("p", "pt", "a4"); const margin = 40; let yPos = margin; const lineHeight = 14; const usableWidth = doc.internal.pageSize.getWidth() - margin * 2; // Function to add a structured section function addSection(title, text) { // Check page break before adding section const textLines = doc.splitTextToSize(text, usableWidth); const textHeight = textLines.length * 10; // Approx height if (yPos > doc.internal.pageSize.getHeight() - 50) { doc.addPage(); yPos = margin; } if (yPos + 20 + textHeight > doc.internal.pageSize.getHeight() - margin) { doc.addPage(); yPos = margin; } doc.setFontSize(14); doc.setFont('helvetica', 'bold'); doc.text(title, margin, yPos); yPos += lineHeight * 1.2; doc.setFontSize(10); doc.setFont('helvetica', 'normal'); const finalLines = doc.splitTextToSize(text, usableWidth); doc.text(finalLines, margin, yPos); yPos += finalLines.length * 10 + 15; } // 3. Document Title & Details doc.setFontSize(20); doc.setFont('helvetica', 'bold'); doc.text(title, doc.internal.pageSize.getWidth() / 2, yPos, { align: 'center' }); yPos += lineHeight * 2; doc.setFontSize(10); doc.setFont('helvetica', 'normal'); doc.text(`River/Body: ${river}`, margin, yPos); doc.text(`Date: ${date}`, margin + 200, yPos); doc.text(`Organization: ${reporter}`, margin + 350, yPos); yPos += lineHeight * 2; // 4. Add Report Sections addSection("Executive Summary", summary); addSection("Key Findings & Analysis", findings); addSection("Recommendations", recommendations); // 5. Add Data Table const tableHead = [["Parameter", "Measured Value", "Standard Limit", "Status"]]; const tableBody = []; const dashRows = dashboardDataTable.querySelectorAll(".rprg-table-row"); dashRows.forEach(row => { const name = row.querySelector(".rprg-dash-name")?.value || 'N/A'; const value = row.querySelector(".rprg-dash-value")?.value || 'N/A'; const limit = row.querySelector(".rprg-dash-standard")?.value || 'N/A'; const status = row.querySelector(".rprg-dash-status")?.value || 'N/A'; tableBody.push([name, value, limit, status]); }); if (tableBody.length > 0) { addSection("Water Quality Data Table", `Detailed measurements taken on ${date}.`); doc.autoTable({ startY: yPos, head: tableHead, body: tableBody, theme: 'striped', headStyles: { fillColor: [0, 115, 230], textColor: [255, 255, 255], }, columnStyles: { 0: { cellWidth: 150 }, 1: { cellWidth: 100 }, 2: { cellWidth: 100 }, 3: { cellWidth: 'auto' }, }, styles: { fontSize: 9, cellPadding: 3, overflow: 'linebreak' }, margin: { left: margin, right: margin } }); } doc.save(`${configRiver.value.replace(/ /g,"_")}_Pollution_Report.pdf`); } /** * Helper to escape HTML */ function escapeHTML(str) { if (!str) return ""; return str .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } // --- 4. INITIALIZATION & EVENT LISTENERS --- // Tab Listeners tabButtons.forEach((btn) => { btn.addEventListener("click", () => showTab(btn.dataset.target)); }); navButtons.forEach((btn) => { btn.addEventListener("click", () => showTab(btn.dataset.target)); }); // Config Tab Listeners if (addTestForm) { addTestForm.addEventListener("submit", handleAddTest); } if (configTestList) { configTestList.addEventListener("click", handleConfigListClick); } if (generateBtn) { generateBtn.addEventListener("click", handleGenerateDashboard); } // Dashboard Tab Listeners if (pdfBtn) { pdfBtn.addEventListener("click", downloadPDF); } if (dashboardDataTable) { dashboardDataTable.addEventListener("click", handleDashboardRemove); } // Set default date configDate.valueAsDate = new Date(); // Load sample data testData.push({ id: 't1', name: 'Dissolved Oxygen (DO)', value: '3.5 mg/L' }); testData.push({ id: 't2', name: 'pH', value: '5.8' }); testData.push({ id: 't3', name: 'Fecal Coliform', value: '450 CFU/100mL' }); // Initial display of sample data updateConfigTestDisplay(); // Initial State: Generate dashboard with samples handleGenerateDashboard(); showTab("rprg-tab-dashboard"); });
Scroll to Top