From 92e7aa127c3e5301482bfccd0989d34a99948bc5 Mon Sep 17 00:00:00 2001 From: Marcel Date: Tue, 31 Mar 2026 19:36:36 +0200 Subject: [PATCH] =?UTF-8?q?feat(dashboard):=20Classic=20Split=20=E2=80=94?= =?UTF-8?q?=202-col=20layout,=20remove=20DashboardMentions=20widget?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructures the dashboard to a lg:grid-cols-[1fr_300px] split: - Left column: DashboardRecentDocuments (with stats footnote) - Right column: DropZone (canWrite) + DashboardNeedsMetadata (flex-1) Adds showRightColumn guard (canWrite || incompleteDocs.length > 0) so read-only users with a complete archive never see an empty 300px ghost column. DashboardMentions is removed from the page; the file is kept. Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/routes/+page.svelte | 36 +++++++++++++--------- frontend/src/routes/page.svelte.spec.ts | 40 +++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 14 deletions(-) diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index 528d5428..15612d4f 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -6,7 +6,6 @@ import SearchFilterBar from './SearchFilterBar.svelte'; import DropZone from './DropZone.svelte'; import DocumentList from './DocumentList.svelte'; import DashboardResumeStrip from '$lib/components/DashboardResumeStrip.svelte'; -import DashboardMentions from '$lib/components/DashboardMentions.svelte'; import DashboardNeedsMetadata from '$lib/components/DashboardNeedsMetadata.svelte'; import DashboardRecentDocuments from '$lib/components/DashboardRecentDocuments.svelte'; import { m } from '$lib/paraglide/messages.js'; @@ -69,6 +68,11 @@ $effect(() => { tagNames = data.filters?.tags || []; if (hasAdvancedFilters(data.filters)) showAdvanced = true; }); + +// Right column is only rendered when there is something to show. +// Omitting it prevents an empty 300px ghost column for read-only users +// with a complete archive. +const showRightColumn = $derived(data.canWrite || (data.incompleteDocs?.length ?? 0) > 0); @@ -94,20 +98,24 @@ $effect(() => { {#if data.isDashboard} - {#if data.canWrite} -
- -
- {/if} + + +
+ -
- - -
-
- + {#if showRightColumn} +
+ {#if data.canWrite} + + {/if} + +
+ +
+
+ {/if}
{:else} diff --git a/frontend/src/routes/page.svelte.spec.ts b/frontend/src/routes/page.svelte.spec.ts index 09956fc7..8a280c1a 100644 --- a/frontend/src/routes/page.svelte.spec.ts +++ b/frontend/src/routes/page.svelte.spec.ts @@ -21,8 +21,12 @@ const emptyData = { user: undefined, canWrite: true, canAnnotate: false, + isDashboard: false, filters: { q: '', from: '', to: '', senderId: '', receiverId: '', tags: [] }, documents: [], + incompleteDocs: [], + recentDocs: [], + stats: null, incompleteCount: 0, initialValues: { senderName: '', receiverName: '' }, error: null @@ -189,6 +193,42 @@ describe('Home page – search input keystroke preservation', () => { }); }); +// ─── Dashboard mode ─────────────────────────────────────────────────────────── + +describe('Home page – dashboard mode', () => { + const dashboardData = { + ...emptyData, + isDashboard: true, + canWrite: false, + incompleteDocs: [], + recentDocs: [] + }; + + it('hides the right column when canWrite is false and incompleteDocs is empty', async () => { + render(Page, { data: dashboardData }); + const rightCol = page.getByTestId('dashboard-right-column'); + await expect.element(rightCol).not.toBeInTheDocument(); + }); + + it('shows the right column when canWrite is true', async () => { + render(Page, { data: { ...dashboardData, canWrite: true } }); + const rightCol = page.getByTestId('dashboard-right-column'); + await expect.element(rightCol).toBeInTheDocument(); + }); + + it('shows the right column when incompleteDocs is non-empty', async () => { + render(Page, { + data: { + ...dashboardData, + canWrite: false, + incompleteDocs: [{ id: 'd1', title: 'Taufschein' }] + } + }); + const rightCol = page.getByTestId('dashboard-right-column'); + await expect.element(rightCol).toBeInTheDocument(); + }); +}); + // ─── Error state ────────────────────────────────────────────────────────────── describe('Home page – error state', () => {