document.addEventListener('DOMContentLoaded', function() { // Sample data - in a real app this would come from an API const softwareData = [ { id: 1, software: "CSI [Etabs, SAFE, SAP2000]", date: "July 9, 2020", cost: 12176.60, year: "2020" }, { id: 2, software: "Plaxis", date: "September 1, 2020", cost: 5361.00, year: "2020" }, { id: 3, software: "Tekla", date: "December 1, 2020", cost: 13503.40, year: "2020" }, { id: 4, software: "CSI [Etabs, SAFE, SAP2000]", date: "July 9, 2021", cost: 11877.00, year: "2021" }, { id: 5, software: "Plaxis", date: "September 1, 2021", cost: 5391.00, year: "2021" }, { id: 6, software: "Tekla", date: "December 1, 2021", cost: 6868.60, year: "2021" }, { id: 7, software: "CSI [Etabs, SAFE, SAP2000]", date: "August 10, 2022", cost: 13482.00, year: "2022" }, { id: 8, software: "Plaxis", date: "September 5, 2022", cost: 5796.00, year: "2022" }, { id: 9, software: "Tekla", date: "October 18, 2022", cost: 7130.37, year: "2022" }, { id: 10, software: "CSI [Etabs, SAFE, SAP2000]", date: "July 4, 2023", cost: 11664.00, year: "2023" }, { id: 11, software: "Plaxis", date: "September 21, 2023", cost: 6201.00, year: "2023" }, { id: 12, software: "Tekla", date: "October 18, 2023", cost: 7792.20, year: "2023" }, { id: 13, software: "CSI [Etabs, SAFE, SAP2000]", date: "July 4, 2024", cost: 11336.00, year: "2024" }, { id: 14, software: "Plaxis", date: "September 18, 2024", cost: 7003.40, year: "2024" }, { id: 15, software: "Tekla", date: "October 10, 2024", cost: 14963.91, year: "2024" }, { id: 16, software: "CSI [Etabs, SAFE, SAP2000]", date: "May 22, 2025", cost: 11336.00, year: "2025" }, { id: 17, software: "Unreal Engine", date: "September 6, 2024", cost: 2727.18, year: "2024" }, { id: 18, software: "Plaxis", date: "September 18, 2025", cost: 7752.84, year: "2025" }, { id: 19, software: "Tekla", date: "November 26, 2025", cost: 15467.10, year: "2025" }, { id: 20, software: "Unreal Engine", date: "September 6, 2025", cost: 2744.62, year: "2025" } ]; // Calculate summary stats const currentYear = new Date().getFullYear().toString(); const currentYearSpend = softwareData .filter(item => item.year === currentYear) .reduce((sum, item) => sum + item.cost, 0); // Set current date const options = { year: 'numeric', month: 'long', day: 'numeric' }; document.getElementById('current-date').textContent = new Date().toLocaleDateString('en-SG', options); document.getElementById('current-year').textContent = `SGD ${currentYearSpend.toLocaleString('en-SG', {minimumFractionDigits: 2, maximumFractionDigits: 2})}`; const totalSpend = softwareData.reduce((sum, item) => sum + item.cost, 0); const years = [...new Set(softwareData.map(item => item.year))]; const avgAnnual = totalSpend / years.length; // Find most expensive software const softwareGroups = {}; softwareData.forEach(item => { if (!softwareGroups[item.software]) { softwareGroups[item.software] = 0; } softwareGroups[item.software] += item.cost; }); const mostExpensive = Object.entries(softwareGroups).reduce((a, b) => a[1] > b[1] ? a : b); // Update summary cards document.getElementById('total-spend').textContent = `SGD ${totalSpend.toLocaleString('en-SG', {minimumFractionDigits: 2, maximumFractionDigits: 2})}`; document.getElementById('avg-annual').textContent = `SGD ${avgAnnual.toLocaleString('en-SG', {minimumFractionDigits: 2, maximumFractionDigits: 2})}`; document.getElementById('most-expensive').textContent = `${mostExpensive[0]} (SGD ${mostExpensive[1].toLocaleString('en-SG', {minimumFractionDigits: 2, maximumFractionDigits: 2})})`; // Create yearly chart const yearlyData = {}; softwareData.forEach(item => { if (!yearlyData[item.year]) { yearlyData[item.year] = 0; } yearlyData[item.year] += item.cost; }); const yearlyLabels = Object.keys(yearlyData).sort(); const yearlyValues = yearlyLabels.map(year => yearlyData[year]); const ctx = document.getElementById('yearly-chart').getContext('2d'); new Chart(ctx, { type: 'bar', data: { labels: yearlyLabels, datasets: [{ label: 'Yearly Software Spend (SGD)', data: yearlyValues, backgroundColor: '#3B82F6', borderColor: '#2563EB', borderWidth: 1 }] }, options: { responsive: true, maintainAspectRatio: false, scales: { y: { beginAtZero: true, ticks: { callback: function(value) { return 'SGD ' + value.toLocaleString('en-SG'); } } } }, plugins: { tooltip: { callbacks: { label: function(context) { return 'SGD ' + context.raw.toLocaleString('en-SG'); } } } } } }); // Populate current year's software table const currentYearTable = document.getElementById('current-year-table'); const currentYearItems = softwareData.filter(item => item.year === currentYear); currentYearItems.forEach(item => { const row = document.createElement('tr'); row.innerHTML = `