diff --git a/web/src/lib/components/StageBadge.svelte b/web/src/lib/components/StageBadge.svelte
new file mode 100644
index 00000000..1da8fd8d
--- /dev/null
+++ b/web/src/lib/components/StageBadge.svelte
@@ -0,0 +1,22 @@
+
+
+{#if state === 'in_progress'}
+
+
+ Processing
+
+{:else if state === 'done'}
+
+
+ Done
+
+{:else if state === 'pending'}
+ Pending
+{:else}
+ Skipped
+{/if}
diff --git a/web/src/lib/components/StageBadge.test.ts b/web/src/lib/components/StageBadge.test.ts
new file mode 100644
index 00000000..c03536a3
--- /dev/null
+++ b/web/src/lib/components/StageBadge.test.ts
@@ -0,0 +1,31 @@
+import { describe, it, expect } from 'vitest';
+import { render, screen } from '@testing-library/svelte';
+import StageBadge from './StageBadge.svelte';
+
+describe('StageBadge', () => {
+ it('renders Processing + spinner when state is in_progress', () => {
+ render(StageBadge, { props: { state: 'in_progress' } });
+ expect(screen.getByText('Processing')).toBeInTheDocument();
+ // The spinner is a lucide icon — just confirm a child SVG exists.
+ expect(document.querySelector('svg')).toBeTruthy();
+ });
+
+ it('renders Done + check when state is done', () => {
+ render(StageBadge, { props: { state: 'done' } });
+ expect(screen.getByText('Done')).toBeInTheDocument();
+ expect(document.querySelector('svg')).toBeTruthy();
+ });
+
+ it('renders Pending muted when state is pending', () => {
+ render(StageBadge, { props: { state: 'pending' } });
+ expect(screen.getByText('Pending')).toBeInTheDocument();
+ // No icon for the muted states.
+ expect(document.querySelector('svg')).toBeFalsy();
+ });
+
+ it('renders Skipped muted when state is skipped', () => {
+ render(StageBadge, { props: { state: 'skipped' } });
+ expect(screen.getByText('Skipped')).toBeInTheDocument();
+ expect(document.querySelector('svg')).toBeFalsy();
+ });
+});
diff --git a/web/src/routes/admin/+page.svelte b/web/src/routes/admin/+page.svelte
index 6bb1165b..56f84b66 100644
--- a/web/src/routes/admin/+page.svelte
+++ b/web/src/routes/admin/+page.svelte
@@ -1,6 +1,8 @@