diff --git a/frontend/src/lib/components/DashboardNeedsMetadata.svelte b/frontend/src/lib/components/DashboardNeedsMetadata.svelte
new file mode 100644
index 00000000..31daab3c
--- /dev/null
+++ b/frontend/src/lib/components/DashboardNeedsMetadata.svelte
@@ -0,0 +1,38 @@
+
+
+{#if incompleteDocs.length > 0}
+
+
+ Metadaten fehlen
+
+ {#each incompleteDocs as doc (doc.id)}
+
+ {/each}
+
+
+{/if}
diff --git a/frontend/src/lib/components/DashboardNeedsMetadata.svelte.spec.ts b/frontend/src/lib/components/DashboardNeedsMetadata.svelte.spec.ts
new file mode 100644
index 00000000..ee2fdeb8
--- /dev/null
+++ b/frontend/src/lib/components/DashboardNeedsMetadata.svelte.spec.ts
@@ -0,0 +1,49 @@
+import { describe, it, expect, afterEach } from 'vitest';
+import { cleanup, render } from 'vitest-browser-svelte';
+import { page } from 'vitest/browser';
+
+import DashboardNeedsMetadata from './DashboardNeedsMetadata.svelte';
+
+afterEach(cleanup);
+
+type IncompleteDocumentDTO = {
+ id: string;
+ title: string;
+};
+
+function makeDoc(id: string, title: string): IncompleteDocumentDTO {
+ return { id, title };
+}
+
+describe('DashboardNeedsMetadata', () => {
+ it('renders nothing when incompleteDocs is empty', async () => {
+ render(DashboardNeedsMetadata, { incompleteDocs: [] });
+ const widget = page.getByTestId('dashboard-needs-metadata');
+ await expect.element(widget).not.toBeInTheDocument();
+ });
+
+ it('shows the widget when incompleteDocs are present', async () => {
+ render(DashboardNeedsMetadata, { incompleteDocs: [makeDoc('d1', 'Taufschein')] });
+ const widget = page.getByTestId('dashboard-needs-metadata');
+ await expect.element(widget).toBeInTheDocument();
+ });
+
+ it('renders a link to /enrich/{id} for each document', async () => {
+ const docs = [makeDoc('d1', 'Taufschein'), makeDoc('d2', 'Heiratsurkunde')];
+ render(DashboardNeedsMetadata, { incompleteDocs: docs });
+ const links = page.getByRole('link');
+ await expect.element(links.nth(0)).toHaveAttribute('href', '/enrich/d1');
+ await expect.element(links.nth(1)).toHaveAttribute('href', '/enrich/d2');
+ });
+
+ it('shows the document title in each row', async () => {
+ render(DashboardNeedsMetadata, { incompleteDocs: [makeDoc('d1', 'Sterbeurkunde 1930')] });
+ await expect.element(page.getByText('Sterbeurkunde 1930')).toBeInTheDocument();
+ });
+
+ it('shows a "Alle anzeigen" link to /enrich', async () => {
+ render(DashboardNeedsMetadata, { incompleteDocs: [makeDoc('d1', 'Dok')] });
+ const allLink = page.getByRole('link', { name: /Alle anzeigen/i });
+ await expect.element(allLink).toHaveAttribute('href', '/enrich');
+ });
+});