Vatsal12345678 commited on
Commit
fba9a63
·
verified ·
1 Parent(s): 069b803

S. No. Software Date of Invoice Cost (Including Tax) Year

Browse files

1 CSI [Etabs, SAFE, SAP2000] July 9, 2020 SGD 12,176.60 July 9, 2020
2 Plaxis September 1, 2020 SGD 5,361.00 September 1, 2020
3 Tekla December 1, 2020 SGD 13,503.40 December 1, 2020
4 CSI [Etabs, SAFE, SAP2000] July 9, 2021 SGD 11,877.00 July 9, 2021
5 Plaxis September 1, 2021 SGD 5,391.00 September 1, 2021
6 Tekla December 1, 2021 SGD 6,868.60 December 1, 2021
7 CSI [Etabs, SAFE, SAP2000] August 10, 2022 SGD 13,482.00 August 10, 2022
8 Plaxis September 5, 2022 SGD 5,796.00 September 5, 2022
9 Tekla October 18, 2022 SGD 7,130.37 December 1, 2022
10 CSI [Etabs, SAFE, SAP2000] July 4, 2023 SGD 11,664.00 July 4, 2023
11 Plaxis September 21, 2023 SGD 6,201.00 September 5, 2023
12 Tekla October 18, 2023 SGD 7,792.20 December 1, 2023
13 CSI [Etabs, SAFE, SAP2000] July 4, 2024 SGD 11,336.00 July 4, 2024
14 Plaxis September 18, 2024 SGD 7,003.40 9/18/2024
15 Tekla October 10, 2024 SGD 14,963.91 10/10/2024
16 CSI [Etabs, SAFE, SAP2000] May 22, 2025 SGD 11,336.00 May 22, 2025
17 Unreal Engine 6-Sep-24 SGD 2,727.18 6-Sep-24
18 Plaxis 18-Sep-25 SGD 7,752.84 18-Sep-25
19 Tekla 26-Nov-25 SGD 15,467.10 26-Nov-25
20 Unreal Engine 6-Sep-25 SGD 2,744.62 6-Sep-25

Files changed (6) hide show
  1. README.md +8 -5
  2. components/footer.js +62 -0
  3. components/header.js +55 -0
  4. index.html +87 -19
  5. script.js +120 -0
  6. style.css +21 -22
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Software Spend Tracker
3
- emoji: 📚
4
- colorFrom: purple
5
- colorTo: purple
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
1
  ---
2
+ title: Software Spend Tracker 💰
3
+ colorFrom: pink
4
+ colorTo: green
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://huggingface.co/deepsite).
components/footer.js ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomFooter extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ footer {
7
+ background-color: #1E293B;
8
+ color: white;
9
+ }
10
+
11
+ .footer-content {
12
+ max-width: 1200px;
13
+ margin: 0 auto;
14
+ }
15
+
16
+ .footer-links a {
17
+ transition: color 0.2s ease;
18
+ }
19
+
20
+ .footer-links a:hover {
21
+ color: #3B82F6;
22
+ }
23
+ </style>
24
+ <footer class="py-8 px-6 mt-12">
25
+ <div class="footer-content">
26
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-8">
27
+ <div>
28
+ <h3 class="text-lg font-semibold mb-4">Software Spend Tracker</h3>
29
+ <p class="text-gray-400">Track and analyze your software subscription costs in one place.</p>
30
+ </div>
31
+ <div>
32
+ <h3 class="text-lg font-semibold mb-4">Quick Links</h3>
33
+ <div class="footer-links flex flex-col space-y-2">
34
+ <a href="#" class="text-gray-400 hover:text-white">Dashboard</a>
35
+ <a href="#" class="text-gray-400 hover:text-white">Reports</a>
36
+ <a href="#" class="text-gray-400 hover:text-white">Settings</a>
37
+ </div>
38
+ </div>
39
+ <div>
40
+ <h3 class="text-lg font-semibold mb-4">Contact</h3>
41
+ <div class="text-gray-400">
42
+ <p class="flex items-center mb-2">
43
+ <i data-feather="mail" class="mr-2"></i>
44
+ support@softwaretracker.com
45
+ </p>
46
+ <p class="flex items-center">
47
+ <i data-feather="globe" class="mr-2"></i>
48
+ www.softwaretracker.com
49
+ </p>
50
+ </div>
51
+ </div>
52
+ </div>
53
+ <div class="border-t border-gray-700 mt-8 pt-8 text-center text-gray-400">
54
+ <p>&copy; ${new Date().getFullYear()} Software Spend Tracker. All rights reserved.</p>
55
+ </div>
56
+ </div>
57
+ </footer>
58
+ `;
59
+ }
60
+ }
61
+
62
+ customElements.define('custom-footer', CustomFooter);
components/header.js ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomHeader extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ header {
7
+ background: linear-gradient(135deg, #3B82F6 0%, #1D4ED8 100%);
8
+ color: white;
9
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
10
+ }
11
+
12
+ .logo {
13
+ font-weight: 700;
14
+ letter-spacing: -0.025em;
15
+ }
16
+
17
+ nav a {
18
+ transition: all 0.2s ease;
19
+ }
20
+
21
+ nav a:hover {
22
+ opacity: 0.8;
23
+ transform: translateY(-1px);
24
+ }
25
+ </style>
26
+ <header class="py-4 px-6">
27
+ <div class="container mx-auto flex justify-between items-center">
28
+ <div class="logo text-2xl flex items-center">
29
+ <i data-feather="dollar-sign" class="mr-2"></i>
30
+ Software Spend Tracker
31
+ </div>
32
+ <nav class="hidden md:flex space-x-6">
33
+ <a href="#" class="flex items-center">
34
+ <i data-feather="home" class="mr-1"></i>
35
+ Dashboard
36
+ </a>
37
+ <a href="#" class="flex items-center">
38
+ <i data-feather="trending-up" class="mr-1"></i>
39
+ Analytics
40
+ </a>
41
+ <a href="#" class="flex items-center">
42
+ <i data-feather="settings" class="mr-1"></i>
43
+ Settings
44
+ </a>
45
+ </nav>
46
+ <button class="md:hidden">
47
+ <i data-feather="menu"></i>
48
+ </button>
49
+ </div>
50
+ </header>
51
+ `;
52
+ }
53
+ }
54
+
55
+ customElements.define('custom-header', CustomHeader);
index.html CHANGED
@@ -1,19 +1,87 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Software Spend Tracker</title>
7
+ <link rel="stylesheet" href="style.css">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
10
+ <script src="https://unpkg.com/feather-icons"></script>
11
+ <script>
12
+ tailwind.config = {
13
+ theme: {
14
+ extend: {
15
+ colors: {
16
+ primary: '#3B82F6',
17
+ secondary: '#10B981'
18
+ }
19
+ }
20
+ }
21
+ }
22
+ </script>
23
+ </head>
24
+ <body class="bg-gray-50 min-h-screen">
25
+ <custom-header></custom-header>
26
+
27
+ <main class="container mx-auto px-4 py-8">
28
+ <div class="flex flex-col md:flex-row justify-between items-start md:items-center mb-8">
29
+ <h1 class="text-3xl font-bold text-gray-800 mb-4 md:mb-0">Software Subscription Costs</h1>
30
+ <div class="flex space-x-2">
31
+ <button id="yearly-view" class="px-4 py-2 bg-primary text-white rounded-lg hover:bg-blue-600 transition">Yearly View</button>
32
+ <button id="software-view" class="px-4 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 transition">Software View</button>
33
+ </div>
34
+ </div>
35
+
36
+ <div class="bg-white rounded-xl shadow-md overflow-hidden">
37
+ <div class="overflow-x-auto">
38
+ <table class="min-w-full divide-y divide-gray-200">
39
+ <thead class="bg-gray-50">
40
+ <tr>
41
+ <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">S.No</th>
42
+ <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Software</th>
43
+ <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Date of Invoice</th>
44
+ <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Cost (SGD)</th>
45
+ <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Year</th>
46
+ </tr>
47
+ </thead>
48
+ <tbody id="data-table" class="bg-white divide-y divide-gray-200">
49
+ <!-- Data will be populated by JavaScript -->
50
+ </tbody>
51
+ </table>
52
+ </div>
53
+ </div>
54
+
55
+ <div class="mt-12 grid grid-cols-1 md:grid-cols-3 gap-6">
56
+ <div class="bg-white p-6 rounded-xl shadow-md">
57
+ <h3 class="text-lg font-medium text-gray-800 mb-4">Total Spend</h3>
58
+ <p id="total-spend" class="text-3xl font-bold text-primary">SGD 0.00</p>
59
+ </div>
60
+ <div class="bg-white p-6 rounded-xl shadow-md">
61
+ <h3 class="text-lg font-medium text-gray-800 mb-4">Average Annual Cost</h3>
62
+ <p id="avg-annual" class="text-3xl font-bold text-secondary">SGD 0.00</p>
63
+ </div>
64
+ <div class="bg-white p-6 rounded-xl shadow-md">
65
+ <h3 class="text-lg font-medium text-gray-800 mb-4">Most Expensive Software</h3>
66
+ <p id="most-expensive" class="text-3xl font-bold text-gray-800">-</p>
67
+ </div>
68
+ </div>
69
+
70
+ <div class="mt-12 bg-white p-6 rounded-xl shadow-md">
71
+ <h3 class="text-lg font-medium text-gray-800 mb-4">Yearly Spend Breakdown</h3>
72
+ <div class="h-64">
73
+ <canvas id="yearly-chart"></canvas>
74
+ </div>
75
+ </div>
76
+ </main>
77
+
78
+ <custom-footer></custom-footer>
79
+
80
+ <script src="components/header.js"></script>
81
+ <script src="components/footer.js"></script>
82
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
83
+ <script src="script.js"></script>
84
+ <script>feather.replace();</script>
85
+ <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
86
+ </body>
87
+ </html>
script.js ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ document.addEventListener('DOMContentLoaded', function() {
2
+ // Sample data - in a real app this would come from an API
3
+ const softwareData = [
4
+ { id: 1, software: "CSI [Etabs, SAFE, SAP2000]", date: "July 9, 2020", cost: 12176.60, year: "2020" },
5
+ { id: 2, software: "Plaxis", date: "September 1, 2020", cost: 5361.00, year: "2020" },
6
+ { id: 3, software: "Tekla", date: "December 1, 2020", cost: 13503.40, year: "2020" },
7
+ { id: 4, software: "CSI [Etabs, SAFE, SAP2000]", date: "July 9, 2021", cost: 11877.00, year: "2021" },
8
+ { id: 5, software: "Plaxis", date: "September 1, 2021", cost: 5391.00, year: "2021" },
9
+ { id: 6, software: "Tekla", date: "December 1, 2021", cost: 6868.60, year: "2021" },
10
+ { id: 7, software: "CSI [Etabs, SAFE, SAP2000]", date: "August 10, 2022", cost: 13482.00, year: "2022" },
11
+ { id: 8, software: "Plaxis", date: "September 5, 2022", cost: 5796.00, year: "2022" },
12
+ { id: 9, software: "Tekla", date: "October 18, 2022", cost: 7130.37, year: "2022" },
13
+ { id: 10, software: "CSI [Etabs, SAFE, SAP2000]", date: "July 4, 2023", cost: 11664.00, year: "2023" },
14
+ { id: 11, software: "Plaxis", date: "September 21, 2023", cost: 6201.00, year: "2023" },
15
+ { id: 12, software: "Tekla", date: "October 18, 2023", cost: 7792.20, year: "2023" },
16
+ { id: 13, software: "CSI [Etabs, SAFE, SAP2000]", date: "July 4, 2024", cost: 11336.00, year: "2024" },
17
+ { id: 14, software: "Plaxis", date: "September 18, 2024", cost: 7003.40, year: "2024" },
18
+ { id: 15, software: "Tekla", date: "October 10, 2024", cost: 14963.91, year: "2024" },
19
+ { id: 16, software: "CSI [Etabs, SAFE, SAP2000]", date: "May 22, 2025", cost: 11336.00, year: "2025" },
20
+ { id: 17, software: "Unreal Engine", date: "September 6, 2024", cost: 2727.18, year: "2024" },
21
+ { id: 18, software: "Plaxis", date: "September 18, 2025", cost: 7752.84, year: "2025" },
22
+ { id: 19, software: "Tekla", date: "November 26, 2025", cost: 15467.10, year: "2025" },
23
+ { id: 20, software: "Unreal Engine", date: "September 6, 2025", cost: 2744.62, year: "2025" }
24
+ ];
25
+
26
+ // Populate table
27
+ const tableBody = document.getElementById('data-table');
28
+ softwareData.forEach(item => {
29
+ const row = document.createElement('tr');
30
+ row.innerHTML = `
31
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item.id}</td>
32
+ <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">${item.software}</td>
33
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item.date}</td>
34
+ <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-primary">SGD ${item.cost.toLocaleString('en-SG', {minimumFractionDigits: 2, maximumFractionDigits: 2})}</td>
35
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item.year}</td>
36
+ `;
37
+ tableBody.appendChild(row);
38
+ });
39
+
40
+ // Calculate summary stats
41
+ const totalSpend = softwareData.reduce((sum, item) => sum + item.cost, 0);
42
+ const years = [...new Set(softwareData.map(item => item.year))];
43
+ const avgAnnual = totalSpend / years.length;
44
+
45
+ // Find most expensive software
46
+ const softwareGroups = {};
47
+ softwareData.forEach(item => {
48
+ if (!softwareGroups[item.software]) {
49
+ softwareGroups[item.software] = 0;
50
+ }
51
+ softwareGroups[item.software] += item.cost;
52
+ });
53
+ const mostExpensive = Object.entries(softwareGroups).reduce((a, b) => a[1] > b[1] ? a : b);
54
+
55
+ // Update summary cards
56
+ document.getElementById('total-spend').textContent = `SGD ${totalSpend.toLocaleString('en-SG', {minimumFractionDigits: 2, maximumFractionDigits: 2})}`;
57
+ document.getElementById('avg-annual').textContent = `SGD ${avgAnnual.toLocaleString('en-SG', {minimumFractionDigits: 2, maximumFractionDigits: 2})}`;
58
+ document.getElementById('most-expensive').textContent = `${mostExpensive[0]} (SGD ${mostExpensive[1].toLocaleString('en-SG', {minimumFractionDigits: 2, maximumFractionDigits: 2})})`;
59
+
60
+ // Create yearly chart
61
+ const yearlyData = {};
62
+ softwareData.forEach(item => {
63
+ if (!yearlyData[item.year]) {
64
+ yearlyData[item.year] = 0;
65
+ }
66
+ yearlyData[item.year] += item.cost;
67
+ });
68
+
69
+ const yearlyLabels = Object.keys(yearlyData).sort();
70
+ const yearlyValues = yearlyLabels.map(year => yearlyData[year]);
71
+
72
+ const ctx = document.getElementById('yearly-chart').getContext('2d');
73
+ new Chart(ctx, {
74
+ type: 'bar',
75
+ data: {
76
+ labels: yearlyLabels,
77
+ datasets: [{
78
+ label: 'Yearly Software Spend (SGD)',
79
+ data: yearlyValues,
80
+ backgroundColor: '#3B82F6',
81
+ borderColor: '#2563EB',
82
+ borderWidth: 1
83
+ }]
84
+ },
85
+ options: {
86
+ responsive: true,
87
+ maintainAspectRatio: false,
88
+ scales: {
89
+ y: {
90
+ beginAtZero: true,
91
+ ticks: {
92
+ callback: function(value) {
93
+ return 'SGD ' + value.toLocaleString('en-SG');
94
+ }
95
+ }
96
+ }
97
+ },
98
+ plugins: {
99
+ tooltip: {
100
+ callbacks: {
101
+ label: function(context) {
102
+ return 'SGD ' + context.raw.toLocaleString('en-SG');
103
+ }
104
+ }
105
+ }
106
+ }
107
+ }
108
+ });
109
+
110
+ // View toggle functionality
111
+ document.getElementById('yearly-view').addEventListener('click', function() {
112
+ // In a real app, this would filter the table by year
113
+ alert('Yearly view would show aggregated data by year');
114
+ });
115
+
116
+ document.getElementById('software-view').addEventListener('click', function() {
117
+ // In a real app, this would group by software
118
+ alert('Software view would show data grouped by software');
119
+ });
120
+ });
style.css CHANGED
@@ -1,28 +1,27 @@
1
- body {
2
- padding: 2rem;
3
- font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
4
  }
5
 
6
- h1 {
7
- font-size: 16px;
8
- margin-top: 0;
 
9
  }
10
 
11
- p {
12
- color: rgb(107, 114, 128);
13
- font-size: 15px;
14
- margin-bottom: 10px;
15
- margin-top: 5px;
16
  }
17
 
18
- .card {
19
- max-width: 620px;
20
- margin: 0 auto;
21
- padding: 16px;
22
- border: 1px solid lightgray;
23
- border-radius: 16px;
24
- }
25
-
26
- .card p:last-child {
27
- margin-bottom: 0;
28
- }
 
1
+ /* Custom styles that can't be easily done with Tailwind */
2
+ #data-table tr:hover {
3
+ background-color: #f8fafc;
4
  }
5
 
6
+ /* Animation for table rows */
7
+ @keyframes fadeIn {
8
+ from { opacity: 0; transform: translateY(10px); }
9
+ to { opacity: 1; transform: translateY(0); }
10
  }
11
 
12
+ #data-table tr {
13
+ animation: fadeIn 0.3s ease-out forwards;
14
+ opacity: 0;
 
 
15
  }
16
 
17
+ /* Delay the animation for each row */
18
+ #data-table tr:nth-child(1) { animation-delay: 0.1s; }
19
+ #data-table tr:nth-child(2) { animation-delay: 0.2s; }
20
+ #data-table tr:nth-child(3) { animation-delay: 0.3s; }
21
+ #data-table tr:nth-child(4) { animation-delay: 0.4s; }
22
+ #data-table tr:nth-child(5) { animation-delay: 0.5s; }
23
+ #data-table tr:nth-child(6) { animation-delay: 0.6s; }
24
+ #data-table tr:nth-child(7) { animation-delay: 0.7s; }
25
+ #data-table tr:nth-child(8) { animation-delay: 0.8s; }
26
+ #data-table tr:nth-child(9) { animation-delay: 0.9s; }
27
+ #data-table tr:nth-child(10) { animation-delay: 1.0s; }