Progress Reports Generator
Progress Reports Generator

General Report Information

Overall Project Summary (Optional)

Report Sections

Report Preview

Click "Generate Preview" to see the report structure.

Author/Team: ${prg_reportConfig.author || "N/A"}

`; html += `

Reporting Period: ${prg_reportConfig.periodStartDate ? new Date(prg_reportConfig.periodStartDate+"T00:00:00Z").toLocaleDateString(undefined, {timeZone:'UTC'}) : "N/A"} - ${prg_reportConfig.periodEndDate ? new Date(prg_reportConfig.periodEndDate+"T00:00:00Z").toLocaleDateString(undefined, {timeZone:'UTC'}) : "N/A"}

`; if (prg_reportConfig.overallHighlights || prg_reportConfig.overallRoadblocks || prg_reportConfig.overallNextSteps) { html += `

Overall Summary

`; html += `

Overall Status: ${prg_reportConfig.overallStatus}

`; if(prg_reportConfig.overallHighlights) html += `

Highlights/Key Achievements:

${prg_reportConfig.overallHighlights.replace(/\n/g, "
")}

`; if(prg_reportConfig.overallRoadblocks) html += `

Major Roadblocks/Issues:

${prg_reportConfig.overallRoadblocks.replace(/\n/g, "
")}

`; if(prg_reportConfig.overallNextSteps) html += `

Next Steps for Project:

${prg_reportConfig.overallNextSteps.replace(/\n/g, "
")}

`; } if (prg_reportSections.length > 0) { html += `

Detailed Section Progress

`; prg_reportSections.forEach(section => { html += `
`; html += `

${section.title || "Untitled Section"}

`; html += `

Status: ${section.status}

`; html += `

Summary (this period):

${section.summary.replace(/\n/g, "
") || "N/A"}

`; if (section.tasks.length > 0) { html += `

Key Tasks/Activities:

    `; section.tasks.forEach(task => { html += `
  • ${task.name || "Unnamed Task"}: ${task.status} (${task.percentComplete}%)
    Notes: ${task.notes || "N/A"}
  • `; }); html += `
`; } html += `

Upcoming Plans:

${section.upcomingPlans.replace(/\n/g, "
") || "N/A"}

`; html += `
`; }); } else { html += `

No sections defined for this report.

`; } previewArea.innerHTML = html; document.getElementById('prg-download-pdf-button').disabled = false; } function prg_clearAllReportData() { if (confirm("Are you sure you want to clear all report data?")) { prg_reportConfig = {}; document.getElementById('prg-report-title').value = "Weekly Progress Report"; const today = new Date(2025,4,14); document.getElementById('prg-period-start').valueAsDate = today; const nextWeek = new Date(today); nextWeek.setDate(today.getDate() + 7); document.getElementById('prg-period-end').valueAsDate = nextWeek; document.getElementById('prg-report-author').value = "My Team"; document.getElementById('prg-overall-status').value = "On Track"; ['overall-highlights', 'overall-roadblocks', 'overall-next-steps'].forEach(id => document.getElementById(`prg-${id}`).value = ''); prg_reportSections = []; prg_sectionCounter = 0; prg_taskCounter = 0; document.getElementById('prg-report-sections-list').innerHTML = ''; prg_addReportSection(); // Add one fresh section document.getElementById('prg-preview-area').innerHTML = 'Click "Generate Preview" to see the report structure.'; document.getElementById('prg-download-pdf-button').disabled = true; } } function prg_downloadPDF() { if (!tpc_jsPDF_loaded_PRG || !tpc_autoTable_loaded_PRG) { alert("PRG Error: PDF libraries not loaded."); return; } prg_generatePreview(); // Ensure data is current and preview is shown if (prg_reportSections.length === 0 && !prg_reportConfig.overallHighlights && !prg_reportConfig.overallRoadblocks) { alert("No content to generate PDF. Please add report sections or overall summary details."); return; } const doc = new TPC_jsPDF_PRG(); const primaryColor = getComputedStyle(document.documentElement).getPropertyValue('--primary-color').trim(); const darkColor = getComputedStyle(document.documentElement).getPropertyValue('--dark-color').trim(); let finalY = 15; const pageHeight = doc.internal.pageSize.height; const margin = 15; function addText(text, size, color, yPos, options = {}) { if (yPos > pageHeight - margin - 10) { // Check for page break doc.addPage(); yPos = margin; } doc.setFontSize(size); doc.setTextColor(color); doc.text(text, margin, yPos, { maxWidth: doc.internal.pageSize.width - margin * 2, ...options }); // Estimate height of text including line breaks const textLines = doc.splitTextToSize(text, doc.internal.pageSize.width - margin * 2); return yPos + (textLines.length * (size * 0.352778 * 1.2)); // Approximate line height factor } function addHeading(text, yPos, size = 16) { return addText(text, size, primaryColor, yPos, {fontStyle:'bold'}); } function addSubHeading(text, yPos, size = 12) { return addText(text, size, darkColor, yPos, {fontStyle:'bold'}); } function addParagraph(text, yPos) { if (!text || text.trim() === "") return yPos; return addText(text, 10, darkColor, yPos) + 3; // Add little spacing after paragraph } finalY = addText(prg_reportConfig.title || "Progress Report", 20, primaryColor, finalY, { align: 'center' }); finalY = addText(`Author/Team: ${prg_reportConfig.author || "N/A"}`, 10, darkColor, finalY + 2, { align: 'center' }); let periodString = `Reporting Period: ${prg_reportConfig.periodStartDate ? new Date(prg_reportConfig.periodStartDate+"T00:00:00Z").toLocaleDateString(undefined, {timeZone:'UTC'}) : "N/A"} - ${prg_reportConfig.periodEndDate ? new Date(prg_reportConfig.periodEndDate+"T00:00:00Z").toLocaleDateString(undefined, {timeZone:'UTC'}) : "N/A"}`; finalY = addText(periodString, 10, darkColor, finalY, { align: 'center' }); finalY += 8; if (prg_reportConfig.overallHighlights || prg_reportConfig.overallRoadblocks || prg_reportConfig.overallNextSteps) { finalY = addHeading("Overall Summary", finalY); finalY = addParagraph(`Overall Status: ${prg_reportConfig.overallStatus}`, finalY); if(prg_reportConfig.overallHighlights) { finalY = addSubHeading("Highlights/Key Achievements:", finalY); finalY = addParagraph(prg_reportConfig.overallHighlights, finalY); } if(prg_reportConfig.overallRoadblocks) { finalY = addSubHeading("Major Roadblocks/Issues:", finalY); finalY = addParagraph(prg_reportConfig.overallRoadblocks, finalY); } if(prg_reportConfig.overallNextSteps) { finalY = addSubHeading("Next Steps for Project:", finalY); finalY = addParagraph(prg_reportConfig.overallNextSteps, finalY); } finalY += 5; } if (prg_reportSections.length > 0) { finalY = addHeading("Detailed Section Progress", finalY); prg_reportSections.forEach(section => { if (finalY > pageHeight - margin - 50) { doc.addPage(); finalY = margin; } // Check before new section finalY = addHeading(section.title || "Untitled Section", finalY, 14); finalY = addParagraph(`Status: ${section.status}`, finalY); finalY = addSubHeading("Summary (this period):", finalY); finalY = addParagraph(section.summary || "N/A", finalY); if (section.tasks.length > 0) { finalY = addSubHeading("Key Tasks/Activities:", finalY); const taskTableBody = section.tasks.map(task => [ task.name || "Unnamed Task", task.status, `${task.percentComplete}%`, task.notes || "-" ]); doc.autoTable({ startY: finalY, head: [['Task', 'Status', '% Comp.', 'Notes/Blockers']], body: taskTableBody, theme: 'grid', headStyles: { fillColor: primaryColor, textColor: '#ffffff', fontSize: 9 }, styles: { fontSize: 8, cellPadding: 1.5, overflow: 'linebreak' }, margin: {left: margin, right: margin} }); finalY = doc.lastAutoTable.finalY + 5; } finalY = addSubHeading("Upcoming Plans:", finalY); finalY = addParagraph(section.upcomingPlans || "N/A", finalY); finalY += 5; // Space between sections }); } doc.save(`${(prg_reportConfig.title || "Progress_Report").replace(/[^a-z0-9]/gi, '_')}.pdf`); }
Scroll to Top