feat(#145): update home page server load for dashboard mode

- Add isDashboard flag (true when no search filters active)
- In dashboard mode: fetch mentions, incompleteDocs, recentDocs via
  Promise.allSettled so widget failures don't crash the page
- In search mode: skip widget fetches for performance
- Replace incomplete-count fetch with list fetch (derive count from
  list.length)
- Update enrich page to use IncompleteDocumentDTO (id + title only)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-03-29 00:32:52 +01:00
parent 4aa3855936
commit 0610f0ee0f
2 changed files with 63 additions and 34 deletions

View File

@@ -1,5 +1,10 @@
import { redirect } from '@sveltejs/kit';
import { createApiClient } from '$lib/api.server';
import type { components } from '$lib/generated/api';
type IncompleteDocumentDTO = components['schemas']['IncompleteDocumentDTO'];
type NotificationDTO = components['schemas']['NotificationDTO'];
type Document = components['schemas']['Document'];
export async function load({ url, fetch }) {
const q = url.searchParams.get('q') || '';
@@ -9,44 +14,76 @@ export async function load({ url, fetch }) {
const receiverId = url.searchParams.get('receiverId') || '';
const tags = url.searchParams.getAll('tag');
const isDashboard = !q && !from && !to && !senderId && !receiverId && !tags.length;
const api = createApiClient(fetch);
try {
const [docsResult, personsResult, incompleteCountResult] = await Promise.all([
api.GET('/api/documents/search', {
params: {
query: {
q: q || undefined,
from: from || undefined,
to: to || undefined,
senderId: senderId || undefined,
receiverId: receiverId || undefined,
tag: tags.length ? tags : undefined
}
}
}),
api.GET('/api/persons'),
api.GET('/api/documents/incomplete-count')
const [docsResult, personsResult] = await Promise.all([
isDashboard
? Promise.resolve(null)
: api.GET('/api/documents/search', {
params: {
query: {
q: q || undefined,
from: from || undefined,
to: to || undefined,
senderId: senderId || undefined,
receiverId: receiverId || undefined,
tag: tags.length ? tags : undefined
}
}
}),
api.GET('/api/persons')
]);
if (docsResult.response.status === 401 || personsResult.response.status === 401) {
if (personsResult.response.status === 401) {
throw redirect(302, '/login');
}
if (docsResult && docsResult.response.status === 401) {
throw redirect(302, '/login');
}
const documents = docsResult.data ?? [];
const documents: Document[] = docsResult?.data ?? [];
const allPersons: { id: string; firstName: string; lastName: string }[] =
personsResult.data ?? [];
const senderObj = allPersons.find((p) => p.id === senderId);
const receiverObj = allPersons.find((p) => p.id === receiverId);
const incompleteCount = incompleteCountResult.response.ok
? (incompleteCountResult.data?.count ?? 0)
: 0;
// Dashboard widgets — failures are isolated and don't crash the page
let mentions: NotificationDTO[] = [];
let incompleteDocs: IncompleteDocumentDTO[] = [];
let recentDocs: Document[] = [];
if (isDashboard) {
const [mentionsResult, incompleteResult, recentResult] = await Promise.allSettled([
api.GET('/api/notifications', {
params: { query: { type: 'MENTION', read: false, size: 5 } }
}),
api.GET('/api/documents/incomplete', { params: { query: { size: 5 } } }),
api.GET('/api/documents/search', {
params: { query: { status: 'REVIEWED' } }
})
]);
if (mentionsResult.status === 'fulfilled' && mentionsResult.value.response.ok) {
mentions = mentionsResult.value.data?.content ?? [];
}
if (incompleteResult.status === 'fulfilled' && incompleteResult.value.response.ok) {
incompleteDocs = incompleteResult.value.data ?? [];
}
if (recentResult.status === 'fulfilled' && recentResult.value.response.ok) {
recentDocs = (recentResult.value.data ?? []).slice(0, 5);
}
}
return {
isDashboard,
documents,
incompleteCount,
mentions,
incompleteDocs,
recentDocs,
initialValues: {
senderName: senderObj ? `${senderObj.firstName} ${senderObj.lastName}` : '',
receiverName: receiverObj ? `${receiverObj.firstName} ${receiverObj.lastName}` : ''
@@ -58,8 +95,11 @@ export async function load({ url, fetch }) {
if ((e as { status?: number }).status) throw e;
console.error('Error loading data:', e);
return {
isDashboard,
documents: [],
incompleteCount: 0,
mentions: [],
incompleteDocs: [],
recentDocs: [],
initialValues: { senderName: '', receiverName: '' },
filters: { q, from, to, senderId, receiverId, tags },
error: 'Daten konnten nicht geladen werden.' as string | null

View File

@@ -5,14 +5,6 @@ let { data } = $props();
const documents = $derived(data.documents);
const count = $derived(documents.length);
function formatUploadDate(createdAt: string): string {
return new Intl.DateTimeFormat('de-DE', {
day: 'numeric',
month: 'long',
year: 'numeric'
}).format(new Date(createdAt));
}
</script>
<div class="mx-auto max-w-4xl px-4 py-10">
@@ -85,10 +77,7 @@ function formatUploadDate(createdAt: string): string {
<p
class="font-serif text-lg font-medium text-ink decoration-accent decoration-2 underline-offset-4 group-hover:underline"
>
{doc.title || doc.originalFilename}
</p>
<p class="mt-1 font-sans text-xs text-ink-3">
{formatUploadDate(doc.createdAt)}
{doc.title}
</p>
</div>
<img