118 lines
3.3 KiB
Svelte
118 lines
3.3 KiB
Svelte
<script lang="ts">
|
|
import { m } from '$lib/paraglide/messages.js';
|
|
import DistributionBar from '$lib/shared/primitives/DistributionBar.svelte';
|
|
import ThumbnailRow from '$lib/document/ThumbnailRow.svelte';
|
|
|
|
type Person = { id: string; firstName?: string | null; lastName: string; displayName: string };
|
|
type Tag = { id: string; name: string };
|
|
|
|
interface Props {
|
|
documents: {
|
|
id: string;
|
|
title?: string;
|
|
originalFilename: string;
|
|
documentDate?: string;
|
|
location?: string;
|
|
summary?: string;
|
|
contentType?: string;
|
|
thumbnailKey?: string;
|
|
thumbnailGeneratedAt?: string;
|
|
thumbnailAspect?: 'PORTRAIT' | 'LANDSCAPE';
|
|
pageCount?: number;
|
|
sender?: Person | null;
|
|
receivers?: Person[];
|
|
tags?: Tag[];
|
|
}[];
|
|
senderId: string;
|
|
receiverId?: string;
|
|
canWrite: boolean;
|
|
senderName?: string;
|
|
receiverName?: string;
|
|
}
|
|
|
|
let { documents, senderId, receiverId, canWrite, senderName, receiverName }: Props = $props();
|
|
|
|
const enrichedDocuments = $derived(
|
|
documents.map((doc, i) => {
|
|
const year = doc.documentDate ? new Date(doc.documentDate).getFullYear() : null;
|
|
const prevYear =
|
|
i > 0 && documents[i - 1].documentDate
|
|
? new Date(documents[i - 1].documentDate!).getFullYear()
|
|
: null;
|
|
const isOut = doc.sender?.id === senderId;
|
|
return { doc, year, showYearDivider: year !== null && year !== prevYear, isOut };
|
|
})
|
|
);
|
|
|
|
const countsByYear = $derived(
|
|
documents.reduce((acc, d) => {
|
|
if (d.documentDate) {
|
|
const y = new Date(d.documentDate).getFullYear();
|
|
acc.set(y, (acc.get(y) ?? 0) + 1);
|
|
}
|
|
return acc;
|
|
}, new Map<number, number>())
|
|
);
|
|
|
|
const outCount = $derived(documents.filter((d) => d.sender?.id === senderId).length);
|
|
const inCount = $derived(documents.length - outCount);
|
|
|
|
const isBilateral = $derived(!!senderId && !!receiverId);
|
|
const showOtherParty = $derived(!receiverId);
|
|
|
|
const newDocUrl = $derived(
|
|
`/documents/new?senderId=${encodeURIComponent(senderId)}${receiverId ? `&receiverId=${encodeURIComponent(receiverId)}` : ''}`
|
|
);
|
|
</script>
|
|
|
|
{#if isBilateral && documents.length > 0}
|
|
<DistributionBar
|
|
outCount={outCount}
|
|
inCount={inCount}
|
|
senderName={senderName ?? ''}
|
|
receiverName={receiverName ?? ''}
|
|
/>
|
|
{/if}
|
|
|
|
<div class="overflow-hidden rounded-sm border border-line bg-surface">
|
|
{#each enrichedDocuments as { doc, year, showYearDivider, isOut } (doc.id)}
|
|
{#if showYearDivider && year !== null}
|
|
<div
|
|
data-testid="year-divider"
|
|
class="flex items-baseline gap-3 border-t-2 border-b border-line bg-muted px-[14px] py-[8px]"
|
|
>
|
|
<span class="text-2xl font-black tracking-tight text-primary">{year}</span>
|
|
<span class="text-sm font-bold text-ink-3">{countsByYear.get(year) ?? 0} Briefe</span>
|
|
</div>
|
|
{/if}
|
|
|
|
<ThumbnailRow doc={doc} isOut={isOut} showOtherParty={showOtherParty} />
|
|
{/each}
|
|
|
|
{#if canWrite}
|
|
<div class="flex justify-end border-t border-line px-[14px] py-[6px]">
|
|
<a
|
|
href={newDocUrl}
|
|
data-testid="conv-new-doc-link"
|
|
class="inline-flex items-center gap-1 text-xs font-bold text-primary/50 transition-colors hover:text-primary"
|
|
>
|
|
<svg
|
|
class="h-3 w-3"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
aria-hidden="true"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M12 4v16m8-8H4"
|
|
/>
|
|
</svg>
|
|
{m.conv_new_doc_link()}
|
|
</a>
|
|
</div>
|
|
{/if}
|
|
</div>
|