From a0f99d9fba8a4aa5d23ee829e5aa14ea3124c2cc Mon Sep 17 00:00:00 2001 From: Adam French Date: Mon, 13 Apr 2026 09:53:30 +0100 Subject: [PATCH] Add CSV export to job applications tracker Co-Authored-By: Claude Sonnet 4.6 --- vue/src/views/CV/JobApplications.vue | 37 ++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/vue/src/views/CV/JobApplications.vue b/vue/src/views/CV/JobApplications.vue index e3fa443..59b270c 100644 --- a/vue/src/views/CV/JobApplications.vue +++ b/vue/src/views/CV/JobApplications.vue @@ -113,6 +113,29 @@ async function deleteApplication(id) { } } +function exportCsv() { + const headers = ["Job Title", "Company", "Status", "Location", "URL", "Applied", "Notes", "Created"]; + const rows = applications.value.map((a) => [ + a.jobTitle, + a.company, + a.status, + a.location ?? "", + a.url ?? "", + a.appliedAt ? a.appliedAt.substring(0, 10) : "", + a.notes ?? "", + a.createdAt ? a.createdAt.substring(0, 10) : "", + ]); + const escape = (v) => `"${String(v).replace(/"/g, '""')}"`; + const csv = [headers, ...rows].map((r) => r.map(escape).join(",")).join("\n"); + const blob = new Blob([csv], { type: "text/csv" }); + const url = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = "job_applications.csv"; + a.click(); + URL.revokeObjectURL(url); +} + function statusClass(status) { const map = { Applied: "status-applied", @@ -136,7 +159,10 @@ onMounted(() => {