diff --git a/README.md b/README.md index e215bc4..f7a90b0 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,75 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). +# 🌙 Luna Cocktail & More — QR Menü -## Getting Started +**Luna Cocktail and More** için tasarlanmış premium dijital QR menü uygulaması. -First, run the development server: +## ✨ Özellikler + +- 🎨 **Premium Dark Theme** — Altın aksanlı, lüks bar atmosferi +- 📱 **Tam Responsive** — Mobil öncelikli tasarım, QR kod ile erişime optimize +- 🧭 **Sticky Kategori Navigasyonu** — Yatay kaydırmalı, aktif kategori takibi +- ⭐ **Animasyonlu Hero** — Yıldız efektli, logo entegrasyonlu açılış ekranı +- 🍸 **Akıllı Fiyat Gösterimi** — Tek/Dbl, Kadeh/Şişe formatlarını otomatik algılar +- 🏷️ **Tat Profili Etiketleri** — Kokteyllerin tat profilini görsel etiketlerle sunar +- 🔝 **Yukarı Dön Butonu** — Uzun menüde kolay navigasyon +- 📊 **JSON Tabanlı Menü** — `menu/menu.json` dosyasını düzenleyerek menüyü güncelleyin + +## 🛠️ Teknolojiler + +- **Next.js 16** — React framework +- **TypeScript** — Tip güvenli geliştirme +- **Tailwind CSS 4** — Utility-first CSS +- **Google Fonts** — Playfair Display, Inter, Outfit + +## 🚀 Kurulum ```bash +# Bağımlılıkları yükle +npm install + +# Geliştirme sunucusunu başlat npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev + +# Production build +npm run build +npm start ``` -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. +## 📂 Proje Yapısı -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. +``` +lunaqrmenu/ +├── app/ +│ ├── globals.css # Tüm stiller +│ ├── layout.tsx # Root layout & meta +│ └── page.tsx # Ana menü sayfası +├── menu/ +│ └── menu.json # Menü verileri +├── public/ +│ ├── logo.jpg # Yuvarlak logo +│ ├── logo.png # Menü kapak görseli +│ └── logo1.png # Hero logosu +└── package.json +``` -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. +## 📝 Menü Güncelleme -## Learn More +`menu/menu.json` dosyasını düzenleyerek menüyü güncelleyebilirsiniz. Desteklenen fiyat formatları: -To learn more about Next.js, take a look at the following resources: +```json +// Basit fiyat +"price": "590 tl" -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. +// Tek/Dbl fiyat +"price": { "single": "370 tl", "double": "560 tl" } -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! +// Kadeh/Şişe fiyat +"price": { "glass": "240 tl", "bottle": "1200 tl" } +``` -## Deploy on Vercel +## 📱 QR Kod -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. +Sitenizi yayınladıktan sonra URL'den QR kod oluşturarak masalara yerleştirebilirsiniz. -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. +--- + +**Luna Cocktail & More** ☽ *Follow us [@lunacocktaill](https://instagram.com/lunacocktaill)* diff --git a/app/globals.css b/app/globals.css index a2dc41e..4cb043e 100644 --- a/app/globals.css +++ b/app/globals.css @@ -1,10 +1,5 @@ @import "tailwindcss"; -:root { - --background: #ffffff; - --foreground: #171717; -} - @theme inline { --color-background: var(--background); --color-foreground: var(--foreground); @@ -12,15 +7,655 @@ --font-mono: var(--font-geist-mono); } -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } +:root { + --background: #0a0a0f; + --foreground: #e8e4dc; + --gold: #c9a96e; + --gold-light: #dfc594; + --gold-dark: #a68544; + --surface: #121218; + --surface-elevated: #1a1a24; + --border-subtle: rgba(201, 169, 110, 0.12); + --border-glow: rgba(201, 169, 110, 0.25); + --text-secondary: #8a8690; + --text-muted: #5a5660; + --accent-purple: #7c5cbf; + --accent-rose: #b44a65; + --accent-teal: #4a9b8e; +} + +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +html { + scroll-behavior: smooth; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } body { background: var(--background); color: var(--foreground); - font-family: Arial, Helvetica, sans-serif; + font-family: 'Inter', sans-serif; + min-height: 100vh; + overflow-x: hidden; } + +/* ===== SCROLLBAR ===== */ +::-webkit-scrollbar { + width: 6px; +} + +::-webkit-scrollbar-track { + background: var(--background); +} + +::-webkit-scrollbar-thumb { + background: var(--gold-dark); + border-radius: 3px; +} + +::-webkit-scrollbar-thumb:hover { + background: var(--gold); +} + +/* ===== HERO ===== */ +.hero { + position: relative; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 100%; + min-height: 100vh; + min-height: 100dvh; + padding: 2rem 1rem; + text-align: center; + overflow: hidden; +} + +.hero::before { + content: ''; + position: absolute; + inset: 0; + background: + radial-gradient(ellipse 600px 400px at 50% 30%, rgba(201, 169, 110, 0.06) 0%, transparent 70%), + radial-gradient(ellipse 400px 300px at 20% 80%, rgba(124, 92, 191, 0.04) 0%, transparent 70%), + radial-gradient(ellipse 400px 300px at 80% 70%, rgba(180, 74, 101, 0.04) 0%, transparent 70%); + pointer-events: none; +} + +.hero-moon { + position: absolute; + top: 8%; + right: 15%; + width: 120px; + height: 120px; + border-radius: 50%; + background: radial-gradient(circle at 35% 35%, rgba(201, 169, 110, 0.15), rgba(201, 169, 110, 0.03)); + box-shadow: + 0 0 60px rgba(201, 169, 110, 0.08), + 0 0 120px rgba(201, 169, 110, 0.04); + animation: moonPulse 6s ease-in-out infinite; + pointer-events: none; +} + +@keyframes moonPulse { + + 0%, + 100% { + opacity: 0.6; + transform: scale(1); + } + + 50% { + opacity: 1; + transform: scale(1.05); + } +} + +.hero-stars { + position: absolute; + inset: 0; + pointer-events: none; + overflow: hidden; +} + +.star { + position: absolute; + width: 2px; + height: 2px; + background: var(--gold-light); + border-radius: 50%; + animation: twinkle var(--duration) ease-in-out infinite; + opacity: 0; +} + +@keyframes twinkle { + + 0%, + 100% { + opacity: 0; + transform: scale(0.5); + } + + 50% { + opacity: var(--max-opacity); + transform: scale(1); + } +} + +.hero-brand { + position: relative; + z-index: 2; + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + animation: fadeSlideUp 1.2s ease-out; +} + +.hero-illustration { + position: absolute; + inset: 0; + display: flex; + align-items: center; + justify-content: center; + z-index: 0; + opacity: 0.04; + pointer-events: none; +} + +.hero-illustration img { + width: auto; + height: 85%; + max-height: 90vh; + object-fit: contain; + filter: invert(1); +} + +.hero-logo { + width: 220px; + height: 220px; + border-radius: 50%; + object-fit: cover; + border: 2px solid rgba(201, 169, 110, 0.2); + box-shadow: + 0 0 40px rgba(201, 169, 110, 0.1), + 0 0 80px rgba(201, 169, 110, 0.05); + filter: invert(1); + transition: transform 0.4s ease, box-shadow 0.4s ease; +} + +.hero-logo:hover { + transform: scale(1.05); + box-shadow: + 0 0 50px rgba(201, 169, 110, 0.15), + 0 0 100px rgba(201, 169, 110, 0.08); +} + +@media (max-width: 480px) { + .hero-logo { + width: 160px; + height: 160px; + } +} + +.hero-title { + font-family: 'Playfair Display', serif; + font-size: clamp(2.8rem, 8vw, 5rem); + font-weight: 500; + line-height: 1.1; + color: #fff; + margin-bottom: 0.5rem; + background: linear-gradient(135deg, #fff 0%, var(--gold-light) 50%, #fff 100%); + background-size: 200% auto; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + animation: shimmerTitle 6s ease-in-out infinite; +} + +@keyframes shimmerTitle { + + 0%, + 100% { + background-position: 0% center; + } + + 50% { + background-position: 200% center; + } +} + +.hero-subtitle { + font-family: 'Inter', sans-serif; + font-size: 0.85rem; + font-weight: 300; + letter-spacing: 0.4em; + color: var(--text-secondary); + margin-top: 0.75rem; +} + +.hero-divider { + width: 60px; + height: 1px; + background: linear-gradient(90deg, transparent, var(--gold), transparent); + margin: 2rem auto; + opacity: 0.6; +} + +.hero-scroll-cta { + position: absolute; + bottom: 2rem; + left: 0; + right: 0; + margin: 0 auto; + width: fit-content; + display: flex; + flex-direction: column; + align-items: center; + gap: 0.75rem; + color: var(--text-muted); + font-size: 0.7rem; + letter-spacing: 0.2em; + animation: fadeSlideUp 1.5s ease-out 0.5s both; + cursor: pointer; + transition: color 0.3s; + text-decoration: none; +} + +.hero-scroll-cta:hover { + color: var(--gold); +} + +.scroll-arrow { + width: 20px; + height: 20px; + border-right: 1px solid var(--gold-dark); + border-bottom: 1px solid var(--gold-dark); + transform: rotate(45deg); + animation: bounceArrow 2s ease-in-out infinite; +} + +@keyframes bounceArrow { + + 0%, + 100% { + transform: rotate(45deg) translate(0, 0); + opacity: 0.4; + } + + 50% { + transform: rotate(45deg) translate(4px, 4px); + opacity: 1; + } +} + +@keyframes fadeSlideUp { + from { + opacity: 0; + transform: translateY(30px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +/* ===== CATEGORY NAVIGATION ===== */ +.category-nav { + position: sticky; + top: 0; + z-index: 100; + background: rgba(10, 10, 15, 0.85); + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + border-bottom: 1px solid var(--border-subtle); + padding: 0; + transition: box-shadow 0.3s; +} + +.category-nav.scrolled { + box-shadow: 0 4px 30px rgba(0, 0, 0, 0.5); +} + +.category-nav-inner { + display: flex; + align-items: center; + gap: 0; + overflow-x: auto; + scrollbar-width: none; + -ms-overflow-style: none; + padding: 0 1rem; + max-width: 900px; + margin: 0 auto; +} + +.category-nav-inner::-webkit-scrollbar { + display: none; +} + +.category-nav-btn { + flex-shrink: 0; + padding: 1rem 1.25rem; + font-family: 'Inter', sans-serif; + font-size: 0.7rem; + font-weight: 500; + letter-spacing: 0.15em; + color: var(--text-muted); + background: none; + border: none; + cursor: pointer; + transition: color 0.3s, border-color 0.3s; + border-bottom: 2px solid transparent; + white-space: nowrap; + position: relative; +} + +.category-nav-btn:hover { + color: var(--foreground); +} + +.category-nav-btn.active { + color: var(--gold); + border-bottom-color: var(--gold); +} + +/* ===== MENU SECTION ===== */ +.menu-container { + max-width: 800px; + margin: 0 auto; + padding: 0 1.5rem 4rem; +} + +.category-section { + padding-top: 3rem; + margin-bottom: 2rem; + animation: fadeIn 0.6s ease-out; +} + +@keyframes fadeIn { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +.category-header { + text-align: center; + margin-bottom: 2.5rem; + position: relative; +} + +.category-title { + font-family: 'Playfair Display', serif; + font-size: clamp(1.6rem, 4vw, 2.2rem); + font-weight: 500; + color: #fff; + letter-spacing: 0.05em; + position: relative; + display: inline-block; +} + +.category-title::after { + content: ''; + display: block; + width: 40px; + height: 1px; + background: var(--gold); + margin: 0.75rem auto 0; + opacity: 0.5; +} + +.category-item-count { + font-family: 'Inter', sans-serif; + font-size: 0.7rem; + font-weight: 400; + color: var(--text-muted); + letter-spacing: 0.15em; + margin-top: 0.5rem; +} + +/* ===== MENU ITEMS ===== */ +.menu-items { + display: flex; + flex-direction: column; + gap: 0; +} + +.menu-item { + display: flex; + align-items: flex-start; + justify-content: space-between; + padding: 1.25rem 0; + border-bottom: 1px solid var(--border-subtle); + transition: background 0.3s, border-color 0.3s; + gap: 1rem; +} + +.menu-item:last-child { + border-bottom: none; +} + +.menu-item:hover { + border-color: var(--border-glow); +} + +.item-info { + flex: 1; + min-width: 0; +} + +.item-name { + font-family: 'Outfit', sans-serif; + font-size: 1.05rem; + font-weight: 500; + color: #fff; + margin-bottom: 0.3rem; + transition: color 0.3s; +} + +.menu-item:hover .item-name { + color: var(--gold-light); +} + +.item-meta { + display: flex; + flex-direction: column; + gap: 0.2rem; +} + +.item-ingredients { + font-family: 'Inter', sans-serif; + font-size: 0.78rem; + font-weight: 300; + color: var(--text-secondary); + line-height: 1.5; +} + +.item-taste-profile { + display: inline-flex; + flex-wrap: wrap; + gap: 0.35rem; + margin-top: 0.3rem; +} + +.taste-tag { + font-family: 'Inter', sans-serif; + font-size: 0.65rem; + font-weight: 500; + letter-spacing: 0.08em; + padding: 0.2rem 0.55rem; + border-radius: 100px; + background: rgba(201, 169, 110, 0.08); + color: var(--gold); + border: 1px solid rgba(201, 169, 110, 0.15); +} + +.item-grape { + font-family: 'Inter', sans-serif; + font-size: 0.75rem; + font-weight: 400; + color: var(--accent-purple); + font-style: italic; + opacity: 0.85; +} + +.item-price-area { + flex-shrink: 0; + display: flex; + flex-direction: column; + align-items: flex-end; + gap: 0.2rem; +} + +.item-price { + font-family: 'Outfit', sans-serif; + font-size: 1rem; + font-weight: 600; + color: var(--gold); + white-space: nowrap; +} + +.item-price-multi { + display: flex; + flex-direction: column; + align-items: flex-end; + gap: 0.15rem; +} + +.price-label { + font-family: 'Inter', sans-serif; + font-size: 0.65rem; + font-weight: 400; + letter-spacing: 0.1em; + color: var(--text-muted); +} + +.price-row { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.price-row .item-price { + font-size: 0.9rem; +} + +/* ===== FOOTER ===== */ +.menu-footer { + text-align: center; + padding: 3rem 1.5rem 2rem; + border-top: 1px solid var(--border-subtle); + max-width: 600px; + margin: 0 auto; +} + +.footer-note { + font-family: 'Inter', sans-serif; + font-size: 0.78rem; + font-weight: 300; + color: var(--text-muted); + line-height: 1.7; + font-style: italic; +} + +.footer-brand { + margin-top: 2rem; + font-family: 'Playfair Display', serif; + font-size: 1rem; + color: var(--gold-dark); + opacity: 0.5; + letter-spacing: 0.1em; +} + +/* ===== ANIMATIONS ===== */ +.reveal { + opacity: 0; + transform: translateY(20px); + transition: opacity 0.6s ease-out, transform 0.6s ease-out; +} + +.reveal.visible { + opacity: 1; + transform: translateY(0); +} + +/* ===== RESPONSIVE ===== */ +@media (max-width: 480px) { + .hero-moon { + width: 80px; + height: 80px; + top: 12%; + right: 10%; + } + + .category-nav-btn { + padding: 0.85rem 1rem; + font-size: 0.65rem; + } + + .menu-container { + padding: 0 1rem 3rem; + } + + .menu-item { + padding: 1rem 0; + } + + .item-name { + font-size: 0.95rem; + } + + .item-price { + font-size: 0.9rem; + } +} + +/* ===== BACK TO TOP ===== */ +.back-to-top { + position: fixed; + bottom: 2rem; + right: 2rem; + width: 44px; + height: 44px; + border-radius: 50%; + background: rgba(201, 169, 110, 0.12); + border: 1px solid rgba(201, 169, 110, 0.2); + color: var(--gold); + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + opacity: 0; + visibility: hidden; + transform: translateY(10px); + transition: all 0.3s ease; + z-index: 50; + backdrop-filter: blur(10px); +} + +.back-to-top.visible { + opacity: 1; + visibility: visible; + transform: translateY(0); +} + +.back-to-top:hover { + background: rgba(201, 169, 110, 0.2); + border-color: var(--gold); + transform: translateY(-2px); +} + +.back-to-top svg { + width: 18px; + height: 18px; +} \ No newline at end of file diff --git a/app/layout.tsx b/app/layout.tsx index 976eb90..91cebcb 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,20 +1,16 @@ import type { Metadata } from "next"; -import { Geist, Geist_Mono } from "next/font/google"; import "./globals.css"; -const geistSans = Geist({ - variable: "--font-geist-sans", - subsets: ["latin"], -}); - -const geistMono = Geist_Mono({ - variable: "--font-geist-mono", - subsets: ["latin"], -}); - export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "Luna Cocktail & More | Menü", + description: + "Luna Cocktail and More - Özel kokteyllerimiz, şaraplarımız ve daha fazlası. QR menü ile keşfedin.", + keywords: "cocktail, kokteyl, bar, menü, luna, drinks", + openGraph: { + title: "Luna Cocktail & More | Menü", + description: "Özel kokteyllerimiz, şaraplarımız ve daha fazlası.", + type: "website", + }, }; export default function RootLayout({ @@ -23,11 +19,20 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - - {children} + + + + + + + {children} ); } diff --git a/app/page.tsx b/app/page.tsx index 3f36f7c..e3f40a0 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,65 +1,324 @@ -import Image from "next/image"; +"use client"; + +import { useEffect, useState, useRef, useCallback } from "react"; +import Image from "next/image"; +import menuData from "../menu/menu.json"; + +/* ────── Helpers ────── */ +interface MenuItem { + name: string; + ingredients?: string; + taste_profile?: string; + grape_variety?: string; + price: + | string + | { single?: string; double?: string; glass?: string; bottle?: string }; +} + +interface Category { + id: string; + title: string; + items: MenuItem[]; +} + +interface MenuData { + restaurant_name: string; + footer_note: string; + categories: Category[]; +} + +const data = menuData as MenuData; + +/* ────── Stars component ────── */ +interface Star { + id: number; + left: string; + top: string; + duration: string; + delay: string; + maxOpacity: number; +} + +function HeroStars() { + const [stars, setStars] = useState([]); + + useEffect(() => { + setStars( + Array.from({ length: 40 }, (_, i) => ({ + id: i, + left: `${Math.random() * 100}%`, + top: `${Math.random() * 100}%`, + duration: `${3 + Math.random() * 4}s`, + delay: `${Math.random() * 5}s`, + maxOpacity: 0.3 + Math.random() * 0.5, + })) + ); + }, []); -export default function Home() { return ( -
-
- Next.js logo + {stars.map((s) => ( + -
-

- To get started, edit the page.tsx file. -

-

- Looking for a starting point or more instructions? Head over to{" "} - - Templates - {" "} - or the{" "} - - Learning - {" "} - center. -

-
-
- - Vercel logomark - Deploy Now - - - Documentation - -
-
+ ))}
); } + +/* ────── Price renderer ────── */ +function PriceDisplay({ price }: { price: MenuItem["price"] }) { + if (typeof price === "string") { + return {price}; + } + + const entries: [string, string][] = []; + if (price.single) entries.push(["Tek", price.single]); + if (price.double) entries.push(["Dbl", price.double]); + if (price.glass) entries.push(["Kadeh", price.glass]); + if (price.bottle) entries.push(["Şişe", price.bottle]); + + return ( +
+ {entries.map(([label, val]) => ( +
+ {label} + {val} +
+ ))} +
+ ); +} + +/* ────── Category Icon (decorative) ────── */ +function getCategoryIcon(id: string): string { + const icons: Record = { + classic_cocktails: "🍸", + lunas_cocktails: "🌙", + shots: "🥃", + gin: "🫒", + whiskey: "🥂", + rum: "🏴‍☠️", + tequila: "🌵", + vodka: "🧊", + cognac: "🍷", + red_wine: "🍷", + white_wine: "🥂", + roze_blush: "🌸", + champagne_prosecco: "🍾", + draft_beer: "🍺", + bottle_beer: "🍻", + coffee: "☕", + soft_drinks: "🧃", + snacks: "🥜", + }; + return icons[id] || "✦"; +} + +/* ────── Main Page ────── */ +export default function MenuPage() { + const [activeCategory, setActiveCategory] = useState( + data.categories[0]?.id || "" + ); + const [showBackToTop, setShowBackToTop] = useState(false); + const navRef = useRef(null); + const sectionRefs = useRef>(new Map()); + + /* Intersection observer to update active category */ + useEffect(() => { + const observer = new IntersectionObserver( + (entries) => { + const visible = entries + .filter((e) => e.isIntersecting) + .sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top); + if (visible.length > 0) { + const id = visible[0].target.getAttribute("data-category-id"); + if (id) setActiveCategory(id); + } + }, + { rootMargin: "-50% 0px -50% 0px", threshold: 0 } + ); + + sectionRefs.current.forEach((el) => observer.observe(el)); + return () => observer.disconnect(); + }, []); + + /* Back-to-top visibility */ + useEffect(() => { + const onScroll = () => setShowBackToTop(window.scrollY > 600); + window.addEventListener("scroll", onScroll, { passive: true }); + return () => window.removeEventListener("scroll", onScroll); + }, []); + + /* Scroll nav button into view */ + useEffect(() => { + if (!navRef.current) return; + const btn = navRef.current.querySelector( + `[data-nav-id="${activeCategory}"]` + ); + if (btn) { + btn.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "center" }); + } + }, [activeCategory]); + + const scrollToCategory = useCallback((id: string) => { + const el = sectionRefs.current.get(id); + if (el) { + const offset = 56; + const y = el.getBoundingClientRect().top + window.scrollY - offset; + window.scrollTo({ top: y, behavior: "smooth" }); + } + }, []); + + const setSectionRef = useCallback( + (id: string) => (el: HTMLElement | null) => { + if (el) sectionRefs.current.set(id, el); + }, + [] + ); + + return ( + <> + {/* ───── HERO ───── */} +
+ +
+ + {/* ───── CATEGORY NAV ───── */} + + + {/* ───── MENU CONTENT ───── */} +
+ {data.categories.map((cat) => ( +
+
+

+ + {getCategoryIcon(cat.id)} + + {cat.title} +

+

+ {cat.items.length} ÜRÜN +

+
+ +
+ {cat.items.map((item, idx) => ( +
+
+

{item.name}

+
+ {item.grape_variety && ( + {item.grape_variety} + )} + {item.ingredients && ( + + {item.ingredients} + + )} + {item.taste_profile && ( +
+ {item.taste_profile.split("-").map((t, i) => ( + + {t.trim()} + + ))} +
+ )} +
+
+
+ +
+
+ ))} +
+
+ ))} +
+ + {/* ───── FOOTER ───── */} +
+

{data.footer_note}

+

LUNA ✦

+
+ + {/* ───── BACK TO TOP ───── */} + + + ); +} diff --git a/menu/menu.json b/menu/menu.json new file mode 100644 index 0000000..94f4f33 --- /dev/null +++ b/menu/menu.json @@ -0,0 +1,765 @@ +{ + "restaurant_name": "LUNA COCKTAIL AND MORE", + "footer_note": "Alerjen bilgisi, ürün içeriği bilgisi ve içecekler hakkında bilgi almak için barmenimize danışabilirsiniz.", + "categories": [ + { + "id": "classic_cocktails", + "title": "Classic Cocktails", + "items": [ + { + "name": "Mojito", + "ingredients": "Havana Club 3 Rom", + "price": "590 tl" + }, + { + "name": "Negroni", + "ingredients": "Beefeater Gin-Garrone Rosso-Campari", + "price": "590 tl" + }, + { + "name": "Margarita", + "ingredients": "Olmeca Tekila-Garrone Triple Sec", + "price": "590 tl" + }, + { + "name": "Martini", + "ingredients": "Beefeater Gin-Garrone Vermut", + "price": "590 tl" + }, + { + "name": "Espresso Martini", + "ingredients": "Absolut Votka-Espresso", + "price": "590 tl" + }, + { + "name": "Aperol Spritz", + "ingredients": "Aperol-Prossecco", + "price": "590 tl" + }, + { + "name": "Long Island Iced Tea", + "ingredients": "Absolut Votka-Beefeater Gin-Olmeca Tekila-Havana Club 3 Rom-Garrone Triple Sec", + "price": "590 tl" + }, + { + "name": "Lynchburg Lemonade", + "ingredients": "Jack Daniel's Viski-Garrone Triple Sec", + "price": "590 tl" + }, + { + "name": "Gin Fizz", + "ingredients": "Beefeater Gin", + "price": "590 tl" + }, + { + "name": "Amaretto Sour", + "ingredients": "Bourbon Viski-Acıbadem Likörü", + "price": "590 tl" + } + ] + }, + { + "id": "lunas_cocktails", + "title": "Luna's Cocktails", + "items": [ + { + "name": "Fruit Freedom", + "taste_profile": "Tatlı-Ekşi-Meyvemsi", + "ingredients": "Beefeater Gin-Tropikal Meyve Likörü-Prosecco", + "price": "590 tl" + }, + { + "name": "Commandante", + "taste_profile": "Sert-Baharatlı-Ekşi", + "ingredients": "Chivas Regal Viski-Mürver Çiçeği Likörü", + "price": "590 tl" + }, + { + "name": "Elderflo", + "taste_profile": "Hafif-Ekşi-Tatlı", + "ingredients": "Havana Club 3 Rom-Mürver Çiçeği Likörü-Frenk Üzümü Likörü", + "price": "590 tl" + }, + { + "name": "Thomas More", + "taste_profile": "Ekşi-Tatlı-Baharatlı", + "ingredients": "Tuzlu Karamelli Votka-Baharatlı Zencefilli Tonik", + "price": "590 tl" + }, + { + "name": "Yellow Passion", + "taste_profile": "Ekşi-Tropikal", + "ingredients": "Havana Club 3 Rom-Tropikal Meyve Likörü", + "price": "590 tl" + }, + { + "name": "Archie's Way", + "taste_profile": "Tatlı-Meyvemsi", + "ingredients": "Havana Club Rom-Krema Likörü-Şeftali likörü", + "price": "590 tl" + }, + { + "name": "Creme de Martini", + "taste_profile": "Tatlı-Kahveli", + "ingredients": "Havana Club 3 Rom-Krema Likörü-Garrone Triple Sec", + "price": "590 tl" + }, + { + "name": "Patronus", + "taste_profile": "Sert-Tatlı", + "ingredients": "Jagermeister-Hindistan Cevizi Likörü", + "price": "590 tl" + }, + { + "name": "Sakura Candy", + "taste_profile": "Tatlı-Ekşi-Baharatlı", + "ingredients": "Beefeater Gin-Kavun Likörü", + "price": "590 tl" + }, + { + "name": "Red Dragonite", + "taste_profile": "Tatlı-Ekşi-Sert-Meyvemsi", + "ingredients": "Beefeater Gin-Absolut Mandrin", + "price": "590 tl" + }, + { + "name": "Green Goblin", + "taste_profile": "Ekşi-Tatlı-Meyvemsi-Baharatlı", + "ingredients": "Beefeater Gin-Ekşi Elma Likörü", + "price": "590 tl" + }, + { + "name": "Wiseberry", + "taste_profile": "Sert-Meyvemsi-Tatlı-Ekşi", + "ingredients": "Beefeater Gin-Absolut Raspberri", + "price": "590 tl" + }, + { + "name": "Vega", + "taste_profile": "Meyvemsi-Ferah-Baharatlı", + "ingredients": "Beefeater Gin-Absolut Pears", + "price": "590 tl" + }, + { + "name": "Illusion", + "taste_profile": "Tatlı-İsli-Acı", + "ingredients": "Jameson Whiskey-Tropikal Meyve Likörü", + "price": "590 tl" + }, + { + "name": "Saturn", + "taste_profile": "Ekşi-Sert-Baharatlı", + "ingredients": "Şerbetli Beefeater Gin-Absolut Lime", + "price": "590 tl" + } + ] + }, + { + "id": "shots", + "title": "Shots", + "items": [ + { + "name": "Avion Silver", + "price": "380 tl" + }, + { + "name": "Jagermeister", + "price": "330 tl" + }, + { + "name": "Nebula-e", + "price": "350 tl" + }, + { + "name": "Sambuca", + "price": "390 tl" + }, + { + "name": "B-52", + "price": "390 tl" + }, + { + "name": "BM2", + "price": "390 tl" + } + ] + }, + { + "id": "gin", + "title": "Gin", + "items": [ + { + "name": "Beefeater", + "price": "310 tl" + }, + { + "name": "Beefeater Pink", + "price": "310 tl" + }, + { + "name": "Beefeater Blood Orange", + "price": "310 tl" + }, + { + "name": "Malfy Originale", + "price": "350 tl" + }, + { + "name": "Malfy Gin Rose", + "price": "350 tl" + }, + { + "name": "Malfy Gin Limone", + "price": "350 tl" + }, + { + "name": "Monkey 47 Dry", + "price": "630 tl" + }, + { + "name": "Monkey 47 Sloe Gin", + "price": "530 tl" + } + ] + }, + { + "id": "whiskey", + "title": "Whiskey", + "items": [ + { + "name": "Chivas Regal 12", + "price": { + "single": "370 tl", + "double": "560 tl" + } + }, + { + "name": "Chivas Smoky", + "price": { + "single": "450 tl", + "double": "620 tl" + } + }, + { + "name": "Chivas Regal 15", + "price": { + "single": "590 tl", + "double": "880 tl" + } + }, + { + "name": "Chivas Regal 18", + "price": { + "single": "840 tl", + "double": "1330 tl" + } + }, + { + "name": "Jameson", + "price": { + "single": "350 tl", + "double": "490 tl" + } + }, + { + "name": "Jameson Black Barrel", + "price": { + "single": "490 tl", + "double": "630 tl" + } + }, + { + "name": "Jameson Caskmates", + "price": { + "single": "460 tl", + "double": "600 tl" + } + }, + { + "name": "Aberlour 12", + "price": { + "single": "660 tl", + "double": "980 tl" + } + }, + { + "name": "Aberlour 14", + "price": { + "single": "840 tl", + "double": "1330 tl" + } + }, + { + "name": "The Glenlivet Founder's Reserve", + "price": { + "single": "490 tl", + "double": "650 tl" + } + }, + { + "name": "The Glenlivet Caribbean Reserve", + "price": { + "single": "520 tl", + "double": "740 tl" + } + }, + { + "name": "The Glenlivet 12", + "price": { + "single": "670 tl", + "double": "950 tl" + } + }, + { + "name": "Jack Daniel's", + "price": { + "single": "370 tl", + "double": "500 tl" + } + }, + { + "name": "Gentleman Jack", + "price": { + "single": "390 tl", + "double": "530 tl" + } + }, + { + "name": "Woodford Reserve", + "price": { + "single": "630 tl", + "double": "910 tl" + } + }, + { + "name": "Woodford Reserve Rye", + "price": { + "single": "710 tl", + "double": "1090 tl" + } + } + ] + }, + { + "id": "rum", + "title": "Rom", + "items": [ + { + "name": "Havana Club 3 Anos", + "price": "320 tl" + }, + { + "name": "Havana Club 7 Anos", + "price": "420 tl" + }, + { + "name": "Bumbu", + "price": "420 tl" + } + ] + }, + { + "id": "tequila", + "title": "Tequila", + "items": [ + { + "name": "Olmeca Silver", + "price": "220 tl" + }, + { + "name": "Olmeca Gold", + "price": "220 tl" + }, + { + "name": "Olmeca Altos Plato", + "price": "310 tl" + }, + { + "name": "Olmeca Altos Reposado", + "price": "320 tl" + }, + { + "name": "Avion Silver", + "price": "440 tl" + } + ] + }, + { + "id": "vodka", + "title": "Vodka", + "items": [ + { + "name": "Absolut Blue", + "price": "280 tl" + }, + { + "name": "Absolut Mandrin", + "price": "280 tl" + }, + { + "name": "Absolut Pears", + "price": "280 tl" + }, + { + "name": "Absolut Lime", + "price": "280 tl" + }, + { + "name": "Absolut Raspberri", + "price": "280 tl" + }, + { + "name": "Absolut Vanilla", + "price": "280 tl" + }, + { + "name": "Absolut Citron", + "price": "280 tl" + }, + { + "name": "Absolut Elyx", + "price": "410 tl" + } + ] + }, + { + "id": "cognac", + "title": "Cognac", + "items": [ + { + "name": "Martell VS", + "price": { + "single": "770 tl", + "double": "1000 tl" + } + }, + { + "name": "Martell VSOP", + "price": { + "single": "1000 tl", + "double": "1300 tl" + } + } + ] + }, + { + "id": "red_wine", + "title": "Red Wine", + "items": [ + { + "name": "Likya Patara", + "grape_variety": "Öküzgözü-Kalecik Karası-Syrah", + "price": { + "glass": "240 tl", + "bottle": "1200 tl" + } + }, + { + "name": "Likya Kızılbel", + "grape_variety": "Merlot-Syrah-Öküzgözü", + "price": { + "bottle": "2100 tl" + } + }, + { + "name": "Likya Kızılbel", + "grape_variety": "Cabarnet Sauvignon-Boğazkere", + "price": { + "bottle": "2100 tl" + } + }, + { + "name": "Likya Arkeo", + "grape_variety": "Merzifon Karası", + "price": { + "bottle": "3200 tl" + } + } + ] + }, + { + "id": "white_wine", + "title": "White Wine", + "items": [ + { + "name": "Likya Patara", + "grape_variety": "Chardonnay-Çalıbağ", + "price": { + "glass": "240 tl", + "bottle": "1200 tl" + } + }, + { + "name": "Likya Arykanda", + "grape_variety": "Sauvignon Blanc", + "price": { + "bottle": "2200 tl" + } + }, + { + "name": "Likya Vineyard", + "grape_variety": "Chardonnay", + "price": { + "bottle": "3200 tl" + } + } + ] + }, + { + "id": "roze_blush", + "title": "Roze & Blush", + "items": [ + { + "name": "Likya Patara", + "grape_variety": "Tilkikuyruğu-Öküzgözü", + "price": { + "glass": "240 tl", + "bottle": "1200 tl" + } + }, + { + "name": "Likya Araxa / Pinot Meunier", + "price": { + "bottle": "3200 tl" + } + } + ] + }, + { + "id": "champagne_prosecco", + "title": "Champagne ve Prosecco", + "items": [ + { + "name": "Garrone Prosecco", + "price": "4200 tl" + }, + { + "name": "Luc Belair", + "price": "5900 tl" + } + ] + }, + { + "id": "draft_beer", + "title": "Draft Beer", + "items": [ + { + "name": "Carlsberg 50 cl", + "price": "210 tl" + }, + { + "name": "Carlsberg 33 cl", + "price": "180 tl" + } + ] + }, + { + "id": "bottle_beer", + "title": "Bottle Beer", + "items": [ + { + "name": "Tuborg 50 cl", + "price": "210 tl" + }, + { + "name": "Carlsberg 50 cl", + "price": "220 tl" + }, + { + "name": "Carlsberg Luna 50 cl", + "price": "240 tl" + }, + { + "name": "Tuborg Filtresiz 50 cl", + "price": "230 tl" + }, + { + "name": "Tuborg Amber 50 cl", + "price": "230 tl" + }, + { + "name": "Tuborg Ice 33 cl Şişe", + "price": "200 tl" + }, + { + "name": "Frederik Serisi 33 cl", + "price": "230 tl" + }, + { + "name": "Blanc 33 cl", + "price": "220 tl" + }, + { + "name": "Weihenstephan 33 cl", + "price": "250 tl" + }, + { + "name": "Sol 33 cl", + "price": "240 tl" + }, + { + "name": "Desperados 33 cl", + "price": "250 tl" + }, + { + "name": "Grimbergen 33 cl", + "price": "280 tl" + } + ] + }, + { + "id": "coffee", + "title": "Coffee", + "items": [ + { + "name": "Espresso", + "price": "150 tl" + }, + { + "name": "Americano", + "price": "220 tl" + }, + { + "name": "Caffe Latte", + "price": "270 tl" + }, + { + "name": "Cappuccino", + "price": "270 tl" + }, + { + "name": "Flat White", + "price": "290 tl" + }, + { + "name": "Cortado", + "price": "240 tl" + }, + { + "name": "Iced Americano", + "price": "240 tl" + }, + { + "name": "Iced Latte", + "price": "290 tl" + } + ] + }, + { + "id": "soft_drinks", + "title": "Soft Drinks", + "items": [ + { + "name": "Su", + "price": "70 tl" + }, + { + "name": "Soda", + "price": "110 tl" + }, + { + "name": "Churchill", + "price": "170 tl" + }, + { + "name": "Coca Cola", + "price": "140 tl" + }, + { + "name": "Coca Cola Zero", + "price": "140 tl" + }, + { + "name": "Fanta", + "price": "140 tl" + }, + { + "name": "Sprite", + "price": "140 tl" + }, + { + "name": "Fuse Tea Şeftali", + "price": "140 tl" + }, + { + "name": "Fuse Tea Mango", + "price": "140 tl" + }, + { + "name": "Fuse Tea Limon", + "price": "140 tl" + }, + { + "name": "Cappy Şeftali Suyu", + "price": "140 tl" + }, + { + "name": "Cappy Vişne Suyu", + "price": "140 tl" + }, + { + "name": "Cappy Karışık Meyve Suyu", + "price": "140 tl" + }, + { + "name": "Redbull ve Çeşitleri", + "price": "230 tl" + }, + { + "name": "Limonata", + "price": "250 tl" + }, + { + "name": "Portakal Suyu", + "price": "250 tl" + }, + { + "name": "Tonic", + "price": "150 tl" + } + ] + }, + { + "id": "snacks", + "title": "Snacks", + "items": [ + { + "name": "Karışık Kuruyemiş", + "price": "310 tl" + }, + { + "name": "Çiğ Badem", + "price": "280 tl" + }, + { + "name": "Kavrulmuş Badem", + "price": "280 tl" + }, + { + "name": "Antep Fıstığı", + "price": "280 tl" + }, + { + "name": "Fındık", + "price": "280 tl" + }, + { + "name": "Kaju", + "price": "280 tl" + }, + { + "name": "Tuzlu Fıstık", + "price": "250 tl" + }, + { + "name": "Meyve Tabağı", + "price": "400 tl" + }, + { + "name": "Peynir Tabağı", + "price": "800 tl" + } + ] + } + ] +} \ No newline at end of file diff --git a/public/logo.jpg b/public/logo.jpg new file mode 100644 index 0000000..7252e12 Binary files /dev/null and b/public/logo.jpg differ diff --git a/public/logo.png b/public/logo.png new file mode 100644 index 0000000..c27931d Binary files /dev/null and b/public/logo.png differ diff --git a/public/logo1.png b/public/logo1.png new file mode 100644 index 0000000..ea56dfe Binary files /dev/null and b/public/logo1.png differ