diff --git a/frontend/src/lib/activity/ChronikEmptyState.svelte b/frontend/src/lib/activity/ChronikEmptyState.svelte deleted file mode 100644 index ecf2b865..00000000 --- a/frontend/src/lib/activity/ChronikEmptyState.svelte +++ /dev/null @@ -1,92 +0,0 @@ - - -
- {#if variant === 'first-run'} - - {:else if variant === 'filter-empty'} - - {:else} - - {/if} - -

- {title} -

- {#if body} -

- {body} -

- {/if} -
diff --git a/frontend/src/lib/activity/ChronikEmptyState.svelte.spec.ts b/frontend/src/lib/activity/ChronikEmptyState.svelte.spec.ts deleted file mode 100644 index 4e3446a4..00000000 --- a/frontend/src/lib/activity/ChronikEmptyState.svelte.spec.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { describe, it, expect, afterEach } from 'vitest'; -import { cleanup, render } from 'vitest-browser-svelte'; -import { page } from 'vitest/browser'; - -import ChronikEmptyState from './ChronikEmptyState.svelte'; - -afterEach(cleanup); - -describe('ChronikEmptyState', () => { - it('renders first-run variant title', async () => { - render(ChronikEmptyState, { variant: 'first-run' }); - await expect.element(page.getByText('Noch nichts geschehen')).toBeInTheDocument(); - }); - - it('renders filter-empty variant title', async () => { - render(ChronikEmptyState, { variant: 'filter-empty' }); - await expect.element(page.getByText('Nichts in dieser Ansicht')).toBeInTheDocument(); - }); - - it('renders inbox-zero variant title', async () => { - render(ChronikEmptyState, { variant: 'inbox-zero' }); - await expect.element(page.getByText('Keine neuen Erwähnungen')).toBeInTheDocument(); - }); - - it('applies the expected data-variant attribute', async () => { - render(ChronikEmptyState, { variant: 'first-run' }); - const wrapper = document.querySelector('[data-testid="chronik-empty-state"]'); - expect(wrapper?.getAttribute('data-variant')).toBe('first-run'); - }); -}); diff --git a/frontend/src/lib/activity/ChronikEmptyState.svelte.test.ts b/frontend/src/lib/activity/ChronikEmptyState.svelte.test.ts deleted file mode 100644 index 920a76db..00000000 --- a/frontend/src/lib/activity/ChronikEmptyState.svelte.test.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { describe, it, expect, afterEach } from 'vitest'; -import { cleanup, render } from 'vitest-browser-svelte'; -import { page } from 'vitest/browser'; -import ChronikEmptyState from './ChronikEmptyState.svelte'; - -afterEach(cleanup); - -describe('ChronikEmptyState', () => { - it('renders the first-run title and body and the clock icon', async () => { - render(ChronikEmptyState, { props: { variant: 'first-run' as const } }); - - await expect.element(page.getByText('Noch nichts geschehen')).toBeVisible(); - await expect.element(page.getByText(/sobald jemand aus der familie/i)).toBeVisible(); - - const wrapper = document.querySelector('[data-testid="chronik-empty-state"]'); - expect(wrapper?.getAttribute('data-variant')).toBe('first-run'); - }); - - it('renders the filter-empty title and body', async () => { - render(ChronikEmptyState, { props: { variant: 'filter-empty' as const } }); - - await expect.element(page.getByText('Nichts in dieser Ansicht')).toBeVisible(); - await expect.element(page.getByText('In diesem Filter gibt es keine Einträge.')).toBeVisible(); - - const wrapper = document.querySelector('[data-testid="chronik-empty-state"]'); - expect(wrapper?.getAttribute('data-variant')).toBe('filter-empty'); - }); - - it('renders the inbox-zero title and no body paragraph', async () => { - render(ChronikEmptyState, { props: { variant: 'inbox-zero' as const } }); - - await expect.element(page.getByText('Keine neuen Erwähnungen')).toBeVisible(); - - // Only one

(the title) since body is empty - const wrapper = document.querySelector('[data-testid="chronik-empty-state"]'); - const paragraphs = wrapper?.querySelectorAll('p'); - expect(paragraphs?.length).toBe(1); - expect(wrapper?.getAttribute('data-variant')).toBe('inbox-zero'); - }); - - it('uses the accent color icon for inbox-zero (vs ink-3 for others)', async () => { - render(ChronikEmptyState, { props: { variant: 'inbox-zero' as const } }); - - const wrapper = document.querySelector('[data-testid="chronik-empty-state"]'); - const svg = wrapper?.querySelector('svg'); - expect(svg?.getAttribute('class')).toContain('text-accent'); - }); - - it('uses the ink-3 color icon for first-run', async () => { - render(ChronikEmptyState, { props: { variant: 'first-run' as const } }); - - const wrapper = document.querySelector('[data-testid="chronik-empty-state"]'); - const svg = wrapper?.querySelector('svg'); - expect(svg?.getAttribute('class')).toContain('text-ink-3'); - }); -}); diff --git a/frontend/src/routes/aktivitaeten/+page.svelte b/frontend/src/routes/aktivitaeten/+page.svelte index 06a0ff6b..a7665a43 100644 --- a/frontend/src/routes/aktivitaeten/+page.svelte +++ b/frontend/src/routes/aktivitaeten/+page.svelte @@ -10,7 +10,7 @@ import { import ChronikFuerDichBox from '$lib/activity/ChronikFuerDichBox.svelte'; import ChronikFilterPills from '$lib/activity/ChronikFilterPills.svelte'; import ChronikTimeline from '$lib/activity/ChronikTimeline.svelte'; -import ChronikEmptyState from '$lib/activity/ChronikEmptyState.svelte'; +import EmptyState from '$lib/shared/primitives/EmptyState.svelte'; import ChronikErrorCard from '$lib/activity/ChronikErrorCard.svelte'; import type { components } from '$lib/generated/api'; import type { FilterValue } from './+page.server'; @@ -88,6 +88,22 @@ const emptyVariant = $derived<'first-run' | 'filter-empty' | 'inbox-zero'>( data.activityFeed.length === 0 ? 'first-run' : 'filter-empty' ); +const emptyHeading = $derived( + emptyVariant === 'first-run' + ? m.chronik_empty_first_run_title() + : emptyVariant === 'filter-empty' + ? m.chronik_empty_filter_title() + : m.chronik_inbox_zero_title() +); + +const emptySubline = $derived( + emptyVariant === 'first-run' + ? m.chronik_empty_first_run_body() + : emptyVariant === 'filter-empty' + ? m.chronik_empty_filter_body() + : '' +); + function retry() { location.reload(); } @@ -118,7 +134,7 @@ function retry() {

{#if isEmpty}
- +
{:else}