Skip to content

Commit 93b2d78

Browse files
Merge pull request steam-bell-92#1452 from Indrayani11-15/add-download-button-budget-tracker
Added export csv button to download
2 parents f672678 + 257bb7e commit 93b2d78

1 file changed

Lines changed: 114 additions & 4 deletions

File tree

web-app/js/projects/budget-tracker.js

Lines changed: 114 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,14 @@ function getBudgetTrackerHTML() {
114114
<div class="budget-panel transactions-panel">
115115
<div class="transactions-header">
116116
<h3><i class="fas fa-list"></i> History</h3>
117-
<button id="btnClearBudgetData" class="btn-clear-budget" type="button">
118-
<i class="fas fa-trash-can"></i> Clear All
119-
</button>
117+
<div class="transactions-header-actions">
118+
<button id="btnExportBudgetCsv" class="btn-export-budget" type="button" disabled>
119+
<i class="fas fa-file-csv"></i> Export CSV
120+
</button>
121+
<button id="btnClearBudgetData" class="btn-clear-budget" type="button">
122+
<i class="fas fa-trash-can"></i> Clear All
123+
</button>
124+
</div>
120125
</div>
121126
122127
<!-- Search and Filters -->
@@ -545,6 +550,50 @@ function getBudgetTrackerHTML() {
545550
padding-bottom: 0;
546551
}
547552
553+
.transactions-header-actions {
554+
display: flex;
555+
align-items: center;
556+
gap: 0.6rem;
557+
}
558+
559+
.btn-export-budget {
560+
background: transparent;
561+
border: 1px solid var(--success-color, #10b981);
562+
color: var(--success-color, #10b981);
563+
border-radius: 8px;
564+
padding: 0.4rem 0.8rem;
565+
font-size: 0.8rem;
566+
font-weight: 600;
567+
cursor: pointer;
568+
display: flex;
569+
align-items: center;
570+
gap: 0.3rem;
571+
transition: all 0.2s ease;
572+
}
573+
574+
.btn-export-budget:hover:not(:disabled) {
575+
background: var(--success-color, #10b981);
576+
color: white;
577+
box-shadow: 0 2px 8px rgba(16, 185, 129, 0.25);
578+
}
579+
580+
.btn-export-budget:active:not(:disabled) {
581+
transform: scale(0.96);
582+
}
583+
584+
.btn-export-budget:disabled {
585+
opacity: 0.45;
586+
cursor: not-allowed;
587+
border-color: var(--border-color);
588+
color: var(--text-secondary);
589+
}
590+
591+
.btn-export-budget.exported {
592+
background: var(--success-color, #10b981);
593+
color: white;
594+
border-color: var(--success-color, #10b981);
595+
}
596+
548597
.btn-clear-budget {
549598
background: transparent;
550599
border: 1px solid #ef4444;
@@ -864,6 +913,7 @@ function initBudgetTracker() {
864913
const searchInput = document.getElementById("budgetSearchInput");
865914
const filterType = document.getElementById("budgetFilterType");
866915
const clearBtn = document.getElementById("btnClearBudgetData");
916+
const exportBtn = document.getElementById("btnExportBudgetCsv");
867917

868918
// Exit early if elements not found
869919
if (!form || !categorySelect || !transactionsList) return;
@@ -983,7 +1033,64 @@ function initBudgetTracker() {
9831033
}
9841034
});
9851035

1036+
exportBtn.addEventListener("click", exportTransactionsToCsv);
1037+
9861038
// Helper functions
1039+
function csvEscape(value) {
1040+
const str = String(value === undefined || value === null ? "" : value);
1041+
if (/[",\n]/.test(str)) {
1042+
return `"${str.replace(/"/g, '""')}"`;
1043+
}
1044+
return str;
1045+
}
1046+
1047+
function exportTransactionsToCsv() {
1048+
if (!transactions.length) return;
1049+
1050+
const header = ["Date", "Type", "Category", "Description", "Amount (INR)"];
1051+
const rows = transactions.map(t => [
1052+
t.date,
1053+
t.type,
1054+
t.category,
1055+
t.description || "",
1056+
t.amount.toFixed(2)
1057+
]);
1058+
1059+
const csvContent = [header, ...rows]
1060+
.map(row => row.map(csvEscape).join(","))
1061+
.join("\r\n");
1062+
1063+
const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
1064+
const url = URL.createObjectURL(blob);
1065+
1066+
const now = new Date();
1067+
const dateStr = now.getFullYear() + '-' +
1068+
String(now.getMonth() + 1).padStart(2, '0') + '-' +
1069+
String(now.getDate()).padStart(2, '0');
1070+
1071+
const link = document.createElement("a");
1072+
link.href = url;
1073+
link.download = `budget-tracker-${dateStr}.csv`;
1074+
document.body.appendChild(link);
1075+
link.click();
1076+
document.body.removeChild(link);
1077+
1078+
// Free the blob URL once the download has been triggered
1079+
setTimeout(() => URL.revokeObjectURL(url), 100);
1080+
1081+
// Brief visual confirmation
1082+
const originalHTML = exportBtn.innerHTML;
1083+
exportBtn.classList.add("exported");
1084+
exportBtn.innerHTML = '<i class="fas fa-check"></i> Downloaded!';
1085+
exportBtn.disabled = true;
1086+
1087+
setTimeout(() => {
1088+
exportBtn.classList.remove("exported");
1089+
exportBtn.innerHTML = originalHTML;
1090+
exportBtn.disabled = transactions.length === 0;
1091+
}, 2000);
1092+
}
1093+
9871094
function onTypeChange() {
9881095
populateCategories();
9891096
}
@@ -1018,6 +1125,9 @@ function initBudgetTracker() {
10181125
updateSummary();
10191126
renderBreakdown();
10201127
renderTransactions();
1128+
if (exportBtn) {
1129+
exportBtn.disabled = transactions.length === 0;
1130+
}
10211131
}
10221132

10231133
function updateSummary() {
@@ -1152,4 +1262,4 @@ function initBudgetTracker() {
11521262
transactionsList.appendChild(row);
11531263
});
11541264
}
1155-
}
1265+
}

0 commit comments

Comments
 (0)