spa(phase 3, tasks 15-22): routing, komponenten, home, postview
Phase 3 komplett:
- Task 15: LoadingOrError-Komponente (loading/error-states, Habla-Fallback)
- Task 16: app.html mit CSS-Variablen (light/dark), Base-Typography
- Task 17: +layout.svelte mit Container + bootstrapReadRelays onMount
- Task 18: ProfileCard-Komponente (Avatar, Name, About, NIP-05, Website)
- Task 19: PostCard-Komponente (Thumbnail + Titel/Summary/Datum), responsive
- Task 20: +page.svelte als Home (Profil + Liste, Promise.all für beides)
- Task 21: PostView-Komponente (Titel, Meta, Cover, Summary, Markdown-Body)
- Task 22: [...slug]/+page.ts+svelte — Catch-all-Route mit Legacy-301-Redirect
Alle $props()-abhängigen Werte via $derived() (Svelte-5-Runes-Konformität).
npm run check: 0 errors, 0 warnings, 592 files. npm run build grün.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 17:39:24 +02:00
|
|
|
<script lang="ts">
|
|
|
|
|
import type { NostrEvent } from '$lib/nostr/loaders';
|
|
|
|
|
import { loadPost } from '$lib/nostr/loaders';
|
|
|
|
|
import { AUTHOR_PUBKEY_HEX } from '$lib/nostr/config';
|
|
|
|
|
import { buildHablaLink } from '$lib/nostr/naddr';
|
|
|
|
|
import PostView from '$lib/components/PostView.svelte';
|
|
|
|
|
import LoadingOrError from '$lib/components/LoadingOrError.svelte';
|
|
|
|
|
|
|
|
|
|
let { data } = $props();
|
|
|
|
|
const dtag = $derived(data.dtag);
|
|
|
|
|
|
|
|
|
|
let post: NostrEvent | null = $state(null);
|
|
|
|
|
let loading = $state(true);
|
|
|
|
|
let error: string | null = $state(null);
|
|
|
|
|
|
|
|
|
|
const hablaLink = $derived(
|
|
|
|
|
buildHablaLink({
|
|
|
|
|
pubkey: AUTHOR_PUBKEY_HEX,
|
|
|
|
|
kind: 30023,
|
|
|
|
|
identifier: dtag
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
2026-04-21 13:17:41 +02:00
|
|
|
$effect(() => {
|
|
|
|
|
const currentDtag = dtag;
|
|
|
|
|
post = null;
|
|
|
|
|
loading = true;
|
|
|
|
|
error = null;
|
|
|
|
|
loadPost(currentDtag)
|
|
|
|
|
.then((p) => {
|
|
|
|
|
if (currentDtag !== dtag) return;
|
|
|
|
|
if (!p) {
|
|
|
|
|
error = `Post "${currentDtag}" nicht gefunden.`;
|
|
|
|
|
} else {
|
|
|
|
|
post = p;
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch((e) => {
|
|
|
|
|
if (currentDtag !== dtag) return;
|
|
|
|
|
error = e instanceof Error ? e.message : 'Unbekannter Fehler';
|
|
|
|
|
})
|
|
|
|
|
.finally(() => {
|
|
|
|
|
if (currentDtag === dtag) loading = false;
|
|
|
|
|
});
|
spa(phase 3, tasks 15-22): routing, komponenten, home, postview
Phase 3 komplett:
- Task 15: LoadingOrError-Komponente (loading/error-states, Habla-Fallback)
- Task 16: app.html mit CSS-Variablen (light/dark), Base-Typography
- Task 17: +layout.svelte mit Container + bootstrapReadRelays onMount
- Task 18: ProfileCard-Komponente (Avatar, Name, About, NIP-05, Website)
- Task 19: PostCard-Komponente (Thumbnail + Titel/Summary/Datum), responsive
- Task 20: +page.svelte als Home (Profil + Liste, Promise.all für beides)
- Task 21: PostView-Komponente (Titel, Meta, Cover, Summary, Markdown-Body)
- Task 22: [...slug]/+page.ts+svelte — Catch-all-Route mit Legacy-301-Redirect
Alle $props()-abhängigen Werte via $derived() (Svelte-5-Runes-Konformität).
npm run check: 0 errors, 0 warnings, 592 files. npm run build grün.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 17:39:24 +02:00
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<nav class="breadcrumb"><a href="/">← Zurück zur Übersicht</a></nav>
|
|
|
|
|
|
|
|
|
|
<LoadingOrError {loading} {error} {hablaLink} />
|
|
|
|
|
|
|
|
|
|
{#if post}
|
|
|
|
|
<PostView event={post} />
|
|
|
|
|
{/if}
|
|
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
.breadcrumb {
|
|
|
|
|
font-size: 0.9rem;
|
|
|
|
|
margin-bottom: 1rem;
|
|
|
|
|
}
|
|
|
|
|
.breadcrumb a {
|
|
|
|
|
color: var(--accent);
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
}
|
|
|
|
|
.breadcrumb a:hover {
|
|
|
|
|
text-decoration: underline;
|
|
|
|
|
}
|
|
|
|
|
</style>
|