diff --git a/frontend/index.html b/frontend/index.html
index 5a7b03b..e052701 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -2163,6 +2163,14 @@
No history yet. Run your first analysis.
@@ -3065,6 +3073,50 @@
Quality Score
renderHistory();
toast('History cleared', 'info');
});
+
+document.getElementById('downloadJsonBtn').addEventListener('click', () => {
+ if (!history || history.length === 0) {
+ toast('No history to download', 'info');
+ return;
+ }
+ const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(history, null, 2));
+ const dlNode = document.createElement('a');
+ dlNode.setAttribute("href", dataStr);
+ dlNode.setAttribute("download", "history.json");
+ document.body.appendChild(dlNode);
+ dlNode.click();
+ dlNode.remove();
+ toast('Downloaded history.json', 'success');
+});
+
+document.getElementById('downloadCsvBtn').addEventListener('click', () => {
+ if (!history || history.length === 0) {
+ toast('No history to download', 'info');
+ return;
+ }
+
+ const headers = Object.keys(history[0]);
+ const csvRows = [];
+ csvRows.push(headers.join(','));
+
+ for (const row of history) {
+ const values = headers.map(header => {
+ let val = row[header] === null || row[header] === undefined ? '' : String(row[header]);
+ val = val.replace(/"/g, '""');
+ return `"${val}"`;
+ });
+ csvRows.push(values.join(','));
+ }
+
+ const csvContent = "data:text/csv;charset=utf-8," + encodeURIComponent(csvRows.join('\n'));
+ const dlNode = document.createElement('a');
+ dlNode.setAttribute("href", csvContent);
+ dlNode.setAttribute("download", "history.csv");
+ document.body.appendChild(dlNode);
+ dlNode.click();
+ dlNode.remove();
+ toast('Downloaded history.csv', 'success');
+});
function loadEntry(id) {
const entry = history.find(h => h.id === Number (id));
console.log(entry);
diff --git a/frontend/script.js b/frontend/script.js
index b641914..7466b68 100644
--- a/frontend/script.js
+++ b/frontend/script.js
@@ -135,6 +135,62 @@ document.getElementById('clearHistoryBtn').addEventListener('click', () => {
renderHistory();
});
+// ── Download History JSON ──
+document.getElementById('downloadJsonBtn').addEventListener('click', () => {
+
+ if (history.length === 0) {
+ showToast('No history to download');
+ return;
+ }
+
+ const blob = new Blob(
+ [JSON.stringify(history, null, 2)],
+ { type: 'application/json' }
+ );
+
+ const a = document.createElement('a');
+ a.href = URL.createObjectURL(blob);
+ a.download = 'analysis-history.json';
+ a.click();
+ URL.revokeObjectURL(a.href);
+
+});
+// ── Download History CSV ──
+document.getElementById('downloadCsvBtn').addEventListener('click', () => {
+
+ if (history.length === 0) {
+ showToast('No history to download');
+ return;
+ }
+
+ const headers = ['id', 'preview', 'mode', 'time'];
+
+ const rows = history.map(h =>
+ [
+ h.id,
+ `"${(h.preview || '').replace(/"/g, '""')}"`,
+ h.mode,
+ h.time
+ ].join(',')
+ );
+
+ const csvContent = [
+ headers.join(','),
+ ...rows
+ ].join('\n');
+
+ const blob = new Blob(
+ [csvContent],
+ { type: 'text/csv' }
+ );
+
+ const a = document.createElement('a');
+ a.href = URL.createObjectURL(blob);
+ a.download = 'analysis-history.csv';
+ a.click();
+URL.revokeObjectURL(a.href);
+});
+
// ── Run Button ──
runBtn.addEventListener('click', runAnalysis);