Employee Remote Work Setup Cost Calculator
Estimation Setup
Cost Itemization for Remote Setup
Add New Cost Item
Enter the cost for one employee for this item.
Defaults to total employees from Setup, can be overridden.
Current Cost Items for Remote Setup
| Item/Service Name | Category | Cost/Unit ($) | # Employees | Total Cost ($) | Notes | Actions |
|---|
Total Estimated Costs & Report
Estimation Plan Name:
Company Name:
Total Employees for Setup:
Total Estimated Remote Work Setup Cost: $0.00
Average Setup Cost per Employee: $0.00
Estimated Costs by Category
| Category | Total Estimated Cost ($) | % of Grand Total |
|---|
Cost Distribution by Category
Chart library not loaded.
"; return; } const ctx = chartCanvas.getContext('2d'); const chartColors = ['#007bff', '#28a745', '#ffc107', '#17a2b8', '#6f42c1', '#fd7e14', '#6c757d', '#dc3545', '#20c997']; if (rwscCategoryCostChartInstance) rwscCategoryCostChartInstance.destroy(); if (labels.length > 0 && data.some(d => d > 0)) { rwscCategoryCostChartInstance = new Chart(ctx, { type: 'pie', data: { labels: labels, datasets: [{ label: 'Cost by Category', data: data, backgroundColor: labels.map((_,i)=>chartColors[i % chartColors.length]), borderColor: varGet('--rwsc-light-text'), borderWidth:1 }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'top' }, tooltip: {callbacks: {label: c=>`${c.label}: $${c.parsed.toFixed(2)}`}} } } }); } else { ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height); ctx.textAlign='center'; ctx.fillStyle = varGet('--rwsc-secondary-color'); ctx.font = "16px Arial"; ctx.fillText("No cost data by category to display chart.", ctx.canvas.width/2, ctx.canvas.height/2); rwscCategoryCostChartInstance = null; } } function varGet(varName) { return getComputedStyle(document.documentElement).getPropertyValue(varName).trim(); } // --- PDF Download --- window.rwscDownloadPDF = function() { if (typeof jsPDF === 'undefined' || typeof autoTable === 'undefined') { alert("PDF libraries not loaded."); return; } const { jsPDF: JSPDF } = window.jspdf; const localAutoTable = window.jspdf.autoTable; const doc = new JSPDF(); rwscUpdateSummaryReport(); const planName = rwscEstimationConfig.planName; const companyName = rwscEstimationConfig.companyName; const totalEmployees = rwscEstimationConfig.totalEmployeesForSetup; const generationDate = new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }) + " (Reference Time: Friday, May 16, 2025)"; doc.setFontSize(18); doc.setTextColor(varGet('--rwsc-primary-color')); doc.text(planName, doc.internal.pageSize.getWidth() / 2, 15, { align: 'center' }); doc.setFontSize(11); doc.setTextColor(varGet('--rwsc-dark-text')); doc.text(`Company: ${companyName || 'N/A'}`, 14, 25); doc.text(`Total Employees for Setup: ${totalEmployees}`, doc.internal.pageSize.getWidth() - 14, 25, { align: 'right' }); doc.setFontSize(9); doc.setTextColor(varGet('--rwsc-secondary-color')); doc.text(`Report Generated: ${generationDate}`, 14, 31); let yPos = 40; const grandTotalCost = rwscCostItems.reduce((sum, item) => sum + item.totalCostForItem, 0); const avgCostPerEmployee = totalEmployees > 0 ? (grandTotalCost / totalEmployees) : 0; doc.setFontSize(12); doc.setTextColor(varGet('--rwsc-primary-color')); doc.text("Overall Cost Summary", 14, yPos); yPos += 7; doc.setFontSize(10); doc.setTextColor(varGet('--rwsc-dark-text')); doc.text(`Total Estimated Setup Cost: $${grandTotalCost.toFixed(2)}`, 14, yPos); yPos += 5; doc.text(`Average Setup Cost per Employee: $${avgCostPerEmployee.toFixed(2)}`, 14, yPos); yPos += 10; doc.setFontSize(12); doc.setTextColor(varGet('--rwsc-primary-color')); doc.text("Itemized Setup Costs", 14, yPos); yPos += 7; const itemHead = [['Item/Service', 'Category', 'Cost/Unit ($)', '# Employees', 'Total Cost ($)', 'Notes']]; const itemBody = rwscCostItems.map(item => [ item.name, item.category, item.costPerUnit.toFixed(2), item.numEmployeesForItem, item.totalCostForItem.toFixed(2), item.notes || '-' ]); localAutoTable(doc, { head: itemHead, body: itemBody, startY: yPos, theme: 'grid', headStyles: { fillColor: varGet('--rwsc-primary-color'), textColor: varGet('--rwsc-light-text')}, styles: { fontSize: 8, cellPadding: 1.5, overflow: 'linebreak' }, columnStyles: { 0:{cellWidth:40}, 1:{cellWidth:40}, 2:{halign:'right'}, 3:{halign:'right'}, 4:{halign:'right', fontStyle:'bold'}, 5:{cellWidth:'auto'} }, didDrawPage: data => yPos = data.cursor.y }); yPos = doc.lastAutoTable.finalY + 10; // Chart const chartCanvas = document.getElementById('rwscCategoryCostChart'); if (chartCanvas && rwscCategoryCostChartInstance && rwscCategoryCostChartInstance.data.datasets[0].data.some(d => d > 0)) { if (yPos > doc.internal.pageSize.getHeight() - 80) { doc.addPage(); yPos = 20;} doc.setFontSize(12); doc.setTextColor(varGet('--rwsc-primary-color')); doc.text("Cost Distribution by Category", doc.internal.pageSize.getWidth() / 2, yPos, { align: 'center' }); yPos += 7; try { const chartImage = chartCanvas.toDataURL('image/png', 1.0); const imgProps = doc.getImageProperties(chartImage); const pdfChartWidth = doc.internal.pageSize.getWidth() * 0.65; const chartHeight = (imgProps.height * pdfChartWidth) / imgProps.width; const xOffset = (doc.internal.pageSize.getWidth() - pdfChartWidth) / 2; if (yPos + chartHeight > doc.internal.pageSize.getHeight() -10 ) { doc.addPage(); yPos = 20; doc.text("Cost Distribution by Category (cont.)", doc.internal.pageSize.getWidth() / 2, yPos, {align: 'center'}); yPos += 7; } doc.addImage(chartImage, 'PNG', xOffset, yPos, pdfChartWidth, chartHeight); } catch(e) { console.error("Error adding chart to PDF:", e); } } doc.save(`${planName.replace(/[^a-z0-9]/gi, '_').toLowerCase()}_remote_setup_costs.pdf`); } // --- Initialization --- rwscRenderCostCategoriesSelect(); // Populate category dropdown // Set default for number of employees for item when tab 1 total employees changes document.getElementById('rwscTotalEmployeesForSetup').addEventListener('input', (e) => { const totalEmpl = parseInt(e.target.value) || 1; document.getElementById('rwscNumEmployeesForItem').value = totalEmpl > 0 ? totalEmpl : 1; rwscSaveEstimationConfig(); // Save immediately as other calcs might depend on it }); rwscRenderCostItemsTable(); rwscShowTab(0); rwscUpdateSummaryReport(); // Initial calculation for summary tab if needed });