feat(frontend): add /gdpr page with PDF export and JSON download

New /gdpr route: skeleton loading state, 2s polling for async export, styled report cards/tables matching /schedule and /account styling. 16 data sections with conditional rendering (empty sections hidden). VAT breakdowns hidden until any payment has non-zero VAT. Deposits Required hidden when 0. PDF export via window.print() with print CSS hiding navbar and verification banner. Raw JSON download button. Export My Data button added to Account page under Change Password. Vite worker format set to 'es' for WASM encoder compatibility.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-06-05 12:13:07 +01:00
co-authored by Sisyphus
parent b460c2ec20
commit 36ad38f670
4 changed files with 1049 additions and 0 deletions
+14
View File
@@ -68,3 +68,17 @@
{/if} {/if}
{@render children?.()} {@render children?.()}
</main> </main>
<style>
@media print {
:global(nav) {
display: none !important;
}
:global(main > div.bg-red-600) {
display: none !important;
}
:global(main) {
padding-top: 0 !important;
}
}
</style>
+18
View File
@@ -1550,6 +1550,24 @@
<Separator /> <Separator />
<!-- Export My Data -->
<div>
<h3 class="mb-2 text-sm font-semibold">Data Privacy</h3>
<p class="mb-3 text-sm text-gray-600">
View and export all personal data we hold about you
</p>
<Button onclick={() => goto('/gdpr')} variant="outline">
<svg xmlns="http://www.w3.org/2000/svg" class="mr-2 h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="7 10 12 15 17 10"/>
<line x1="12" y1="15" x2="12" y2="3"/>
</svg>
Export My Data
</Button>
</div>
<Separator />
<!-- Notification Preferences (non-admin users only) --> <!-- Notification Preferences (non-admin users only) -->
{#if authStore.currentUser?.role !== 'admin'} {#if authStore.currentUser?.role !== 'admin'}
<div> <div>
File diff suppressed because it is too large Load Diff
+3
View File
@@ -7,5 +7,8 @@ export default defineConfig({
assetsInclude: ['**/*.wasm'], assetsInclude: ['**/*.wasm'],
optimizeDeps: { optimizeDeps: {
exclude: ['@discourse/jxl', '@jsquash/avif', '@jsquash/webp', '@jsquash/jpeg'] exclude: ['@discourse/jxl', '@jsquash/avif', '@jsquash/webp', '@jsquash/jpeg']
},
worker: {
format: 'es'
} }
}); });