- Use @RequiredArgsConstructor in AuditLogQueryService; remove unused import
- Add 401/403 tests for /activity endpoint
- Add getPulseStats and findContributorsPerDocument integration tests
- Use m.pulse_headline/pulse_you in FamilyPulse; composite avatar keys
- Replace hover:text-accent with hover:text-ink in ActivityFeed (WCAG AA)
- Localise "Alle →" link with feed_show_all key + aria-label
- Gate DropZone behind {#if data.canWrite}
- Export DashboardResumeDTO, DashboardPulseDTO, ActivityFeedItemDTO from api.ts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
71 lines
2.3 KiB
Svelte
71 lines
2.3 KiB
Svelte
<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">
|
|
{m.pulse_headline({ pages: pulse.pages })}
|
|
</h2>
|
|
{/if}
|
|
|
|
{#if pulse.yourPages > 0}
|
|
<p class="font-serif text-sm text-ink-2">
|
|
{m.pulse_you({ pages: pulse.yourPages })}
|
|
</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 + c.color)}
|
|
<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}
|