File size: 6,585 Bytes
fba9a63 62afa00 fba9a63 62afa00 fba9a63 62afa00 fba9a63 c06a7c4 fba9a63 c06a7c4 fba9a63 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
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 = `
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">${item.software}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item.date}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item.cost.toLocaleString('en-SG', {minimumFractionDigits: 2, maximumFractionDigits: 2})}</td>
`;
currentYearTable.appendChild(row);
});
// View toggle functionality
document.getElementById('yearly-view').addEventListener('click', function() {
// In a real app, this would filter the table by year
alert('Yearly view would show aggregated data by year');
});
document.getElementById('software-view').addEventListener('click', function() {
// In a real app, this would group by software
alert('Software view would show data grouped by software');
});
}); |