feat(dashboard): complete frontend redesign for Issue #271
Some checks failed
CI / OCR Service Tests (push) Successful in 29s
CI / Backend Unit Tests (push) Failing after 1m21s
CI / Unit & Component Tests (push) Failing after 2m37s
CI / Unit & Component Tests (pull_request) Failing after 2m27s
CI / OCR Service Tests (pull_request) Successful in 30s
CI / Backend Unit Tests (pull_request) Failing after 1m21s

- +layout.svelte: Upload button in header (authenticated users only)
- +page.server.ts: call /api/dashboard/resume, /pulse, /activity;
  remove deprecated /api/documents/incomplete and /recent-activity
- +page.svelte: 2-col grid layout (main + 320px sidebar), greeting,
  DashboardFamilyPulse + DashboardActivityFeed in sidebar
- DashboardResumeStrip: refactored to use server data (resumeDoc prop),
  SVG thumbnail, progress bar with aria-*, empty state, CTA
- DashboardFamilyPulse: new component — weekly stats from audit_log
- DashboardActivityFeed: new component — activity feed with "für dich" badge
- Update specs for new data shapes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-19 17:44:08 +02:00
parent 99247ed58d
commit 10dbce1c70
10 changed files with 488 additions and 157 deletions

View File

@@ -0,0 +1,70 @@
<script lang="ts">
import * as m from '$lib/paraglide/messages.js';
import type { DashboardPulseDTO } from '$lib/generated/api';
interface Props {
pulse: DashboardPulseDTO | null;
}
const { pulse }: Props = $props();
</script>
{#if pulse !== null}
<section class="rounded-sm border border-line bg-surface p-5">
<p class="font-sans text-[11px] font-bold tracking-[.12em] text-ink-3 uppercase">
{m.pulse_eyebrow()}
</p>
{#if pulse.pages > 0}
<h2 class="mt-1 font-serif text-[1.375rem] leading-snug text-ink">
Ihr habt <strong>{pulse.pages}</strong> Seiten bearbeitet.
</h2>
{/if}
{#if pulse.yourPages > 0}
<p class="font-serif text-sm text-ink-2">
Du selbst hast {pulse.yourPages} davon bearbeitet.
</p>
{/if}
{#if pulse.contributors.length > 0}
<div class="mt-3 flex items-center gap-1">
<p class="mr-1 font-sans text-[11px] text-ink-3">{m.pulse_contributors()}</p>
{#each pulse.contributors as c (c.initials)}
<span
class="-ml-2 inline-flex h-7 w-7 items-center justify-center rounded-full font-sans text-[11px] font-bold text-white ring-2 ring-white first:ml-0"
style="background:{c.color}"
title={c.name ?? ''}>{c.initials}</span
>
{/each}
</div>
{/if}
<div class="mt-4 grid grid-cols-3 gap-2">
<div class="flex flex-col gap-0.5">
<span class="font-serif text-[1.875rem] leading-none font-bold text-ink"
>{pulse.annotated}</span
>
<span class="flex items-center gap-1 font-sans text-[11px] text-ink-3">
<span class="text-[8px]" style="color:#00c7b1"></span>{m.pulse_transcribed()}
</span>
</div>
<div class="flex flex-col gap-0.5">
<span class="font-serif text-[1.875rem] leading-none font-bold text-ink"
>{pulse.transcribed}</span
>
<span class="flex items-center gap-1 font-sans text-[11px] text-ink-3">
<span class="text-[8px]" style="color:#5a8a6a"></span>{m.pulse_reviewed()}
</span>
</div>
<div class="flex flex-col gap-0.5">
<span class="font-serif text-[1.875rem] leading-none font-bold text-ink"
>{pulse.uploaded}</span
>
<span class="flex items-center gap-1 font-sans text-[11px] text-ink-3">
<span class="text-[8px]" style="color:#3060b0"></span>{m.pulse_uploaded()}
</span>
</div>
</div>
</section>
{/if}