- Add dynamic sitemap.ts, robots.ts, and llms.txt route - Add metadataBase and JSON-LD Organization schema to layout - Set canonical alternates for all routes - Migrate raw img tags to next/image for LCP optimization - Add SEO dictionary strings to tr.json and en.json
130 lines
4.7 KiB
TypeScript
130 lines
4.7 KiB
TypeScript
import { SectionHeader } from "@/app/components/ui/section-header";
|
||
import { Badge } from "@/app/components/ui/badge";
|
||
import { getDictionary, Locale } from "../../dictionaries";
|
||
|
||
export async function generateMetadata({ params }: { params: Promise<{ lang: string }> }) {
|
||
const { lang } = await params;
|
||
const dict = await getDictionary(lang as Locale);
|
||
return {
|
||
title: dict.seo.menu.title,
|
||
description: dict.seo.menu.description,
|
||
alternates: {
|
||
canonical: `/${lang}/menu`,
|
||
},
|
||
};
|
||
}
|
||
|
||
export default async function MenuPage({
|
||
params,
|
||
}: {
|
||
params: Promise<{ lang: string }>;
|
||
}) {
|
||
const { lang } = await params;
|
||
const locale = lang as Locale;
|
||
const dict = await getDictionary(locale);
|
||
const t = dict.menu;
|
||
|
||
const MENU_SECTIONS = [
|
||
{
|
||
title: t.starters,
|
||
badge: "Starters",
|
||
variant: "gold" as const,
|
||
items: [
|
||
{ name: "Zeytinyağlı Enginar", desc: "Taze dereotu ve limon", price: "₺ 185" },
|
||
{ name: "Ahtapot Izgara", desc: "Kapari salatası, fesleğen yağı", price: "₺ 340" },
|
||
{ name: "Kabak Çiçeği Dolması", desc: "Lor peyniri, nane", price: "₺ 210" },
|
||
{ name: "Ezme Tabağı", desc: "Ev yapımı ekmek ile", price: "₺ 145" },
|
||
],
|
||
},
|
||
{
|
||
title: t.mains,
|
||
badge: "Mains",
|
||
variant: "blue" as const,
|
||
items: [
|
||
{ name: "Levrek Izgara", desc: "Mevsim yeşillikleri, limon yağı", price: "₺ 680" },
|
||
{ name: "Çipura Fırın", desc: "Ege otları, domates, zeytinyağı", price: "₺ 620" },
|
||
{ name: "Kuzu Pirzola", desc: "Kekik soslu, ızgara sebze", price: "₺ 750" },
|
||
{ name: "Mantar Risotto", desc: "Porcini, parmesan, taze kekik", price: "₺ 390" },
|
||
],
|
||
},
|
||
{
|
||
title: t.desserts,
|
||
badge: "Desserts",
|
||
variant: "green" as const,
|
||
items: [
|
||
{ name: "Incir Tatlısı", desc: "Kaymak, ceviz, pekmez", price: "₺ 175" },
|
||
{ name: "Dondurma Tabağı", desc: "Yerel bademli, mevsim meyve", price: "₺ 145" },
|
||
{ name: "Kemalpaşa", desc: "Sıcak servis, dövme ceviz", price: "₺ 120" },
|
||
],
|
||
},
|
||
{
|
||
title: t.drinks,
|
||
badge: "Drinks",
|
||
variant: "dark" as const,
|
||
items: [
|
||
{ name: "Datça Badem Şerbeti", desc: "Ev yapımı, taze", price: "₺ 95" },
|
||
{ name: "Limonata", desc: "Taze sıkım, nane", price: "₺ 85" },
|
||
{ name: "Lokal Şarap", desc: "Günlük seçki", price: "₺ 195 / bardak" },
|
||
{ name: "Soda & Maden Suyu", desc: "", price: "₺ 45" },
|
||
],
|
||
},
|
||
];
|
||
|
||
return (
|
||
<div className="min-h-screen bg-[var(--color-moy-light)]">
|
||
{/* Hero */}
|
||
<div className="bg-[var(--color-moy-dark)] pt-40 pb-20">
|
||
<div className="max-w-3xl mx-auto px-6 text-center">
|
||
<p className="text-[10px] uppercase tracking-[0.28em] text-[var(--color-moy-gold)] mb-4">{t.eyebrow}</p>
|
||
<h1 className="text-5xl md:text-6xl font-serif text-white mb-6">{t.title}</h1>
|
||
<p className="text-gray-400 text-base max-w-lg mx-auto leading-relaxed">
|
||
{t.subtitle}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="max-w-4xl mx-auto px-4 sm:px-6 py-24 space-y-16">
|
||
<SectionHeader
|
||
eyebrow="Moy Restaurant"
|
||
title={t.sectionTitle}
|
||
subtitle={t.sectionSubtitle}
|
||
/>
|
||
|
||
{MENU_SECTIONS.map((section) => (
|
||
<div key={section.title}>
|
||
<div className="flex items-center gap-4 mb-8">
|
||
<h2 className="text-2xl font-serif text-[var(--color-moy-dark)]">{section.title}</h2>
|
||
<Badge variant={section.variant}>{section.badge}</Badge>
|
||
</div>
|
||
|
||
<div className="divide-y divide-gray-200/60">
|
||
{section.items.map((item) => (
|
||
<div
|
||
key={item.name}
|
||
className="flex items-baseline justify-between py-5 group hover:px-3 transition-all duration-200"
|
||
>
|
||
<div>
|
||
<h3 className="font-serif text-lg text-[var(--color-moy-dark)] group-hover:text-[var(--color-moy-gold-dark)] transition-colors">
|
||
{item.name}
|
||
</h3>
|
||
{item.desc && (
|
||
<p className="text-xs text-gray-400 mt-1 tracking-wide">{item.desc}</p>
|
||
)}
|
||
</div>
|
||
<span className="text-sm font-medium text-[var(--color-moy-dark)] ml-8 shrink-0">
|
||
{item.price}
|
||
</span>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
))}
|
||
|
||
<p className="text-xs text-center text-gray-400 border-t border-gray-200 pt-8">
|
||
{t.note}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|