fix(timeline): render undated events as pills/bands, not letter cards
The undated bucket is assembled from all entries, so it can contain events as well as letters. Rendering every undated entry with LetterCard produced a dead /documents/undefined link and "Unknown -> Unknown" for events. Dispatch on kind/type like YearBand does (WorldBand/EventPill/ LetterCard). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,9 @@ import * as m from '$lib/paraglide/messages.js';
|
||||
import YearBand from './YearBand.svelte';
|
||||
import GapSpan from './GapSpan.svelte';
|
||||
import LetterCard from './LetterCard.svelte';
|
||||
import EventPill from './EventPill.svelte';
|
||||
import WorldBand from './WorldBand.svelte';
|
||||
import { entryKey } from './entryKey';
|
||||
import type { components } from '$lib/generated/api';
|
||||
|
||||
type TimelineDTO = components['schemas']['TimelineDTO'];
|
||||
@@ -59,8 +62,22 @@ const isEmpty = $derived(timeline.years.length === 0 && timeline.undated.length
|
||||
<section data-testid="undated-section" class="mx-auto mt-8 max-w-3xl">
|
||||
<h2 class="mb-3 font-serif text-sm font-bold text-ink-2">{m.timeline_undated_section()}</h2>
|
||||
<ul class="space-y-2">
|
||||
{#each timeline.undated as entry (entry.documentId ?? entry.title)}
|
||||
<li><LetterCard entry={entry} /></li>
|
||||
<!-- The undated bucket is filtered from ALL entries, so it can hold
|
||||
events as well as letters. Dispatch on kind/type exactly like
|
||||
YearBand — an event rendered as a LetterCard would link to
|
||||
/documents/undefined and read "Unknown → Unknown" (REQ-007/008/009). -->
|
||||
{#each timeline.undated as entry (entryKey(entry))}
|
||||
<li>
|
||||
{#if entry.kind === 'EVENT'}
|
||||
{#if entry.type === 'HISTORICAL'}
|
||||
<WorldBand entry={entry} />
|
||||
{:else}
|
||||
<EventPill entry={entry} />
|
||||
{/if}
|
||||
{:else}
|
||||
<LetterCard entry={entry} />
|
||||
{/if}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
@@ -89,6 +89,70 @@ describe('TimelineView', () => {
|
||||
expect(document.querySelector('[data-testid="undated-section"]')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('renders an undated curated EVENT as a pill, not a broken letter card (REQ-008/016)', () => {
|
||||
render(TimelineView, {
|
||||
timeline: makeTimelineDTO({
|
||||
undated: [
|
||||
makeEntry({
|
||||
kind: 'EVENT',
|
||||
type: 'PERSONAL',
|
||||
derived: false,
|
||||
eventId: 'e1',
|
||||
precision: 'UNKNOWN',
|
||||
eventDate: undefined,
|
||||
title: 'Auswanderung',
|
||||
senderName: '',
|
||||
receiverName: '',
|
||||
documentId: undefined
|
||||
})
|
||||
]
|
||||
})
|
||||
});
|
||||
// The event renders inside the undated section…
|
||||
expect(document.querySelector('[data-testid="undated-section"]')).not.toBeNull();
|
||||
expect(document.body.textContent).toContain('Auswanderung');
|
||||
// …as an EventPill (its edit affordance), never as a letter card linking
|
||||
// to /documents/undefined with "Unbekannt → Unbekannt".
|
||||
expect(document.querySelector('[data-testid="event-edit"]')).not.toBeNull();
|
||||
expect(document.querySelector('a[href="/documents/undefined"]')).toBeNull();
|
||||
expect(document.body.textContent).not.toContain('Unbekannt');
|
||||
});
|
||||
|
||||
it('renders an undated HISTORICAL EVENT as a world band, not a letter card (REQ-009/016)', () => {
|
||||
render(TimelineView, {
|
||||
timeline: makeTimelineDTO({
|
||||
undated: [
|
||||
makeEntry({
|
||||
kind: 'EVENT',
|
||||
type: 'HISTORICAL',
|
||||
derived: false,
|
||||
precision: 'UNKNOWN',
|
||||
eventDate: undefined,
|
||||
title: 'Weltwirtschaftskrise',
|
||||
senderName: '',
|
||||
receiverName: '',
|
||||
documentId: undefined
|
||||
})
|
||||
]
|
||||
})
|
||||
});
|
||||
expect(document.querySelector('[data-testid="undated-section"]')).not.toBeNull();
|
||||
expect(document.body.textContent).toContain('Weltwirtschaftskrise');
|
||||
// HISTORICAL → WorldBand carries the sr-only "Weltgeschehen" cue (REQ-018),
|
||||
// not a broken document link.
|
||||
expect(document.body.textContent).toContain('Weltgeschehen');
|
||||
expect(document.querySelector('a[href="/documents/undefined"]')).toBeNull();
|
||||
});
|
||||
|
||||
it('still renders an undated LETTER as a letter card (REQ-016)', () => {
|
||||
render(TimelineView, {
|
||||
timeline: makeTimelineDTO({
|
||||
undated: [makeEntry({ precision: 'UNKNOWN', eventDate: undefined, documentId: 'u1' })]
|
||||
})
|
||||
});
|
||||
expect(document.querySelector('a[href="/documents/u1"]')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('renders two derived events in one band without key collision (no-double-null-key)', () => {
|
||||
const a = makeEntry({
|
||||
kind: 'EVENT',
|
||||
|
||||
Reference in New Issue
Block a user