6363d1327b
- MusicPlayer ins Layout verschoben (läuft auf allen Seiten) - Mobile-Autoplay: Desktop startet stumm + fade-in bei Scroll, Mobile wartet auf ersten Touch und startet dann mit Fade-In - Dennis-Perspektive auf eigene Seite /meine-oma ausgelagert, dezenter Link "Von Dennis" am Ende der Tribute-Sektion - "Berge von Essen" entfernt - "Jacky und Niklas" → "ihre Enkelin" / "Meine Schwester" Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
126 lines
4.6 KiB
TypeScript
126 lines
4.6 KiB
TypeScript
import { getDb } from '@/lib/db'
|
|
import type { Memory, MediaItem } from '@/lib/types'
|
|
import HeroSection from '@/components/HeroSection'
|
|
import PhotoSlideshow from '@/components/PhotoSlideshow'
|
|
import PhotoGallery from '@/components/PhotoGallery'
|
|
import MemorySection from '@/components/MemorySection'
|
|
import WriteSection from '@/components/WriteSection'
|
|
import VideoGallery from '@/components/VideoGallery'
|
|
import TributeSection from '@/components/TributeSection'
|
|
|
|
export const dynamic = 'force-dynamic'
|
|
|
|
// node:sqlite returns null-prototype objects; convert to plain objects for Client Components
|
|
function plain<T>(rows: unknown[]): T[] {
|
|
return JSON.parse(JSON.stringify(rows))
|
|
}
|
|
|
|
export default async function HomePage() {
|
|
const db = getDb()
|
|
|
|
const photos = plain<MediaItem>(
|
|
db.prepare("SELECT * FROM media WHERE type = 'photo' ORDER BY sort_order, created_at").all()
|
|
)
|
|
const videos = plain<MediaItem>(
|
|
db.prepare("SELECT * FROM media WHERE type = 'video' ORDER BY sort_order, created_at").all()
|
|
)
|
|
const memories = plain<Memory>(
|
|
db.prepare('SELECT * FROM memories ORDER BY created_at DESC').all()
|
|
)
|
|
|
|
return (
|
|
<main className="min-h-screen bg-cream">
|
|
{/* Hero */}
|
|
<HeroSection heroPhoto={photos[0]?.filename ?? null} />
|
|
|
|
{/* Navigation */}
|
|
<nav className="sticky top-0 z-20 bg-cream/80 backdrop-blur-sm border-b border-warm-border">
|
|
<div className="max-w-4xl mx-auto px-4 py-3 flex items-center justify-center gap-6 sm:gap-10">
|
|
<a href="#ueber-oma" className="text-warm-brown-light hover:text-warm-gold text-sm font-cormorant italic transition-colors">
|
|
Über Oma
|
|
</a>
|
|
{photos.length > 0 && (
|
|
<a href="#bilder" className="text-warm-brown-light hover:text-warm-gold text-sm font-cormorant italic transition-colors">
|
|
Bilder
|
|
</a>
|
|
)}
|
|
<a href="#erinnerungen" className="text-warm-brown-light hover:text-warm-gold text-sm font-cormorant italic transition-colors">
|
|
Erinnerungen
|
|
</a>
|
|
{videos.length > 0 && (
|
|
<a href="#videos" className="text-warm-brown-light hover:text-warm-gold text-sm font-cormorant italic transition-colors">
|
|
Videos
|
|
</a>
|
|
)}
|
|
</div>
|
|
</nav>
|
|
|
|
{/* Personal tribute */}
|
|
<TributeSection />
|
|
|
|
{/* Photos */}
|
|
{photos.length > 0 && (
|
|
<section id="bilder" className="py-16 sm:py-20">
|
|
<div className="max-w-6xl mx-auto px-4">
|
|
<div className="text-center mb-12">
|
|
<h2 className="font-cormorant italic text-4xl sm:text-5xl text-warm-brown mb-3">
|
|
Erinnerungen in Bildern
|
|
</h2>
|
|
<div className="flex items-center justify-center gap-4">
|
|
<div className="h-px w-16 bg-warm-gold/40" />
|
|
<span className="text-warm-gold text-xl">✦</span>
|
|
<div className="h-px w-16 bg-warm-gold/40" />
|
|
</div>
|
|
</div>
|
|
{photos.length > 1 && <PhotoSlideshow photos={photos} />}
|
|
<PhotoGallery photos={photos} />
|
|
</div>
|
|
</section>
|
|
)}
|
|
|
|
{/* Write */}
|
|
<WriteSection />
|
|
|
|
{/* Memories */}
|
|
<section id="erinnerungen">
|
|
<MemorySection memories={memories} />
|
|
</section>
|
|
|
|
{/* Videos */}
|
|
<VideoGallery videos={videos} />
|
|
|
|
{/* Footer */}
|
|
<footer className="py-12 text-center border-t border-warm-border bg-amber-50/30">
|
|
<div className="max-w-lg mx-auto px-4">
|
|
<p className="font-cormorant italic text-warm-brown-light/60 text-lg">
|
|
„Du bist nicht fort, nur ein Schritt voraus."
|
|
</p>
|
|
|
|
<div className="flex items-center justify-center gap-3 mt-5">
|
|
<div className="h-px w-8 bg-warm-gold/20" />
|
|
<span className="text-warm-gold/30 text-xs">✦</span>
|
|
<div className="h-px w-8 bg-warm-gold/20" />
|
|
</div>
|
|
|
|
<div className="mt-6 flex items-center justify-center gap-5">
|
|
<a
|
|
href="/impressum"
|
|
className="text-warm-brown-light/35 hover:text-warm-brown-light/65 text-xs font-lora tracking-wider transition-colors duration-200"
|
|
>
|
|
Impressum
|
|
</a>
|
|
<span className="text-warm-border/40 text-xs">·</span>
|
|
<a
|
|
href="/admin"
|
|
className="text-warm-border/25 hover:text-warm-border/50 text-xs transition-colors"
|
|
title="Verwaltung"
|
|
>
|
|
·
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
</main>
|
|
)
|
|
}
|