import { getDb } from '@/lib/db' import type { Memory, MediaItem, TimelineEntry, Recipe, TimelineContribution } from '@/lib/types' import HeroSection from '@/components/HeroSection' import PhotoSlideshow from '@/components/PhotoSlideshow' import PhotoGallery from '@/components/PhotoGallery' import MemorySection from '@/components/MemorySection' import VideoGallery from '@/components/VideoGallery' import TributeSection from '@/components/TributeSection' import CandleSection from '@/components/CandleSection' import TimelineSection from '@/components/TimelineSection' import TimelineUploadSection from '@/components/TimelineUploadSection' import MemoryUploadSection from '@/components/MemoryUploadSection' import PhotoUploadSection from '@/components/PhotoUploadSection' import RecipeSection from '@/components/RecipeSection' import RecipeUploadSection from '@/components/RecipeUploadSection' export const revalidate = 10 // Revalidate every 10 seconds export const dynamic = 'force-dynamic' // node:sqlite returns null-prototype objects; convert to plain objects for Client Components function plain(rows: unknown[]): T[] { return JSON.parse(JSON.stringify(rows)) } export default async function HomePage() { const db = getDb() const photos = plain( db.prepare("SELECT * FROM media WHERE type = 'photo' AND status = 'approved' ORDER BY sort_order, created_at DESC").all() ) const videos = plain( db.prepare("SELECT * FROM media WHERE type = 'video' AND status = 'approved' ORDER BY sort_order, created_at DESC").all() ) const memories = plain( db.prepare('SELECT * FROM memories ORDER BY created_at DESC').all() ) // Fetch approved user contributions (memories) let userMemories: any[] = [] try { userMemories = plain( db.prepare(` SELECT id, name, title, content, media_filenames, created_at FROM contributions WHERE status = 'approved' AND type = 'memory' ORDER BY created_at DESC `).all() ) } catch (err) { console.error('Error fetching user memories:', err) } // Combine admin memories + approved user contributions const combinedMemories = [ ...memories, ...userMemories.map((m: any) => ({ id: m.id, title: m.title || 'Erinnerung', content: m.content, author: m.name || null, media_filenames: m.media_filenames || null, created_at: m.created_at, updated_at: m.created_at, })) ] const timeline = plain( db.prepare('SELECT * FROM timeline ORDER BY sort_order, year').all() ) // Fetch approved timeline contributions let contributions: any[] = [] try { contributions = plain( db.prepare("SELECT * FROM contributions WHERE status = 'approved' AND type = 'timeline' ORDER BY year, month, day").all() ) } catch { // Fallback to old table try { contributions = plain( db.prepare("SELECT * FROM timeline_contributions WHERE status = 'approved' ORDER BY year, month, day").all() ) } catch {} } // Collect all timeline photo filenames for the main gallery const timelinePhotoFilenames = new Set() // Combine official timeline + community contributions const combinedTimeline = [ ...timeline.map(t => { // Add timeline photos to set if (t.media_filenames) { t.media_filenames.split(',').forEach(f => timelinePhotoFilenames.add(f.trim())) } return { ...t, source: 'official' as const } }), ...contributions.map((c: any) => { // Add contribution photos to set if (c.media_filenames) { c.media_filenames.split(',').forEach((f: string) => timelinePhotoFilenames.add(f.trim())) } return { id: c.id, year: c.year, month: c.month, day: c.day, title: c.title, description: c.content || c.story || null, location: c.location || null, media_filenames: c.media_filenames || null, sort_order: 0, created_at: c.created_at, source: 'community' as const, contributorName: c.name, } }) ].sort((a, b) => { const dateA = parseInt(a.year) * 10000 + parseInt(a.month || '0') * 100 + parseInt(a.day || '0') const dateB = parseInt(b.year) * 10000 + parseInt(b.month || '0') * 100 + parseInt(b.day || '0') return dateA - dateB }) // Create virtual MediaItem entries for timeline photos const timelinePhotos: MediaItem[] = Array.from(timelinePhotoFilenames).map((filename, i) => ({ id: 999000 + i, filename, original_name: null, type: 'photo' as const, caption: 'Aus dem Zeitstrahl', sort_order: 9999, status: 'approved' as const, created_at: new Date().toISOString(), })) // Fetch approved media contributions (user-uploaded photos) let mediaContribPhotos: MediaItem[] = [] try { const mediaContribs = plain( db.prepare("SELECT id, media_filenames, name, created_at FROM contributions WHERE status = 'approved' AND media_filenames IS NOT NULL AND media_filenames != ''").all() ) mediaContribPhotos = mediaContribs.flatMap((c: any) => c.media_filenames.split(',').filter(Boolean).map((filename: string, i: number) => ({ id: 998000 + c.id * 10 + i, filename: filename.trim(), original_name: null, type: 'photo' as const, caption: null, sort_order: 9998, status: 'approved' as const, created_at: c.created_at, })) ) } catch {} // Merge all photos const allPhotos = [...photos, ...timelinePhotos, ...mediaContribPhotos] const recipes = plain( db.prepare('SELECT * FROM recipes ORDER BY sort_order, title').all() ) return (
{/* Hero */} {/* Navigation */} {/* Personal tribute */} {/* Candles */} {/* Timeline */} {/* Timeline Upload */} {/* Photos */} {allPhotos.length > 0 && (

Erinnerungen in Bildern

{allPhotos.length > 1 && }
)} {/* Photo Upload */} {/* Memories */}
{/* Memory Upload */} {/* Videos */} {/* Recipe section */} {recipes.length > 0 && } {/* Recipe Upload */} {/* Footer placeholder */}
) }