249 lines
11 KiB
TypeScript
249 lines
11 KiB
TypeScript
import { getTranslations, setRequestLocale } from 'next-intl/server'
|
||
import { mockDb } from '@/lib/mockDb'
|
||
import Navbar from '@/components/Navbar'
|
||
import Footer from '@/components/Footer'
|
||
import ListingCard from '@/components/ListingCard'
|
||
import { Link } from '@/i18n/routing'
|
||
import { Search, MapPin, CheckCircle, ArrowRight } from 'lucide-react'
|
||
|
||
export default async function HomePage({ params }: { params: Promise<{ locale: string }> }) {
|
||
const { locale } = await params
|
||
setRequestLocale(locale)
|
||
|
||
const t = await getTranslations('hero')
|
||
const homeT = await getTranslations('home')
|
||
const navT = await getTranslations('nav')
|
||
|
||
// Get active listings and filter for featured (Local Approved)
|
||
const allListings = await mockDb.getListings()
|
||
const featuredListings = allListings.filter(l => l.isLocalApproved).slice(0, 3)
|
||
|
||
const categories = await mockDb.getCategories()
|
||
const neighborhoods = await mockDb.getNeighborhoods()
|
||
|
||
// Get localized names
|
||
const getLocalizedName = (obj: any) => {
|
||
if (!obj) return ''
|
||
return locale === 'ru' ? obj.nameRu : locale === 'en' ? obj.nameEn : obj.nameTr
|
||
}
|
||
|
||
// Map category slug to lucide icons or nice visual cues
|
||
const categoryImages: Record<string, string> = {
|
||
restoran: 'https://images.unsplash.com/photo-1555396273-367ea4eb4db5?w=800&auto=format&fit=crop&q=80',
|
||
apart: 'https://images.unsplash.com/photo-1566073771259-6a8506099945?w=800&auto=format&fit=crop&q=80',
|
||
isletme: 'https://images.unsplash.com/photo-1544551763-46a013bb70d5?w=800&auto=format&fit=crop&q=80'
|
||
}
|
||
|
||
const categoryPaths: Record<string, string> = {
|
||
restoran: '/restoranlar',
|
||
apart: '/apartlar',
|
||
isletme: '/isletmeler'
|
||
}
|
||
|
||
return (
|
||
<div className="flex-1 flex flex-col min-h-screen bg-stone text-ink">
|
||
<Navbar />
|
||
|
||
{/* Hero Section */}
|
||
<section className="bg-pine text-stone pt-20 pb-24 relative overflow-hidden">
|
||
{/* Decorative background shapes */}
|
||
<div className="absolute inset-0 opacity-5 pointer-events-none">
|
||
<div className="absolute -top-40 -right-40 w-96 h-96 rounded-full bg-turquoise blur-3xl" />
|
||
<div className="absolute -bottom-45 -left-40 w-96 h-96 rounded-full bg-bougainvillea blur-3xl" />
|
||
</div>
|
||
|
||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10 space-y-8">
|
||
|
||
{/* Logo stamp effect */}
|
||
<div className="flex justify-center">
|
||
<div className="w-16 h-16 rounded-full border-2 border-stone/30 flex items-center justify-center relative bg-white/5 backdrop-blur-sm -rotate-6">
|
||
<div className="absolute inset-[3.5px] rounded-full border border-dashed border-turquoise/50" />
|
||
<span className="font-heading font-extrabold text-stone text-lg tracking-tighter">ML</span>
|
||
</div>
|
||
</div>
|
||
|
||
<h2 className="font-heading font-extrabold text-3xl sm:text-5xl lg:text-6xl text-stone leading-tight tracking-tight max-w-3xl mx-auto lowercase">
|
||
{locale === 'tr' && (
|
||
<>En iyi yerel adresler,<br /><span className="text-turquoise">turistin göremediği yerde.</span></>
|
||
)}
|
||
{locale === 'en' && (
|
||
<>The best local spots,<br /><span className="text-turquoise">hidden from plain sight.</span></>
|
||
)}
|
||
{locale === 'ru' && (
|
||
<>Лучшие места,<br /><span className="text-turquoise">которые знают местные.</span></>
|
||
)}
|
||
</h2>
|
||
|
||
<p className="text-sm sm:text-base text-stone/70 max-w-xl mx-auto font-medium">
|
||
{t('subtitle')}
|
||
</p>
|
||
|
||
{/* Search Form */}
|
||
<form
|
||
action={`/${locale}/restoranlar`}
|
||
method="GET"
|
||
className="max-w-xl mx-auto bg-paper p-2 rounded-2xl flex items-center shadow-lg border border-white/10"
|
||
>
|
||
<div className="flex items-center flex-1 px-3">
|
||
<Search className="w-5 h-5 text-shutter shrink-0" />
|
||
<input
|
||
type="text"
|
||
name="search"
|
||
placeholder={t('searchPlaceholder')}
|
||
className="w-full bg-transparent border-0 focus:ring-0 text-sm py-2 px-3 text-ink placeholder:text-ink/40 outline-none"
|
||
/>
|
||
</div>
|
||
<button
|
||
type="submit"
|
||
className="bg-turquoise hover:bg-turquoise/90 text-paper font-medium text-xs px-5 py-3 rounded-xl transition"
|
||
>
|
||
{t('cta')}
|
||
</button>
|
||
</form>
|
||
|
||
{/* Local Approved Banner */}
|
||
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-white/5 border border-white/10 text-xs">
|
||
<span className="inline-block w-2.5 h-2.5 rounded-full bg-turquoise animate-pulse" />
|
||
<span className="font-semibold text-turquoise">{t('approvedBadge')}</span>
|
||
<span className="text-stone/60">mührü ile güvenli rehber</span>
|
||
</div>
|
||
|
||
</div>
|
||
</section>
|
||
|
||
{/* Category Grid Section */}
|
||
<section className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20">
|
||
<div className="text-center mb-12">
|
||
<h3 className="text-2xl sm:text-3xl font-heading font-extrabold text-pine lowercase">
|
||
{homeT('categories')}
|
||
</h3>
|
||
<p className="text-sm text-ink/65 mt-2 font-medium">
|
||
{homeT('categoriesSubtitle')}
|
||
</p>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||
{categories.map((cat) => {
|
||
const imageUrl = categoryImages[cat.slug] || categoryImages.isletme
|
||
const path = categoryPaths[cat.slug] || '/isletmeler'
|
||
const catName = getLocalizedName(cat)
|
||
|
||
return (
|
||
<Link
|
||
key={cat.id}
|
||
href={path}
|
||
className="group relative h-64 rounded-2xl overflow-hidden shadow-sm hover:shadow-md transition duration-300 border border-pine/5 flex items-end p-6"
|
||
>
|
||
<div className="absolute inset-0">
|
||
<img
|
||
src={imageUrl}
|
||
alt={catName}
|
||
className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-105"
|
||
/>
|
||
<div className="absolute inset-0 bg-gradient-to-t from-pine/90 via-pine/30 to-transparent" />
|
||
</div>
|
||
<div className="relative z-10 space-y-1">
|
||
<h4 className="font-heading font-extrabold text-xl text-stone group-hover:text-turquoise transition-colors lowercase">
|
||
{catName}
|
||
</h4>
|
||
<div className="flex items-center gap-1 text-[11px] font-mono text-turquoise">
|
||
<span>{homeT('explore')}</span>
|
||
<ArrowRight className="w-3.5 h-3.5 group-hover:translate-x-1 transition-transform" />
|
||
</div>
|
||
</div>
|
||
</Link>
|
||
)
|
||
})}
|
||
</div>
|
||
</section>
|
||
|
||
{/* Local Approved Featured Section */}
|
||
<section className="bg-stone-deep py-20 border-t border-b border-pine/5">
|
||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||
|
||
<div className="flex flex-col sm:flex-row sm:items-end justify-between mb-12 gap-4">
|
||
<div>
|
||
<div className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full border border-turquoise/20 bg-turquoise/5 text-[10px] font-mono text-turquoise font-semibold uppercase tracking-wider mb-3">
|
||
{t('approvedBadge')}
|
||
</div>
|
||
<h3 className="text-2xl sm:text-3xl font-heading font-extrabold text-pine lowercase">
|
||
{homeT('featured')}
|
||
</h3>
|
||
<p className="text-sm text-ink/65 mt-2 font-medium">
|
||
{homeT('featuredSubtitle')}
|
||
</p>
|
||
</div>
|
||
|
||
<Link
|
||
href="/restoranlar?approved=true"
|
||
className="flex items-center gap-1 text-xs font-bold text-pine hover:text-turquoise transition-colors border-b border-pine/20 hover:border-turquoise pb-1 w-fit"
|
||
>
|
||
<span>{locale === 'tr' ? 'tüm onaylı mekanlar' : locale === 'en' ? 'all approved places' : 'все проверенные места'}</span>
|
||
<ArrowRight className="w-3.5 h-3.5" />
|
||
</Link>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8">
|
||
{featuredListings.map((listing) => (
|
||
<ListingCard key={listing.id} listing={listing} />
|
||
))}
|
||
</div>
|
||
|
||
</div>
|
||
</section>
|
||
|
||
{/* Neighborhoods Section */}
|
||
<section className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20">
|
||
<div className="text-center mb-12">
|
||
<h3 className="text-2xl sm:text-3xl font-heading font-extrabold text-pine lowercase">
|
||
{homeT('neighborhoods')}
|
||
</h3>
|
||
<p className="text-sm text-ink/65 mt-2 font-medium">
|
||
{homeT('neighborhoodsSubtitle')}
|
||
</p>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-2 md:grid-cols-5 gap-4">
|
||
{neighborhoods.map((neigh) => {
|
||
const name = getLocalizedName(neigh)
|
||
return (
|
||
<Link
|
||
key={neigh.id}
|
||
href={`/mahalle/${neigh.slug}`}
|
||
className="bg-paper p-5 rounded-xl border border-pine/8 text-center hover:border-turquoise/40 hover:bg-paper/90 transition shadow-sm group flex flex-col items-center gap-2"
|
||
>
|
||
<MapPin className="w-5 h-5 text-shutter group-hover:text-turquoise transition-colors" />
|
||
<span className="font-heading font-bold text-xs text-pine lowercase group-hover:text-turquoise transition-colors">
|
||
{name}
|
||
</span>
|
||
</Link>
|
||
)
|
||
})}
|
||
</div>
|
||
</section>
|
||
|
||
{/* Trust Badge Explainer */}
|
||
<section className="bg-pine text-stone py-16 border-t border-white/5">
|
||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center space-y-6">
|
||
<div className="flex justify-center">
|
||
<div className="w-14 h-14 rounded-full border-2 border-turquoise flex items-center justify-center relative bg-paper -rotate-6">
|
||
<div className="absolute inset-[2px] rounded-full border border-dashed border-turquoise/60" />
|
||
<span className="font-mono text-[8px] text-center font-bold text-turquoise tracking-tight leading-none uppercase">
|
||
YEREL<br />ONAYLI
|
||
</span>
|
||
</div>
|
||
</div>
|
||
<h3 className="text-xl sm:text-2xl font-heading font-extrabold lowercase">
|
||
yerel onay mührü nedir?
|
||
</h3>
|
||
<p className="text-xs sm:text-sm text-stone/70 max-w-xl mx-auto font-medium leading-relaxed">
|
||
{t('approvedExplain')}
|
||
</p>
|
||
</div>
|
||
</section>
|
||
|
||
<Footer />
|
||
</div>
|
||
)
|
||
}
|