feat: redesign web menu layout, add header cover banner & dynamic header layout, refine mobile inputs and theme selector
This commit is contained in:
@@ -20,7 +20,7 @@ export default async function DemoMenuPage({ searchParams }: PageProps) {
|
||||
restaurant={DEMO_RESTAURANT}
|
||||
categories={DEMO_CATEGORIES}
|
||||
initialThemeKey={theme}
|
||||
allowThemeSwitching={true}
|
||||
allowThemeSwitching={false}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ export default async function PublicMenuPage({ params, searchParams }: PageProps
|
||||
let restaurant: any = null;
|
||||
const { data: bySlug } = await supabase
|
||||
.from("restaurants")
|
||||
.select("id, name, slug, logo_url, phone, address")
|
||||
.select("id, name, slug, logo_url, cover_url, phone, address")
|
||||
.eq("slug", slug)
|
||||
.maybeSingle();
|
||||
|
||||
@@ -84,7 +84,7 @@ export default async function PublicMenuPage({ params, searchParams }: PageProps
|
||||
// 2. Try finding restaurant by custom domain hostname
|
||||
const { data: domainRow } = await supabase
|
||||
.from("domains")
|
||||
.select("restaurant_id, restaurants(id, name, slug, logo_url, phone, address)")
|
||||
.select("restaurant_id, restaurants(id, name, slug, logo_url, cover_url, phone, address)")
|
||||
.eq("hostname", slug)
|
||||
.maybeSingle();
|
||||
|
||||
@@ -144,6 +144,7 @@ export default async function PublicMenuPage({ params, searchParams }: PageProps
|
||||
name: restaurant.name,
|
||||
slug: restaurant.slug,
|
||||
logo_url: restaurant.logo_url,
|
||||
cover_url: restaurant.cover_url,
|
||||
phone: restaurant.phone,
|
||||
address: restaurant.address,
|
||||
};
|
||||
|
||||
@@ -26,6 +26,7 @@ export interface RestaurantData {
|
||||
name: string;
|
||||
slug: string;
|
||||
logo_url: string | null;
|
||||
cover_url?: string | null;
|
||||
phone?: string | null;
|
||||
address?: string | null;
|
||||
}
|
||||
@@ -43,7 +44,7 @@ export function PublicMenuClient({
|
||||
categories,
|
||||
initialThemeKey = "elegant",
|
||||
customThemeConfig,
|
||||
allowThemeSwitching = true,
|
||||
allowThemeSwitching = false,
|
||||
}: PublicMenuClientProps) {
|
||||
const [selectedThemeKey, setSelectedThemeKey] = useState<string>(initialThemeKey);
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
@@ -176,26 +177,38 @@ export function PublicMenuClient({
|
||||
|
||||
{/* Header Hero Banner */}
|
||||
<header
|
||||
style={{ background: theme.headerGradient }}
|
||||
className="relative text-white px-4 sm:px-6 pt-8 sm:pt-10 pb-7 sm:pb-8 rounded-b-3xl shadow-lg overflow-hidden"
|
||||
style={{ background: restaurant.cover_url ? "none" : theme.headerGradient }}
|
||||
className="relative text-white px-4 sm:px-6 pt-8 sm:pt-10 pb-7 sm:pb-8 rounded-b-3xl shadow-lg overflow-hidden min-h-[200px]"
|
||||
>
|
||||
{/* Background Cover Image if available */}
|
||||
{restaurant.cover_url && (
|
||||
<>
|
||||
<img
|
||||
src={restaurant.cover_url}
|
||||
alt={restaurant.name}
|
||||
className="absolute inset-0 w-full h-full object-cover z-0"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-b from-black/65 via-black/45 to-black/85 z-0 backdrop-blur-[1px]" />
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Subtle Ambient Glow */}
|
||||
<div
|
||||
className="absolute top-0 right-0 w-64 h-64 rounded-full blur-3xl opacity-20 pointer-events-none"
|
||||
style={{ backgroundColor: theme.config.primaryColor }}
|
||||
/>
|
||||
{!restaurant.cover_url && (
|
||||
<div
|
||||
className="absolute top-0 right-0 w-64 h-64 rounded-full blur-3xl opacity-20 pointer-events-none"
|
||||
style={{ backgroundColor: theme.config.primaryColor }}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Top Bar: Table & Action Buttons */}
|
||||
<div className="flex items-center justify-between mb-4 sm:mb-5 relative z-10">
|
||||
<div className="flex items-center justify-between mb-2 relative z-10">
|
||||
{tableNumber ? (
|
||||
<div className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full bg-white/10 backdrop-blur-md border border-white/15 text-xs font-semibold tracking-wide">
|
||||
<div className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full bg-black/40 backdrop-blur-md border border-white/20 text-xs font-semibold tracking-wide text-white">
|
||||
<span className="w-2 h-2 rounded-full bg-emerald-400 animate-pulse" />
|
||||
Masa {tableNumber}
|
||||
</div>
|
||||
) : (
|
||||
<div className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full bg-white/10 backdrop-blur-md border border-white/15 text-xs font-medium tracking-wide">
|
||||
<span>✨</span> Dijital QR Menü
|
||||
</div>
|
||||
<div />
|
||||
)}
|
||||
|
||||
<div className="flex items-center gap-1.5 sm:gap-2">
|
||||
@@ -230,54 +243,84 @@ export function PublicMenuClient({
|
||||
</svg>
|
||||
)}
|
||||
</button>
|
||||
|
||||
{/* Live Theme Switcher Trigger */}
|
||||
{allowThemeSwitching && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowThemePicker(!showThemePicker)}
|
||||
className="px-2.5 py-1 sm:py-1.5 rounded-full bg-white/10 hover:bg-white/20 active:scale-95 transition-all flex items-center gap-1.5 border border-white/15 backdrop-blur-md text-[11px] sm:text-xs font-semibold"
|
||||
aria-label="Tema Değiştir"
|
||||
>
|
||||
<span className="w-2 h-2 sm:w-2.5 sm:h-2.5 rounded-full" style={{ backgroundColor: theme.config.primaryColor }} />
|
||||
<span>Tema</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Restaurant Identity */}
|
||||
<div className="flex items-center gap-3 sm:gap-4 relative z-10">
|
||||
{restaurant.logo_url ? (
|
||||
<img
|
||||
src={restaurant.logo_url}
|
||||
alt={restaurant.name}
|
||||
className="w-14 h-14 sm:w-16 sm:h-16 rounded-2xl object-cover border-2 shadow-md flex-shrink-0"
|
||||
style={{ borderColor: theme.config.primaryColor }}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
className="w-14 h-14 sm:w-16 sm:h-16 rounded-2xl flex items-center justify-center font-bold text-xl sm:text-2xl flex-shrink-0 shadow-inner border border-white/20"
|
||||
style={{
|
||||
background: "rgba(255, 255, 255, 0.12)",
|
||||
color: theme.config.primaryColor,
|
||||
}}
|
||||
>
|
||||
{restaurant.name.charAt(0).toUpperCase()}
|
||||
</div>
|
||||
)}
|
||||
{/* Restaurant Identity - Dynamic Header Layout (Centered or Left) */}
|
||||
{theme.config.headerLayout === "left" ? (
|
||||
/* Left-Aligned Header Layout */
|
||||
<div className="flex items-center gap-3.5 sm:gap-4 relative z-10 pt-1 pb-1">
|
||||
{restaurant.logo_url ? (
|
||||
<img
|
||||
src={restaurant.logo_url}
|
||||
alt={restaurant.name}
|
||||
className="w-14 h-14 sm:w-16 sm:h-16 rounded-2xl object-cover border-2 shadow-md flex-shrink-0"
|
||||
style={{ borderColor: theme.config.primaryColor }}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
className="w-14 h-14 sm:w-16 sm:h-16 rounded-2xl flex items-center justify-center font-bold text-xl sm:text-2xl flex-shrink-0 shadow-inner border border-white/20"
|
||||
style={{
|
||||
background: "rgba(255, 255, 255, 0.12)",
|
||||
color: theme.config.primaryColor,
|
||||
}}
|
||||
>
|
||||
{restaurant.name.charAt(0).toUpperCase()}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex-1 min-w-0">
|
||||
<h1 className="text-xl sm:text-2xl font-bold tracking-tight leading-snug break-words">
|
||||
<div className="flex-1 min-w-0">
|
||||
<h1 className="text-xl sm:text-2xl font-bold tracking-tight leading-snug break-words text-white">
|
||||
{restaurant.name}
|
||||
</h1>
|
||||
<p className="text-[11px] sm:text-xs text-white/80 mt-0.5 flex items-center gap-1.5 font-medium">
|
||||
<span>{totalItemsCount} Özel Lezzet</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
/* Centered Header Layout */
|
||||
<div className="flex flex-col items-center text-center relative z-10 pt-1 pb-2">
|
||||
{/* Centered Logo Avatar */}
|
||||
<div className="relative group">
|
||||
{restaurant.logo_url ? (
|
||||
<img
|
||||
src={restaurant.logo_url}
|
||||
alt={restaurant.name}
|
||||
className="w-18 h-18 sm:w-20 sm:h-20 rounded-full object-cover border-2 shadow-2xl transition-transform duration-300 group-hover:scale-105"
|
||||
style={{ borderColor: theme.config.primaryColor }}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
className="w-18 h-18 sm:w-20 sm:h-20 rounded-full flex items-center justify-center font-black text-2xl sm:text-3xl shadow-2xl border-2 backdrop-blur-md"
|
||||
style={{
|
||||
background: "rgba(255, 255, 255, 0.15)",
|
||||
borderColor: theme.config.primaryColor,
|
||||
color: "#FFFFFF",
|
||||
}}
|
||||
>
|
||||
{restaurant.name.charAt(0).toUpperCase()}
|
||||
</div>
|
||||
)}
|
||||
{/* Decorative Ambient Glow Ring */}
|
||||
<div
|
||||
className="absolute -inset-1 rounded-full blur-md opacity-30 pointer-events-none"
|
||||
style={{ backgroundColor: theme.config.primaryColor }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Centered Restaurant Title */}
|
||||
<h1 className="text-2xl sm:text-3xl font-extrabold tracking-tight leading-snug mt-3 text-white drop-shadow-md max-w-md">
|
||||
{restaurant.name}
|
||||
</h1>
|
||||
<p className="text-[11px] sm:text-xs text-white/70 mt-0.5 flex flex-wrap items-center gap-1.5">
|
||||
|
||||
{/* Centered Subtitle Badge Pill */}
|
||||
<div className="mt-2 inline-flex items-center gap-1.5 px-3.5 py-1 rounded-full bg-black/35 backdrop-blur-md border border-white/15 text-xs font-medium text-white/90 shadow-sm">
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-amber-400 animate-pulse" />
|
||||
<span>{totalItemsCount} Özel Lezzet</span>
|
||||
<span>•</span>
|
||||
<span className="capitalize">{theme.name} Şablonu</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Live Search Bar */}
|
||||
<div className="mt-6 relative z-10">
|
||||
@@ -810,12 +853,6 @@ export function PublicMenuClient({
|
||||
>
|
||||
₺{item.price.toFixed(0)}
|
||||
</span>
|
||||
<span
|
||||
className="w-6 h-6 rounded-full flex items-center justify-center text-xs font-bold text-stone-950 shadow-sm transition-transform group-hover:scale-110"
|
||||
style={{ backgroundColor: theme.config.primaryColor }}
|
||||
>
|
||||
+
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
@@ -905,48 +942,19 @@ export function PublicMenuClient({
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
{/* Floating Quick Action Bar (Garson Çağır / Hesap İste / Başa Dön) */}
|
||||
<aside aria-label="Masa Servis İşlemleri" className="fixed bottom-5 left-1/2 -translate-x-1/2 z-40 max-w-sm w-full px-4 flex items-center justify-between gap-2 pointer-events-none">
|
||||
<div className="flex items-center gap-2 pointer-events-auto shadow-2xl rounded-full p-1 bg-stone-900/90 backdrop-blur-lg border border-stone-700 text-white">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() =>
|
||||
triggerServiceAction(
|
||||
tableNumber
|
||||
? `Masa ${tableNumber} için Garson Çağrıldı! Garsonunuz en kısa sürede masanızda olacaktır.`
|
||||
: "Garson çağrıldı! Garsonunuz hemen masanızda olacaktır.",
|
||||
)
|
||||
}
|
||||
className="px-3.5 py-2 rounded-full hover:bg-white/15 active:scale-95 transition-all text-xs font-bold flex items-center gap-1.5"
|
||||
>
|
||||
<span>👋</span> Garson Çağır
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() =>
|
||||
triggerServiceAction(
|
||||
tableNumber
|
||||
? `Masa ${tableNumber} için Hesap İsteği iletildi!`
|
||||
: "Hesap isteği iletildi!",
|
||||
)
|
||||
}
|
||||
className="px-3.5 py-2 rounded-full hover:bg-white/15 active:scale-95 transition-all text-xs font-bold flex items-center gap-1.5"
|
||||
>
|
||||
<span>💳</span> Hesap İste
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{showBackToTop && (
|
||||
{/* Floating Back to Top Button */}
|
||||
{showBackToTop && (
|
||||
<aside aria-label="Başa Dön" className="fixed bottom-5 right-5 z-40">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => window.scrollTo({ top: 0, behavior: "smooth" })}
|
||||
className="w-11 h-11 rounded-full bg-stone-900 text-white shadow-2xl flex items-center justify-center pointer-events-auto active:scale-90 transition-all border border-stone-700"
|
||||
className="w-11 h-11 rounded-full bg-stone-900 text-white shadow-2xl flex items-center justify-center active:scale-90 transition-all border border-stone-700 font-bold"
|
||||
aria-label="Başa Dön"
|
||||
>
|
||||
↑
|
||||
</button>
|
||||
)}
|
||||
</aside>
|
||||
</aside>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Item Detail Modal */}
|
||||
@@ -1003,30 +1011,17 @@ export function PublicMenuClient({
|
||||
{selectedItem.description}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* Quality Badges */}
|
||||
<div className="pt-2 flex flex-wrap gap-2 text-xs">
|
||||
<span className="px-3 py-1 rounded-full bg-emerald-50 text-emerald-700 font-semibold border border-emerald-200">
|
||||
🌱 Taze & Günlük
|
||||
</span>
|
||||
<span className="px-3 py-1 rounded-full bg-amber-50 text-amber-700 font-semibold border border-amber-200">
|
||||
⭐ Şefin İmzası
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Modal Footer */}
|
||||
<div className="p-4 border-t" style={{ borderColor: theme.cardBorder }}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setSelectedItem(null);
|
||||
triggerServiceAction(`"${selectedItem.name}" sipariş tercihleriniz garsona iletildi!`);
|
||||
}}
|
||||
onClick={() => setSelectedItem(null)}
|
||||
className="w-full py-3.5 rounded-2xl font-bold text-white shadow-lg active:scale-98 transition-all flex items-center justify-center gap-2 text-sm"
|
||||
style={{ backgroundColor: theme.config.primaryColor }}
|
||||
>
|
||||
<span>➕</span> Garsona Sipariş Olarak Bildir
|
||||
Kapat
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { PublicMenuClient, type MenuCategory, type RestaurantData } from "@/components/PublicMenuClient";
|
||||
import { THEME_PRESETS, type ThemePreset } from "@/lib/theme";
|
||||
import { THEME_PRESETS } from "@/lib/theme";
|
||||
|
||||
interface TemplateGalleryClientProps {
|
||||
restaurant: RestaurantData;
|
||||
@@ -14,199 +13,86 @@ interface TemplateGalleryClientProps {
|
||||
export function TemplateGalleryClient({
|
||||
restaurant,
|
||||
categories,
|
||||
initialThemeKey = "elegant",
|
||||
}: TemplateGalleryClientProps) {
|
||||
const [selectedThemeKey, setSelectedThemeKey] = useState<string>(initialThemeKey);
|
||||
const [viewMode, setViewMode] = useState<"phone" | "fullscreen">("phone");
|
||||
|
||||
const currentPreset: ThemePreset = THEME_PRESETS[selectedThemeKey] || THEME_PRESETS.elegant!;
|
||||
const presetsList = Object.values(THEME_PRESETS);
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-stone-950 text-stone-100 flex flex-col font-sans">
|
||||
{/* Top Navbar */}
|
||||
<header className="border-b border-stone-800/80 bg-stone-900/90 backdrop-blur-xl sticky top-0 z-50 px-4 sm:px-6 py-3.5">
|
||||
<div className="max-w-7xl mx-auto flex flex-col md:flex-row items-center justify-between gap-3">
|
||||
<div className="flex items-center justify-between w-full md:w-auto">
|
||||
<div className="flex items-center gap-3">
|
||||
<Link href="/" className="font-black text-xl tracking-tight text-amber-400">
|
||||
MENULIO
|
||||
</Link>
|
||||
<span className="text-stone-600 hidden sm:inline">/</span>
|
||||
<span className="text-xs font-semibold text-stone-400 hidden sm:inline">Şablon Galerisi</span>
|
||||
</div>
|
||||
|
||||
{/* View Mode Toggle (Visible on desktop/tablet) */}
|
||||
<div className="flex items-center bg-stone-800/80 p-1 rounded-xl border border-stone-700 md:hidden">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setViewMode("phone")}
|
||||
className={`px-2.5 py-1 rounded-lg text-xs font-bold transition-all ${
|
||||
viewMode === "phone" ? "bg-amber-400 text-stone-950 shadow" : "text-stone-400"
|
||||
}`}
|
||||
>
|
||||
📱 Mobil
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setViewMode("fullscreen")}
|
||||
className={`px-2.5 py-1 rounded-lg text-xs font-bold transition-all ${
|
||||
viewMode === "fullscreen" ? "bg-amber-400 text-stone-950 shadow" : "text-stone-400"
|
||||
}`}
|
||||
>
|
||||
🖥️ Tam
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 5 Theme Pills - Smooth Horizontal Scroll */}
|
||||
<div className="flex items-center gap-2 overflow-x-auto w-full md:w-auto pb-1 md:pb-0 no-scrollbar">
|
||||
{Object.values(THEME_PRESETS).map((preset) => {
|
||||
const isActive = selectedThemeKey === preset.key;
|
||||
return (
|
||||
<button
|
||||
key={preset.key}
|
||||
type="button"
|
||||
onClick={() => setSelectedThemeKey(preset.key)}
|
||||
className={`px-3.5 py-1.5 rounded-xl text-xs font-bold transition-all flex items-center gap-2 whitespace-nowrap border flex-shrink-0 ${
|
||||
isActive
|
||||
? "bg-white text-stone-950 border-white shadow-lg scale-105"
|
||||
: "bg-stone-800/90 text-stone-300 border-stone-700 hover:border-stone-500 hover:text-white"
|
||||
}`}
|
||||
>
|
||||
<span
|
||||
className="w-2.5 h-2.5 rounded-full"
|
||||
style={{ backgroundColor: preset.config.primaryColor }}
|
||||
/>
|
||||
<span>{preset.name}</span>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="hidden md:flex items-center gap-3">
|
||||
{/* View Mode Toggle (Desktop) */}
|
||||
<div className="flex items-center bg-stone-800/80 p-1 rounded-xl border border-stone-700">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setViewMode("phone")}
|
||||
className={`px-3 py-1 rounded-lg text-xs font-bold transition-all ${
|
||||
viewMode === "phone" ? "bg-amber-400 text-stone-950 shadow" : "text-stone-400 hover:text-white"
|
||||
}`}
|
||||
>
|
||||
📱 Telefon
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setViewMode("fullscreen")}
|
||||
className={`px-3 py-1 rounded-lg text-xs font-bold transition-all ${
|
||||
viewMode === "fullscreen" ? "bg-amber-400 text-stone-950 shadow" : "text-stone-400 hover:text-white"
|
||||
}`}
|
||||
>
|
||||
🖥️ Tam Ekran
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<Link
|
||||
href="/"
|
||||
className="text-xs font-bold px-4 py-2 rounded-xl bg-amber-500 hover:bg-amber-400 text-stone-950 transition-all shadow-md shadow-amber-500/20"
|
||||
>
|
||||
Uygulamayı İndir →
|
||||
<div className="max-w-7xl mx-auto flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
<Link href="/" className="font-black text-xl tracking-tight text-amber-400">
|
||||
MENULIO
|
||||
</Link>
|
||||
<span className="text-stone-600 hidden sm:inline">/</span>
|
||||
<span className="text-xs font-semibold text-stone-400 hidden sm:inline">
|
||||
Şablon Galerisi
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<Link
|
||||
href="/"
|
||||
className="text-xs font-bold px-4 py-2 rounded-xl bg-amber-500 hover:bg-amber-400 text-stone-950 transition-all shadow-md shadow-amber-500/20"
|
||||
>
|
||||
Ana Sayfa →
|
||||
</Link>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{/* Main Content Area */}
|
||||
<main className="flex-1 w-full flex flex-col items-center justify-center p-0 sm:p-6 lg:p-8">
|
||||
{viewMode === "fullscreen" ? (
|
||||
/* Fullscreen Fluid View */
|
||||
<div className="w-full flex-1 min-h-[85vh]">
|
||||
<PublicMenuClient
|
||||
restaurant={restaurant}
|
||||
categories={categories}
|
||||
initialThemeKey={selectedThemeKey}
|
||||
allowThemeSwitching={true}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
/* Responsive Device Simulator / Side-by-Side on Desktop */
|
||||
<div className="w-full max-w-6xl mx-auto grid grid-cols-1 lg:grid-cols-12 gap-8 items-center justify-center py-4">
|
||||
{/* Left Info Panel (Visible on Desktop) */}
|
||||
<div className="hidden lg:flex lg:col-span-5 flex-col space-y-6 pr-4">
|
||||
<div className="space-y-2">
|
||||
<span className="text-amber-400 text-xs font-bold uppercase tracking-wider">
|
||||
ŞABLON DETAYI
|
||||
</span>
|
||||
<h2 className="text-3xl font-extrabold text-white">
|
||||
{currentPreset.name}
|
||||
</h2>
|
||||
<p className="text-sm text-stone-400 leading-relaxed">
|
||||
{currentPreset.key === "elegant" && "Fine dining restoranlar, şarap evleri ve lüks steakhouse mekanlar için altın & krem tonlarında yüksek prestijli tasarım."}
|
||||
{currentPreset.key === "modern" && "Kafeler, burgerciler ve dinamik mekanlar için canlı mavi safir tonları ve hızlı arama odaklı ızgara düzeni."}
|
||||
{currentPreset.key === "dark" && "Gece kulüpleri, kokteyl barlar ve lounge mekanlar için obsidian siyahı ve kehribar parıltılı lüks mod."}
|
||||
{currentPreset.key === "minimal" && "Butik kahveciler, fırınlar ve üçüncü nesil mekanlar için ferah ve monokromatik Nordic mizanpaj."}
|
||||
{currentPreset.key === "classic" && "Geleneksel brasserie'ler, meyhaneler ve trattoria'lar için Toskana bordo ve sıcak rustik doku."}
|
||||
</p>
|
||||
{/* Main Content Area - Stacked Vertically */}
|
||||
<main className="flex-1 w-full max-w-4xl mx-auto py-10 px-4 space-y-16">
|
||||
{presetsList.map((preset) => (
|
||||
<section
|
||||
key={preset.key}
|
||||
className="flex flex-col items-center gap-8 border-b border-stone-800/80 pb-16 last:border-0"
|
||||
>
|
||||
{/* Theme Info */}
|
||||
<div className="text-center max-w-xl space-y-3">
|
||||
<div className="inline-flex items-center gap-2.5 px-3.5 py-1.5 rounded-full bg-stone-900 border border-stone-800 text-xs font-bold text-stone-300">
|
||||
<span
|
||||
className="w-2.5 h-2.5 rounded-full"
|
||||
style={{ backgroundColor: preset.config.primaryColor }}
|
||||
/>
|
||||
<span className="uppercase tracking-wider text-[11px]">{preset.key} Şablonu</span>
|
||||
</div>
|
||||
|
||||
{/* Theme Specs */}
|
||||
<div className="p-5 rounded-2xl bg-stone-900 border border-stone-800 space-y-3.5 text-xs">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-stone-400">Vurgu Rengi</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<span
|
||||
className="w-4 h-4 rounded-full border border-white/20"
|
||||
style={{ backgroundColor: currentPreset.config.primaryColor }}
|
||||
/>
|
||||
<span className="font-mono text-stone-200">{currentPreset.config.primaryColor}</span>
|
||||
</div>
|
||||
</div>
|
||||
<h2 className="text-2xl sm:text-3xl font-extrabold text-white">
|
||||
{preset.name}
|
||||
</h2>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-stone-400">Tipografi Ailesi</span>
|
||||
<span className="font-semibold text-stone-200 uppercase">{currentPreset.fontFamily}</span>
|
||||
</div>
|
||||
<p className="text-xs sm:text-sm text-stone-400 leading-relaxed">
|
||||
Tipografi: <span className="uppercase text-stone-200 font-semibold">{preset.fontFamily}</span> • Mizanpaj: <span className="uppercase text-stone-200 font-semibold">{preset.config.productLayout}</span>
|
||||
</p>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-stone-400">Ürün Mizanpajı</span>
|
||||
<span className="font-semibold text-stone-200 uppercase">{currentPreset.config.productLayout}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-stone-400">Kategori Gezintisi</span>
|
||||
<span className="font-semibold text-stone-200 uppercase">{currentPreset.config.categoryLayout}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Direct Demo Link */}
|
||||
<Link
|
||||
href={`/demo?theme=${selectedThemeKey}`}
|
||||
target="_blank"
|
||||
className="w-full py-3.5 rounded-xl font-bold text-center bg-stone-800 hover:bg-stone-700 text-stone-200 border border-stone-700 transition-all text-xs flex items-center justify-center gap-2"
|
||||
>
|
||||
<span>↗</span> Yeni Sekmede Canlı Menüyü Aç
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Right Phone Mockup Container */}
|
||||
<div className="lg:col-span-7 flex justify-center w-full">
|
||||
<div className="w-full max-w-[420px] rounded-[36px] sm:rounded-[44px] overflow-hidden shadow-2xl border-0 sm:border-[8px] border-stone-800 bg-stone-900 relative">
|
||||
{/* Dynamic Island (Desktop only) */}
|
||||
<div className="hidden sm:block w-24 h-4 bg-stone-800 rounded-full mx-auto mt-2 mb-1" />
|
||||
|
||||
{/* Simulated Screen Body */}
|
||||
<div className="overflow-y-auto max-h-[85vh] sm:max-h-[780px] rounded-none sm:rounded-[32px] no-scrollbar">
|
||||
<PublicMenuClient
|
||||
restaurant={restaurant}
|
||||
categories={categories}
|
||||
initialThemeKey={selectedThemeKey}
|
||||
allowThemeSwitching={true}
|
||||
/>
|
||||
</div>
|
||||
<div className="pt-2">
|
||||
<Link
|
||||
href={`/demo?theme=${preset.key}`}
|
||||
target="_blank"
|
||||
className="inline-flex items-center gap-2 px-4 py-2.5 rounded-xl bg-stone-900 hover:bg-stone-800 text-stone-200 border border-stone-700/80 text-xs font-bold transition-all shadow-md"
|
||||
>
|
||||
<span>↗</span> Canlı Demoyu Sekmede Aç
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Phone Mockup Preview */}
|
||||
<div className="w-full max-w-[420px] rounded-[36px] sm:rounded-[44px] overflow-hidden shadow-2xl border-0 sm:border-[8px] border-stone-800 bg-stone-900 relative">
|
||||
{/* Dynamic Island */}
|
||||
<div className="hidden sm:block w-24 h-4 bg-stone-800 rounded-full mx-auto mt-2.5 mb-1" />
|
||||
|
||||
{/* Screen Body */}
|
||||
<div className="overflow-y-auto max-h-[720px] rounded-none sm:rounded-[32px] no-scrollbar">
|
||||
<PublicMenuClient
|
||||
restaurant={restaurant}
|
||||
categories={categories}
|
||||
initialThemeKey={preset.key}
|
||||
allowThemeSwitching={false}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
))}
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -5,6 +5,7 @@ export const DEMO_RESTAURANT: RestaurantData = {
|
||||
name: "Gusto & Co. Brasserie",
|
||||
slug: "gusto-brasserie",
|
||||
logo_url: null,
|
||||
cover_url: "https://images.unsplash.com/photo-1517248135467-4c7edcad34c4?w=1200&auto=format&fit=crop&q=80",
|
||||
phone: "+90 (212) 555 0192",
|
||||
address: "Nişantaşı, Abdi İpekçi Cad. No: 42, İstanbul",
|
||||
};
|
||||
|
||||
@@ -25,6 +25,7 @@ export const THEME_PRESETS: Record<string, ThemePreset> = {
|
||||
background: "#F7F3EC",
|
||||
productLayout: "card",
|
||||
categoryLayout: "tabs",
|
||||
headerLayout: "centered",
|
||||
},
|
||||
cardBg: "#FCFAF6",
|
||||
cardBorder: "#E4DBCF",
|
||||
@@ -44,6 +45,7 @@ export const THEME_PRESETS: Record<string, ThemePreset> = {
|
||||
background: "#0D1117",
|
||||
productLayout: "card",
|
||||
categoryLayout: "tabs",
|
||||
headerLayout: "left",
|
||||
},
|
||||
cardBg: "#FCF7EC",
|
||||
cardBorder: "rgba(255, 42, 133, 0.3)",
|
||||
@@ -63,6 +65,7 @@ export const THEME_PRESETS: Record<string, ThemePreset> = {
|
||||
background: "#EEEAE4",
|
||||
productLayout: "card",
|
||||
categoryLayout: "tabs",
|
||||
headerLayout: "centered",
|
||||
},
|
||||
cardBg: "#F7F4EF",
|
||||
cardBorder: "rgba(36, 70, 58, 0.2)",
|
||||
@@ -82,6 +85,7 @@ export const THEME_PRESETS: Record<string, ThemePreset> = {
|
||||
background: "#FFFFFF",
|
||||
productLayout: "card",
|
||||
categoryLayout: "tabs",
|
||||
headerLayout: "left",
|
||||
},
|
||||
cardBg: "#FFFFFF",
|
||||
cardBorder: "#000000",
|
||||
@@ -101,6 +105,7 @@ export const THEME_PRESETS: Record<string, ThemePreset> = {
|
||||
background: "#121316",
|
||||
productLayout: "card",
|
||||
categoryLayout: "tabs",
|
||||
headerLayout: "centered",
|
||||
},
|
||||
cardBg: "#1C1E24",
|
||||
cardBorder: "rgba(255, 255, 255, 0.08)",
|
||||
@@ -120,6 +125,7 @@ export const THEME_PRESETS: Record<string, ThemePreset> = {
|
||||
background: "#FAF8F5",
|
||||
productLayout: "card",
|
||||
categoryLayout: "accordion",
|
||||
headerLayout: "centered",
|
||||
},
|
||||
cardBg: "#FFFFFF",
|
||||
cardBorder: "rgba(200, 169, 107, 0.18)",
|
||||
@@ -139,6 +145,7 @@ export const THEME_PRESETS: Record<string, ThemePreset> = {
|
||||
background: "#F8FAFC",
|
||||
productLayout: "card",
|
||||
categoryLayout: "tabs",
|
||||
headerLayout: "left",
|
||||
},
|
||||
cardBg: "#FFFFFF",
|
||||
cardBorder: "rgba(226, 232, 240, 0.9)",
|
||||
@@ -158,6 +165,7 @@ export const THEME_PRESETS: Record<string, ThemePreset> = {
|
||||
background: "#0F0F12",
|
||||
productLayout: "card",
|
||||
categoryLayout: "accordion",
|
||||
headerLayout: "centered",
|
||||
},
|
||||
cardBg: "#18181D",
|
||||
cardBorder: "rgba(255, 255, 255, 0.07)",
|
||||
@@ -177,6 +185,7 @@ export const THEME_PRESETS: Record<string, ThemePreset> = {
|
||||
background: "#FAFAFA",
|
||||
productLayout: "list",
|
||||
categoryLayout: "flat",
|
||||
headerLayout: "left",
|
||||
},
|
||||
cardBg: "#FFFFFF",
|
||||
cardBorder: "#E4E4E7",
|
||||
@@ -196,6 +205,7 @@ export const THEME_PRESETS: Record<string, ThemePreset> = {
|
||||
background: "#FFF9F2",
|
||||
productLayout: "list",
|
||||
categoryLayout: "accordion",
|
||||
headerLayout: "centered",
|
||||
},
|
||||
cardBg: "#FFFFFF",
|
||||
cardBorder: "rgba(139, 30, 30, 0.15)",
|
||||
|
||||
Reference in New Issue
Block a user