Proposal Generation Dashboard

Client & Project Information
Scope of Work
Pricing

Subtotal: $0.00
Tax: $0.00

Grand Total: $0.00

Terms & Conditions

This is a preview of your final proposal. Review it carefully before exporting.

From: ${d.preparedBy}

Date: ${d.proposalDate}

1. Project Overview

${d.overview}

2. Scope & Deliverables

${deliverablesHtml}

3. Investment

${pricingHtml}

4. Terms & Conditions

${termsHtml}
`; } // --- Event Handlers & UI --- window.pgd_updatePricing = () => { let subtotal = 0; document.querySelectorAll('#pgd-pricing-body tr').forEach(row => { const qty = parseFloat(row.cells[1].querySelector('input').value) || 0; const unitPrice = parseFloat(row.cells[2].querySelector('input').value) || 0; const lineTotal = qty * unitPrice; row.cells[3].textContent = lineTotal.toLocaleString('en-US', { style: 'currency', currency: 'USD' }); subtotal += lineTotal; }); const taxRate = parseFloat(document.getElementById('pgd-cfg-tax-rate').value) || 0; const tax = subtotal * (taxRate / 100); const grandTotal = subtotal + tax; document.getElementById('pgd-subtotal').textContent = subtotal.toLocaleString('en-US', { style: 'currency', currency: 'USD' }); document.getElementById('pgd-tax').textContent = tax.toLocaleString('en-US', { style: 'currency', currency: 'USD' }); document.getElementById('pgd-grand-total').textContent = grandTotal.toLocaleString('en-US', { style: 'currency', currency: 'USD' }); }; window.pgd_addListItem = (key) => { const container = document.getElementById(`pgd-cfg-${key}`); const div = document.createElement('div'); div.className = 'pgd-dynamic-list-item'; div.innerHTML = ``; container.appendChild(div); }; window.pgd_addPricingRow = () => { const tbody = document.getElementById('pgd-pricing-body'); const row = tbody.insertRow(); row.innerHTML = ` $0.00 `; }; window.pgd_openTab = (evt, tabId) => { pgd_saveDataFromTabs(); if (tabId === 'pgd-preview') { pgd_renderPreview(); } document.querySelectorAll("#pgd-container .pgd-tab-content").forEach(c => c.classList.remove('active')); document.querySelectorAll("#pgd-container .pgd-tab-link").forEach(l => l.classList.remove('active')); document.getElementById(tabId).classList.add('active'); evt.currentTarget.classList.add('active'); document.getElementById('pgd-download-btn').style.display = (tabId === 'pgd-preview') ? 'inline-block' : 'none'; }; window.pgd_navigateTabs = (direction) => { const tabs = Array.from(document.querySelectorAll('#pgd-container .pgd-tab-link')); const activeTabIndex = tabs.findIndex(tab => tab.classList.contains('active')); let nextTabIndex = (direction === 'next') ? (activeTabIndex + 1) % tabs.length : (activeTabIndex - 1 + tabs.length) % tabs.length; tabs[nextTabIndex].click(); }; window.pgd_downloadPDF = () => { const { jsPDF } = window.jspdf; const content = document.getElementById('pgd-preview-area'); html2canvas(content, { scale: 2, useCORS: true }).then(canvas => { const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'p', unit: 'mm', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = pdf.internal.pageSize.getHeight(); const imgProps = pdf.getImageProperties(imgData); const imgWidth = pdfWidth; const imgHeight = (imgProps.height * imgWidth) / imgProps.width; let heightLeft = imgHeight; let position = 0; pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight); heightLeft -= pdfHeight; while (heightLeft > 0) { position = heightLeft - imgHeight; pdf.addPage(); pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight); heightLeft -= pdfHeight; } pdf.save(`${pgd_proposalData.projectTitle.replace(/\s+/g, '-')}-Proposal.pdf`); }); }; pgd_init(); });
Scroll to Top