feat(journey-reader): match spec LR-2 — card layout, interlude, badge, actions; inline note in editor row
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 3m3s
CI / OCR Service Tests (pull_request) Successful in 24s
CI / Backend Unit Tests (pull_request) Successful in 4m11s
CI / fail2ban Regex (pull_request) Successful in 45s
CI / Semgrep Security Scan (pull_request) Successful in 23s
CI / Compose Bucket Idempotency (pull_request) Successful in 1m5s

JourneyItemCard: restructure from full-<a> to div+card with meta line
(date · von X an Y) and explicit "Brief öffnen →" link; note renders as
mint-border annotation inside the card.

JourneyInterlude: remove ❦ ornament; orange-400 left-border spec classes.

JourneyReader: fix intro classes (dashed border-b); remove bottom author
actions (moved to +page.svelte metabar).

+page.svelte geschichten/[id]: badge above title with spec orange-50 classes;
Bearbeiten/Löschen in metabar right side for isJourney + canBlogWrite.

JourneyItemRow: items-center on main row; drag handle self-center; note
textarea inline in content column (removes border-t section below).

i18n: add journey_item_open, journey_item_meta_from_to to de/en/es.

Tests: update JourneyItemCard + JourneyReader specs to match new structure;
fix datePrecision 'FULL'→'DAY', add receiverCount: 0 to all test fixtures.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-06-10 19:59:32 +02:00
parent b0d75b26cd
commit 90a1bd4082
11 changed files with 203 additions and 182 deletions

View File

@@ -54,22 +54,39 @@ async function handleDelete() {
<article aria-labelledby="geschichte-title">
<header class="mb-6">
<div class="mb-3 flex flex-wrap items-center gap-2">
<h1 id="geschichte-title" class="font-serif text-4xl font-bold text-ink">
{g.title}
</h1>
{#if isJourney}
<span
class="inline-block rounded-full bg-journey-tint px-2 py-0.5 text-xs font-bold tracking-wider text-journey uppercase"
>
{m.journey_badge_detail()}
</span>
{#if isJourney}
<span
class="mb-2 inline-flex rounded-sm border border-orange-200 bg-orange-50 px-2 py-px text-[10px] font-bold tracking-widest text-orange-700 uppercase"
>
{m.journey_badge_detail()}
</span>
{/if}
<h1 id="geschichte-title" class="mb-4 font-serif text-3xl leading-tight font-bold text-ink">
{g.title}
</h1>
<div class="border-subtle mb-4 flex items-center gap-3 border-b pb-4">
<p class="font-sans text-sm text-ink-3">
{authorName}
{#if publishedAt}· {m.geschichten_published_on({ date: publishedAt })}{/if}
</p>
{#if isJourney && data.canBlogWrite}
<div class="ml-auto flex items-center gap-3">
<a
href="/geschichten/{g.id}/edit"
class="inline-flex h-9 items-center rounded border border-line bg-surface px-3 font-sans text-sm font-medium text-ink hover:bg-muted focus:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring"
>
{m.btn_edit()}
</a>
<button
type="button"
onclick={handleDelete}
class="inline-flex h-9 items-center rounded font-sans text-sm font-medium text-danger hover:underline focus:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring"
>
{m.btn_delete()}
</button>
</div>
{/if}
</div>
<p class="font-sans text-sm text-ink-3">
{authorName}
{#if publishedAt}· {m.geschichten_published_on({ date: publishedAt })}{/if}
</p>
</header>
{#if deleteError}
@@ -82,7 +99,7 @@ async function handleDelete() {
{/if}
{#if isJourney}
<JourneyReader geschichte={g} canBlogWrite={data.canBlogWrite} ondelete={handleDelete} />
<JourneyReader geschichte={g} />
{:else}
<StoryReader geschichte={g} canBlogWrite={data.canBlogWrite} ondelete={handleDelete} />
{/if}

View File

@@ -166,7 +166,7 @@ describe('geschichten/[id] page', () => {
{
id: 'item1',
position: 0,
document: { id: 'd1', title: 'Brief 1923', datePrecision: 'FULL' },
document: { id: 'd1', title: 'Brief 1923', datePrecision: 'DAY', receiverCount: 0 },
note: 'Brief aus 1923'
}
]