'use client'; import { useEffect, useMemo, useState } from 'react'; import Link from 'next/link'; import { useI18n } from './components/I18nProvider'; type LatestListing = { id: string; title: string; slug: string; teaser: string | null; coverImage: string | null; city: string; region: string; isSample: boolean; priceWeekdayEuros: number | null; priceWeekendEuros: number | null; }; export const dynamic = 'force-dynamic'; export default function HomePage() { const { t } = useI18n(); const [latest, setLatest] = useState([]); const [activeIndex, setActiveIndex] = useState(0); const [loadingLatest, setLoadingLatest] = useState(false); const [paused, setPaused] = useState(false); useEffect(() => { setLoadingLatest(true); fetch('/api/listings?limit=8', { cache: 'no-store' }) .then((res) => res.json()) .then((data) => setLatest((data.listings ?? []).slice(0, 5))) .catch(() => setLatest([])) .finally(() => setLoadingLatest(false)); }, []); useEffect(() => { if (!latest.length || paused) return; const id = setInterval(() => { setActiveIndex((prev) => (prev + 1) % latest.length); }, 4200); return () => clearInterval(id); }, [latest, paused]); useEffect(() => { if (activeIndex >= latest.length) { setActiveIndex(0); } }, [activeIndex, latest.length]); const activeListing = useMemo(() => { if (!latest.length) return null; return latest[Math.min(activeIndex, latest.length - 1)]; }, [latest, activeIndex]); return (
{t('heroEyebrow')}

{t('heroTitle')}

{t('heroBody')}

{t('latestListingsTitle')}

{t('latestListingsLead')}

{t('ctaBrowse')}
{loadingLatest ? (

{t('loading')}

) : !activeListing ? (

{t('mapNoResults')}

) : (
setPaused(true)} onMouseLeave={() => setPaused(false)}>
{latest.map((item) => (
{item.coverImage ? ( {item.title} ) : (
)}
{item.city}, {item.region} {item.isSample ? {t('sampleBadge')} : null}

{item.title}

{item.teaser}

{item.priceWeekdayEuros || item.priceWeekendEuros ? (
{t('priceStartingFromShort', { price: Math.min( ...([item.priceWeekdayEuros, item.priceWeekendEuros].filter((p): p is number => typeof p === 'number')), ), })}
) : null}
{t('openListing')}
))}
{latest.map((_, idx) => ( setActiveIndex(idx)} /> ))}
)}
); }