Period: ${period} | Unit: ${unit.toUpperCase()}
`;
html += `
${totals.total.toFixed(1)} ${unit.toUpperCase()}
Total Waste Logged
${reductionPct.toFixed(1)}%
Reduction Progress (Goal: ${goal}%)
`;
// 2. Breakdown Table
html += `
Category Breakdown (${unit.toUpperCase()})
| Category |
Total Output |
Percentage |
Notes |
| Paper/Cardboard | ${totals.paper.toFixed(1)} | ${(totals.paper / totals.total * 100).toFixed(1)}% | Largest volume contributor. |
| Plastics/Metals | ${totals.plastic.toFixed(1)} | ${(totals.plastic / totals.total * 100).toFixed(1)}% | Key target for immediate substitution. |
| Organics/Compost | ${totals.organic.toFixed(1)} | ${(totals.organic / totals.total * 100).toFixed(1)}% | Best opportunity for diversion. |
`;
// 3. Detailed Log
html += `
Detailed Log Entries
| Date/Interval |
Paper |
Plastic |
Organic |
Total |
`;
logData.forEach(item => {
const rowTotal = (item.paper + item.plastic + item.organic).toFixed(1);
html += `
| ${item.date} |
${item.paper.toFixed(1)} |
${item.plastic.toFixed(1)} |
${item.organic.toFixed(1)} |
${rowTotal} |
`;
});
html += `
`;
container.innerHTML = html;
}
function wrtgSwitchTab(tabId) {
document.querySelectorAll('.wrtg-tab-btn').forEach(b => b.classList.remove('active'));
document.querySelectorAll('.wrtg-content').forEach(c => c.classList.remove('active'));
const idx = tabId === 'setup' ? 0 : (tabId === 'log' ? 1 : 2);
document.querySelectorAll('.wrtg-tab-btn')[idx].classList.add('active');
document.getElementById('wrtg-' + tabId).classList.add('active');
if (tabId === 'report') {
wrtgRenderReport();
}
}
function wrtgLoadExample() {
if(!confirm("Overwrite current data and load example office waste data?")) return;
document.getElementById('inp-project').value = "HQ Cafeteria Waste Stream Analysis";
document.getElementById('inp-period').value = "May 2026 Baseline";
document.getElementById('inp-unit').value = "kg";
document.getElementById('inp-goal').value = "15";
// Clear and fill log entries
document.getElementById('wrtg-log-rows-container').innerHTML = '';
wrtgAddLogRow("Week 1", 45, 15, 10);
wrtgAddLogRow("Week 2", 40, 13, 9);
wrtgAddLogRow("Week 3", 35, 11, 7);
wrtgAddLogRow("Week 4", 32, 10, 6); // Showing successful reduction trend
wrtgRenderReport();
wrtgSwitchTab('report');
}
/* --- PDF Generation --- */
async function wrtgGeneratePDF() {
wrtgRenderReport(); // Ensure report is updated
const logData = wrtgGetLogData();
if (logData.length === 0) {
alert("Please add log entries before generating the PDF.");
return;
}
const { jsPDF } = window.jspdf;
const doc = new jsPDF('p', 'mm', 'a4');
const unit = document.getElementById('inp-unit').value.toUpperCase();
const project = document.getElementById('inp-project').value || "Waste Audit Project";
const period = document.getElementById('inp-period').value || "Reporting Period";
const goal = parseFloat(document.getElementById('inp-goal').value) || 0;
const totals = logData.reduce((acc, item) => ({
paper: acc.paper + item.paper, plastic: acc.plastic + item.plastic, organic: acc.organic + item.organic, total: acc.total + item.paper + item.plastic + item.organic
}), { paper: 0, plastic: 0, organic: 0, total: 0 });
const reductionPct = ((logData[0].paper + logData[0].plastic + logData[0].organic - (logData[logData.length - 1].paper + logData[logData.length - 1].plastic + logData[logData.length - 1].organic)) / (logData[0].paper + logData[0].plastic + logData[0].organic)) * 100;
const teal = [0, 150, 136];
let y = 20;
// 1. Header
doc.setFillColor(...teal);
doc.rect(0, 0, 210, 20, 'F');
doc.setTextColor(255, 255, 255);
doc.setFontSize(16);
doc.text(`Waste Reduction Audit: ${project}`, 14, 13);
// 2. Summary
doc.setTextColor(0, 0, 0);
doc.setFontSize(10);
doc.text(`Period: ${period} | Unit: ${unit}`, 14, y + 10);
y += 20;
const summaryTable = [
['Total Waste Logged', `${totals.total.toFixed(1)} ${unit}`, 'Reduction Goal', `${goal}%`],
['Achieved Reduction', `${reductionPct.toFixed(1)}%`, 'Plastic Total', `${totals.plastic.toFixed(1)} ${unit}`]
];
doc.autoTable({
startY: y,
body: summaryTable,
theme: 'grid',
styles: { fontSize: 9 },
headStyles: { fillColor: [240, 240, 240], textColor: [0, 0, 0], fontStyle: 'bold' }
});
y = doc.lastAutoTable.finalY + 10;
// 3. Detailed Log
doc.setFontSize(12);
doc.setFont("helvetica", "bold");
doc.setTextColor(0, 150, 136);
doc.text("Detailed Log Entries", 14, y);
y += 5;
const tableBody = logData.map(item => [
item.date,
item.paper.toFixed(1),
item.plastic.toFixed(1),
item.organic.toFixed(1),
(item.paper + item.plastic + item.organic).toFixed(1)
]);
doc.autoTable({
startY: y,
head: [['Date/Interval', 'Paper', 'Plastics', 'Organics', `Total (${unit})`]],
body: tableBody,
theme: 'grid',
headStyles: { fillColor: teal, fontSize: 10 },
styles: { fontSize: 9 },
columnStyles: {
0: { cellWidth: 30, fontStyle: 'bold' },
4: { cellWidth: 30, fontStyle: 'bold', halign: 'center' }
}
});
// 4. Recommendation Space
y = doc.lastAutoTable.finalY + 15;
if (y > 270) { doc.addPage(); y = 20; }
doc.setFontSize(10);
doc.setTextColor(50);
doc.text("Recommendations / Next Steps (To be filled manually):", 14, y);
doc.setDrawColor(200);
doc.rect(14, y + 5, 180, 25, 'S');
doc.save(`WasteAudit_${project.replace(/\s/g, '_')}.pdf`);
}