kite-menu-lang

This commit is contained in:
2026-06-11 14:05:36 +03:00
parent dadde7eeea
commit f8ca2034e0
7 changed files with 206 additions and 42 deletions
+34 -5
View File
@@ -2,9 +2,11 @@
import { useEffect, useState, useRef } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { useRouter, usePathname } from "next/navigation";
import { MenuCategory, MenuItem as MenuItemType } from "@/data/menu";
import { CategoryNav } from "@/components/CategoryNav";
import { MenuItem } from "@/components/MenuItem";
import { getDictionary } from "@/lib/dictionaries";
export const CATEGORY_ICONS: Record<string, string> = {
"kahvaltiliklar": "🌅",
@@ -35,12 +37,23 @@ type SiteSettings = {
restaurantName: string
}
export default function MenuClient({ initialCategories, siteSettings }: { initialCategories: MenuCategory[], siteSettings: SiteSettings }) {
export default function MenuClient({ initialCategories, siteSettings, lang = "tr" }: { initialCategories: MenuCategory[], siteSettings: SiteSettings, lang?: string }) {
const [activeCategoryId, setActiveCategoryId] = useState<string>(
initialCategories[0]?.id || ""
);
const [selectedItem, setSelectedItem] = useState<MenuItemType | null>(null);
const sectionRefs = useRef<(HTMLElement | null)[]>([]);
const router = useRouter();
const pathname = usePathname();
const t = getDictionary(lang);
const switchLanguage = (newLang: string) => {
if (newLang === lang) return;
// Replace the current locale in the pathname
const newPath = pathname.replace(`/${lang}`, `/${newLang}`);
router.push(newPath || `/${newLang}`);
};
useEffect(() => {
const observer = new IntersectionObserver(
@@ -81,6 +94,22 @@ export default function MenuClient({ initialCategories, siteSettings }: { initia
}}
/>
{/* Language Switcher */}
<div className="absolute top-4 right-4 z-20 flex gap-2">
<button
onClick={() => switchLanguage('tr')}
className={`px-3 py-1.5 rounded-full text-[11px] font-sans tracking-widest uppercase transition-colors ${lang === 'tr' ? 'bg-white text-stone-900 font-bold' : 'bg-black/40 text-white/90 backdrop-blur-sm border border-white/20'}`}
>
TR
</button>
<button
onClick={() => switchLanguage('en')}
className={`px-3 py-1.5 rounded-full text-[11px] font-sans tracking-widest uppercase transition-colors ${lang === 'en' ? 'bg-white text-stone-900 font-bold' : 'bg-black/40 text-white/90 backdrop-blur-sm border border-white/20'}`}
>
EN
</button>
</div>
{/* Dark overlay to make text readable */}
<div className="absolute inset-0 z-0 bg-gradient-to-b from-black/60 via-black/40 to-black/80" />
@@ -96,7 +125,7 @@ export default function MenuClient({ initialCategories, siteSettings }: { initia
className="text-[10px] tracking-[0.38em] uppercase mb-8 font-sans font-medium"
style={{ color: "rgba(255,220,160,1)" }}
>
Akyaka · Muğla
{siteSettings.location || t.hero.location}
</p>
{/* Logo */}
@@ -120,7 +149,7 @@ export default function MenuClient({ initialCategories, siteSettings }: { initia
className="text-xs font-sans tracking-wide"
style={{ color: "rgba(255,218,168,0.5)" }}
>
Akyaka&apos;nın en keyifli menüsü
{t.hero.subtitle}
</p>
</motion.div>
</div>
@@ -203,7 +232,7 @@ export default function MenuClient({ initialCategories, siteSettings }: { initia
className="text-[10px] font-sans tracking-[0.3em] uppercase mt-1"
style={{ color: "rgba(255,200,130,0.35)" }}
>
Akyaka, Muğla
{siteSettings.location || t.hero.location}
</p>
<div
className="flex items-center gap-3 my-4"
@@ -217,7 +246,7 @@ export default function MenuClient({ initialCategories, siteSettings }: { initia
className="text-[11px] font-sans"
style={{ color: "rgba(120,90,60,0.5)" }}
>
© 2026 KiteBeach Akyaka. Tüm hakları saklıdır.
{t.footer.copyright}
</p>
<a
href="https://ayris.tech"
+17 -4
View File
@@ -1,6 +1,7 @@
import type { Metadata } from "next";
import { Cormorant_Garamond, Plus_Jakarta_Sans } from "next/font/google";
import "./globals.css";
import Script from "next/script";
import "../globals.css";
const cormorant = Cormorant_Garamond({
variable: "--font-cormorant",
@@ -22,14 +23,26 @@ export const metadata: Metadata = {
description: "Kite Beach Akyaka dijital menü.",
};
export default function RootLayout({
export default async function RootLayout({
children,
params,
}: Readonly<{
children: React.ReactNode;
params: Promise<{ lang: string }>;
}>) {
const { lang } = await params;
return (
<html lang="tr" className={`${cormorant.variable} ${jakarta.variable} h-full`}>
<body className="min-h-full flex flex-col antialiased" suppressHydrationWarning>{children}</body>
<html lang={lang} className={`${cormorant.variable} ${jakarta.variable} h-full`}>
<body className="min-h-full flex flex-col antialiased" suppressHydrationWarning>
{children}
{/* VPS Panel Analytics */}
<Script
src="https://panel.ayris.tech/api/analytics/script"
data-domain="https://menu.kitebeachakyaka.com.tr/"
strategy="afterInteractive"
/>
</body>
</html>
);
}
+15 -9
View File
@@ -1,8 +1,8 @@
import prisma from "@/lib/prisma";
import MenuClient from "./MenuClient";
import MenuClient from "../MenuClient";
import { MenuCategory } from "@/data/menu";
async function getMenuData(): Promise<MenuCategory[]> {
async function getMenuData(lang: string): Promise<MenuCategory[]> {
const dbCategories = await prisma.categories.findMany({
where: { status: 1 },
orderBy: { order_num: "asc" },
@@ -17,12 +17,12 @@ async function getMenuData(): Promise<MenuCategory[]> {
const categoryProducts = dbProducts.filter((p) => p.category_id === cat.id);
return {
id: cat.slug,
title: cat.name_tr,
title: lang === "tr" ? cat.name_tr : cat.name,
items: categoryProducts.map((p) => ({
id: p.id.toString(),
name: p.name_tr,
description: p.description_tr,
price: p.price.toString() + " ₺",
name: lang === "tr" ? p.name_tr : p.name,
description: (lang === "tr" ? p.description_tr : p.description) || "",
price: p.price.toString() + (lang === "tr" ? " ₺" : " ₺"), // Or maybe dynamic currency formatting
image: p.image_url || '/default-product.png',
})),
};
@@ -43,11 +43,17 @@ async function getSiteSettings() {
}
}
export default async function Page() {
export default async function Page({
params,
}: {
params: Promise<{ lang: string }>;
}) {
const { lang } = await params;
const [menuData, siteSettings] = await Promise.all([
getMenuData(),
getMenuData(lang),
getSiteSettings(),
]);
return <MenuClient initialCategories={menuData} siteSettings={siteSettings} />;
return <MenuClient initialCategories={menuData} siteSettings={siteSettings} lang={lang} />;
}
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB