first commit

This commit is contained in:
AyrisAI
2026-08-20 01:51:59 +03:00
commit 97b83c7fd4
109 changed files with 21215 additions and 0 deletions
+141
View File
@@ -0,0 +1,141 @@
import type { MenuCategory, RestaurantData } from "@/components/PublicMenuClient";
export const DEMO_RESTAURANT: RestaurantData = {
id: "demo-restaurant-1",
name: "Gusto & Co. Brasserie",
slug: "gusto-brasserie",
logo_url: null,
phone: "+90 (212) 555 0192",
address: "Nişantaşı, Abdi İpekçi Cad. No: 42, İstanbul",
};
export const DEMO_CATEGORIES: MenuCategory[] = [
{
id: "cat-starters",
name: "Başlangıçlar & Meze",
description: "Özenle seçilmiş taze malzemeler ve paylaşımlık tabaklar",
is_active: true,
menu_items: [
{
id: "item-1",
name: "Truffle Burrata & Çeri Domates",
description: "Manda burrata, trüf yağı, fırınlanmış karamelize çeri domates ve fesleğen pesto sosu ile.",
price: 420,
image_url: "https://images.unsplash.com/photo-1592417817098-8f3d69102353?w=600&auto=format&fit=crop&q=80",
is_active: true,
},
{
id: "item-2",
name: "Dana Carpaccio",
description: "İnce dilimlenmiş marine bonfile, roka, parmesan talaşı, kapari ve trüflü balzamik glaze.",
price: 490,
image_url: "https://images.unsplash.com/photo-1544025162-d76694265947?w=600&auto=format&fit=crop&q=80",
is_active: true,
},
{
id: "item-3",
name: "Çıtır Kalamar & Aioli",
description: "Ege kalamarı, hafif mısır unlu kaplama, köz biberli ev yapımı aioli sos ve taze limon dilimleri.",
price: 380,
image_url: "https://images.unsplash.com/photo-1599488615731-7e5c2823ff28?w=600&auto=format&fit=crop&q=80",
is_active: true,
},
],
},
{
id: "cat-mains",
name: "Ana Yemekler & Izgaralar",
description: "Kömür ateşinde dinlendirilmiş etler ve şefin özel tarifleri",
is_active: true,
menu_items: [
{
id: "item-4",
name: "Dry-Aged Ribeye Steak (300g)",
description: "28 gün kuru dinlendirilmiş antrikot, trüflü patates püresi, ızgara kuşkonmaz ve biberiye sosu.",
price: 890,
image_url: "https://images.unsplash.com/photo-1600891964599-f61ba0e24092?w=600&auto=format&fit=crop&q=80",
is_active: true,
},
{
id: "item-5",
name: "Trüflü Ev Yapımı Pappardelle",
description: "Taze el açması makarna, yaban mantarları kreması, taze trüf mantarı rendesi ve 24 aylık parmesan.",
price: 520,
image_url: "https://images.unsplash.com/photo-1621996346565-e3d5d6281691?w=600&auto=format&fit=crop&q=80",
is_active: true,
},
{
id: "item-6",
name: "Fırınlanmış Norveç Somonu",
description: "Közlenmiş rezene, fırın tatlı patates, taze otlar ve narenciye beurre blanc sosu eşliğinde.",
price: 680,
image_url: "https://images.unsplash.com/photo-1519708227418-c8fd9a32b7a2?w=600&auto=format&fit=crop&q=80",
is_active: true,
},
{
id: "item-7",
name: "Gusto Signature Smash Burger",
description: "İkili 100g kuru dinlendirilmiş köfte, duble cheddar peyniri, karamelize soğan, trüf mayonez ve brioche ekmeği.",
price: 440,
image_url: "https://images.unsplash.com/photo-1568901346375-23c9450c58cd?w=600&auto=format&fit=crop&q=80",
is_active: true,
},
],
},
{
id: "cat-cocktails",
name: "İmza Kokteyller & İçecekler",
description: "Miksolojistlerimiz tarafından hazırlanan taze meyveli kokteyller",
is_active: true,
menu_items: [
{
id: "item-8",
name: "Smoked Rosemary Old Fashioned",
description: "Meşe fıçıda dinlendirilmiş burbon, Angostura bitter, tütsülenmiş taze biberiye ve portakal kabuğu.",
price: 410,
image_url: "https://images.unsplash.com/photo-1514362545857-3bc16c4c7d1b?w=600&auto=format&fit=crop&q=80",
is_active: true,
},
{
id: "item-9",
name: "Passionfruit & Chili Margarita",
description: "Tekila reposado, çarkıfelek meyvesi püresi, taze misket limonu suyu, agave ve acı biberli tuz çemberi.",
price: 390,
image_url: "https://images.unsplash.com/photo-1551024709-8f23befc6f87?w=600&auto=format&fit=crop&q=80",
is_active: true,
},
{
id: "item-10",
name: "Artisan Soğuk Demleme Kahve (Cold Brew)",
description: "18 saat soğuk demlenmiş tek kökenli Etiyopya Yirgacheffe çekirdekleri, buz ile servis edilir.",
price: 160,
image_url: "https://images.unsplash.com/photo-1517701550927-30cf4ba1dba5?w=600&auto=format&fit=crop&q=80",
is_active: true,
},
],
},
{
id: "cat-desserts",
name: "Tatlılar",
description: "Günün tatlı sonu için taze pastacılık lezzetleri",
is_active: true,
menu_items: [
{
id: "item-11",
name: "San Sebastián Cheesecake & Belçika Çikolatası",
description: "Akışkan fırınlanmış Bask cheesecake, eritilmiş sıcak Callebaut bitter çikolatası ile.",
price: 280,
image_url: "https://images.unsplash.com/photo-1533134242443-d4fd215305ad?w=600&auto=format&fit=crop&q=80",
is_active: true,
},
{
id: "item-12",
name: "Sıcak Çikolatalı Fondan & Vanilyalı Dondurma",
description: "Akışkan lav kek, Madagaskar vanilyalı dondurma ve çıtır fındık krokant.",
price: 310,
image_url: "https://images.unsplash.com/photo-1606313564200-e75d5e30476c?w=600&auto=format&fit=crop&q=80",
is_active: true,
},
],
},
];
+11
View File
@@ -0,0 +1,11 @@
import { createClient } from "@supabase/supabase-js";
const url = process.env.NEXT_PUBLIC_SUPABASE_URL;
const anonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;
if (!url || !anonKey) {
throw new Error("NEXT_PUBLIC_SUPABASE_URL / NEXT_PUBLIC_SUPABASE_ANON_KEY missing");
}
// Anon key only — RLS enforces that only published-menu data is readable here.
export const supabase = createClient(url, anonKey);
+131
View File
@@ -0,0 +1,131 @@
import type { ThemeConfig } from "@menulio/shared";
export interface ThemePreset {
key: string;
name: string;
fontFamily: "serif" | "sans" | "heading";
config: ThemeConfig;
cardBg: string;
cardBorder: string;
textPrimary: string;
textSecondary: string;
accentBg: string;
headerGradient: string;
badgeBg: string;
badgeText: string;
}
export const THEME_PRESETS: Record<string, ThemePreset> = {
elegant: {
key: "elegant",
name: "Elegant Gold",
fontFamily: "serif",
config: {
primaryColor: "#C8A96B",
background: "#FAF8F5",
productLayout: "card",
categoryLayout: "accordion",
},
cardBg: "#FFFFFF",
cardBorder: "rgba(200, 169, 107, 0.18)",
textPrimary: "#1C1917",
textSecondary: "#78716C",
accentBg: "rgba(200, 169, 107, 0.12)",
headerGradient: "linear-gradient(180deg, #1C1917 0%, #292524 100%)",
badgeBg: "#F5F0E6",
badgeText: "#926E27",
},
modern: {
key: "modern",
name: "Modern Sapphire",
fontFamily: "sans",
config: {
primaryColor: "#2563EB",
background: "#F8FAFC",
productLayout: "card",
categoryLayout: "tabs",
},
cardBg: "#FFFFFF",
cardBorder: "rgba(226, 232, 240, 0.9)",
textPrimary: "#0F172A",
textSecondary: "#64748B",
accentBg: "rgba(37, 99, 235, 0.08)",
headerGradient: "linear-gradient(135deg, #1E293B 0%, #0F172A 100%)",
badgeBg: "#EFF6FF",
badgeText: "#1D4ED8",
},
dark: {
key: "dark",
name: "Luxury Dark",
fontFamily: "heading",
config: {
primaryColor: "#F59E0B",
background: "#0F0F12",
productLayout: "card",
categoryLayout: "accordion",
},
cardBg: "#18181D",
cardBorder: "rgba(255, 255, 255, 0.07)",
textPrimary: "#F8FAFC",
textSecondary: "#94A3B8",
accentBg: "rgba(245, 158, 11, 0.12)",
headerGradient: "linear-gradient(180deg, #09090B 0%, #18181B 100%)",
badgeBg: "#27272A",
badgeText: "#FBBF24",
},
minimal: {
key: "minimal",
name: "Nordic Minimal",
fontFamily: "sans",
config: {
primaryColor: "#18181B",
background: "#FAFAFA",
productLayout: "list",
categoryLayout: "flat",
},
cardBg: "#FFFFFF",
cardBorder: "#E4E4E7",
textPrimary: "#18181B",
textSecondary: "#71717A",
accentBg: "#F4F4F5",
headerGradient: "linear-gradient(180deg, #27272A 0%, #18181B 100%)",
badgeBg: "#F4F4F5",
badgeText: "#27272A",
},
classic: {
key: "classic",
name: "Classic Bistro",
fontFamily: "serif",
config: {
primaryColor: "#8B1E1E",
background: "#FFF9F2",
productLayout: "list",
categoryLayout: "accordion",
},
cardBg: "#FFFFFF",
cardBorder: "rgba(139, 30, 30, 0.15)",
textPrimary: "#2D1B18",
textSecondary: "#7A6966",
accentBg: "rgba(139, 30, 30, 0.08)",
headerGradient: "linear-gradient(180deg, #38120F 0%, #240B0A 100%)",
badgeBg: "#FDF2F0",
badgeText: "#8B1E1E",
},
};
const ELEGANT_PRESET: ThemePreset = THEME_PRESETS.elegant!;
export const DEFAULT_THEME: ThemeConfig = ELEGANT_PRESET.config;
export function resolveThemePreset(themeKey?: string, customConfig?: Partial<ThemeConfig>): ThemePreset {
const base = (themeKey ? THEME_PRESETS[themeKey] : undefined) ?? ELEGANT_PRESET;
if (!customConfig) return base;
return {
...base,
config: {
...base.config,
...customConfig,
},
};
}