22d7326ac3
- Added concise English descriptions to every item in lib/menu-data.ts (street food, meat, chicken, pizza, rolls, sweets, drinks, etc.). - Expanded Swedish (and fallback) translations in lib/translations.ts under menuDescriptions and signatureMenuItems so descriptions are properly localized when language is switched (names remain unchanged). - This fixes missing descriptions on the /menu page and homepage signature menu. - Descriptions sourced from authentic Indian/Pakistani cuisine references.
206 lines
14 KiB
TypeScript
206 lines
14 KiB
TypeScript
/**
|
||
* =============================================================================
|
||
* CENTRAL MENU DATA — Shahi Kitchen
|
||
* =============================================================================
|
||
*
|
||
* This is the SINGLE SOURCE OF TRUTH for every dish shown on the website.
|
||
*
|
||
* WHY THIS FILE EXISTS:
|
||
* - Keeps menu content decoupled from UI components (easy for restaurant staff
|
||
* or future devs to update prices/descriptions without touching React code)
|
||
* - Powers BOTH the public menu page AND the cart system
|
||
* - Enables future features: search, filters, online ordering, admin CMS, etc.
|
||
*
|
||
* DATA MODEL:
|
||
* - MenuCategory: A logical section (Street Food, Vegetarian, Chicken, Sweets...)
|
||
* - MenuItem: One dish
|
||
* id → stable unique key (used in cart, URLs, analytics). NEVER change.
|
||
* name → displayed title
|
||
* price → integer in Swedish Krona (kr). No decimals in current design.
|
||
* description → optional rich text shown under the name
|
||
* image → filename inside /public/images/dishes/ (fallback when no video)
|
||
* video → filename inside /public/videos/ (MP4 or WebM)
|
||
* The menu page automatically looks for a matching
|
||
* `-poster.jpg` first frame in /public/images/dishes/
|
||
* isVegetarian → boolean flag. Powers the green "VEGETARIAN" pill + filter toggle
|
||
*
|
||
* VIDEO + POSTER CONTRACT (critical):
|
||
* When `video: "butter-chicken-steam.mp4"` exists:
|
||
* 1. The card shows the static poster image first (performance + first-frame accuracy)
|
||
* 2. On hover the actual video plays (only while hovering)
|
||
* 3. On mouse leave → video pauses + resets to time 0
|
||
* Poster lookup order (see menu/page.tsx for the exact fallback logic):
|
||
* butter-chicken-steam-poster.jpg
|
||
* butter-chicken-steam-optimized-poster.jpg
|
||
* (and a few legacy variants for safety)
|
||
*
|
||
* HOW TO ADD A NEW DISH (future-proof instructions):
|
||
* 1. Add a high-quality image to /public/images/dishes/your-dish.jpg
|
||
* 2. (Optional but recommended) Generate a short 4–8s video → optimize with ffmpeg
|
||
* and place in /public/videos/your-dish.webm + .mp4
|
||
* 3. Extract first frame as your-dish-poster.jpg (see extract-video-posters.sh)
|
||
* 4. Add the item object below in the correct category
|
||
* 5. If vegetarian → set isVegetarian: true
|
||
* 6. Update price in both places if the restaurant changes pricing
|
||
*
|
||
* IMPORTANT GOTCHAS:
|
||
* - The `id` must be kebab-case and globally unique across all categories.
|
||
* - Price is stored as number (not string) so cart math works.
|
||
* - Do NOT delete items that have already been ordered by real customers
|
||
* (the cart uses the id as primary key).
|
||
*
|
||
* RELATED FILES:
|
||
* - app/menu/page.tsx → consumes this data + adds cart buttons + video hover
|
||
* - components/CartContext.tsx → stores references by id + name + price
|
||
*/
|
||
|
||
export type MenuItem = {
|
||
id: string;
|
||
name: string;
|
||
description?: string;
|
||
price: number;
|
||
image?: string; // filename from /public/images/dishes/
|
||
video?: string; // filename from /public/videos/ (for animated dishes)
|
||
isVegetarian?: boolean;
|
||
};
|
||
|
||
export type MenuCategory = {
|
||
id: string;
|
||
name: string;
|
||
items: MenuItem[];
|
||
};
|
||
|
||
/**
|
||
* THE ACTUAL MENU DATA
|
||
*
|
||
* Categories are rendered in the exact order they appear here on /menu.
|
||
* Each category has a stable `id` used for:
|
||
* - URL hash navigation (#street-food)
|
||
* - IntersectionObserver active state
|
||
* - Category filter pills (the beautiful sliding gold indicator)
|
||
*
|
||
* Keep descriptions concise (1–2 lines max) — the design is generous but not verbose.
|
||
*/
|
||
export const menuCategories: MenuCategory[] = [
|
||
{
|
||
id: "street-food",
|
||
name: "Street Food & Starters",
|
||
items: [
|
||
{ id: "samosa-aloo", name: "Samosa Aloo Veg", description: "Crispy fried triangular pastries filled with spiced potatoes and peas.", price: 34, image: "aloo-samosa.jpg", video: "samosa-aloo.mp4" },
|
||
{ id: "samosa-keema", name: "Samosa Keema", description: "Flaky pastries stuffed with spiced minced meat filling.", price: 39, image: "keema-samosa.jpg", video: "samosa-keema.mp4" },
|
||
{ id: "samosa-chat", name: "Samosa Chat", description: "Crispy samosas topped with spicy chickpeas, yogurt, chutneys and fresh herbs.", price: 89, image: "samosa-chaat.jpg", video: "samosa-chaat.mp4" },
|
||
{ id: "chana-chat", name: "Chana Chat", description: "Tangy spiced chickpeas mixed with potatoes, onions, tomatoes and chutneys.", price: 69, image: "chana-chaat.jpg", video: "chana-chaat.mp4" },
|
||
{ id: "panipuri", name: "Panipuri / Golgappe", description: "Crispy hollow puris filled with spiced chickpeas and potatoes, served with tangy tamarind water.", price: 69, image: "panipuri.jpg", video: "panipuri.mp4" },
|
||
{ id: "keema-naan-starter", name: "Keema Naan", description: "Soft naan bread stuffed with spiced minced meat, baked until golden.", price: 75, image: "keema-naan.jpg", video: "keema-naan.mp4" },
|
||
],
|
||
},
|
||
{
|
||
id: "vegetarian",
|
||
name: "Vegetarian",
|
||
items: [
|
||
{ id: "palak-paneer", name: "Palak Paneer", description: "Cottage cheese cooked in a creamy spinach gravy with mild spices and aromatic herbs.", price: 139, image: "palak-paneer.jpg", video: "palak-paneer.mp4", isVegetarian: true },
|
||
{ id: "shahi-paneer", name: "Shahi Paneer", description: "Soft cottage cheese in a rich, creamy cashew and tomato gravy with Indian spices.", price: 139, image: "shahi-paneer.jpg", video: "shahi-paneer.mp4", isVegetarian: true },
|
||
{ id: "malai-kofta", name: "Malai Kofta", description: "Soft vegetable koftas simmered in a rich and creamy onion-tomato gravy with mild spices.", price: 139, image: "malai-kofta.jpg", video: "malai-kofta.mp4", isVegetarian: true },
|
||
{ id: "daal-makhani", name: "Daal Makhani", description: "Slow-cooked black lentils in a buttery, creamy tomato gravy with aromatic spices.", price: 139, image: "daal-makhani.jpg", video: "daal-makhani.mp4", isVegetarian: true },
|
||
{ id: "lahore-chana", name: "Lahore Chana", description: "Spiced chickpeas cooked in a tangy onion-tomato gravy with traditional Punjabi spices.", price: 139, image: "lahore-chana.jpg", isVegetarian: true },
|
||
],
|
||
},
|
||
{
|
||
id: "meat",
|
||
name: "Meat",
|
||
items: [
|
||
{ id: "lamm-palak", name: "Lamm Palak", description: "Tender lamb cooked with fresh spinach in a mild, flavorful gravy.", price: 179, image: "lamm-palak.jpg", video: "lamm-palak.mp4" },
|
||
{ id: "lamm-vindaloo", name: "Lamm Vindaloo", description: "Spicy and tangy lamb curry in a vinegar and chili-based sauce.", price: 179, image: "lamm-vindaloo.jpg", video: "lamm-vindaloo.mp4" },
|
||
{ id: "lamm-rogan-josh", name: "Lamm Rogan Josh", description: "Aromatic lamb curry simmered in a rich yogurt and Kashmiri spice gravy.", price: 199, image: "lamm-rogan-josh.jpg", video: "lamm-rogan-josh.mp4" },
|
||
{ id: "lamm-karahi", name: "Lamm Karahi", description: "Lamb pieces stir-fried in a wok with tomatoes, ginger, garlic and spices.", price: 179, image: "lamm-karahi.jpg", video: "lamm-karahi.mp4" },
|
||
{ id: "bong-nihari", name: "Bong Nihari", description: "Slow-cooked beef shank in a rich, aromatic gravy, traditionally served with naan.", price: 199, image: "bong-nihari.jpg", video: "bong-nihari.mp4" },
|
||
{ id: "paye", name: "Paye", description: "Slow-simmered lamb trotters in a thick, spicy and flavorful gravy.", price: 149, image: "paye.jpg", video: "paye.mp4" },
|
||
],
|
||
},
|
||
{
|
||
id: "burger-sandwich",
|
||
name: "Burger & Sandwich",
|
||
items: [
|
||
{ id: "shahi-burger", name: "Shahi Burger", description: "Juicy spiced meat patty in a soft bun with special sauces, lettuce and tomatoes.", price: 119, image: "shahi-burger.jpg", video: "shahi-burger.mp4" },
|
||
{ id: "shami-sandwich", name: "Shami Sandwich Menu", description: "Spiced minced meat shami kebab patties served in bread with chutney and onions.", price: 99, image: "shami-sandwich.jpg", video: "shami-sandwich.mp4" },
|
||
],
|
||
},
|
||
{
|
||
id: "chicken",
|
||
name: "Chicken",
|
||
items: [
|
||
{ id: "chicken-biryani", name: "Chicken Biryani", description: "Fragrant aged basmati rice layered with tender spiced chicken, saffron and caramelized onions.", price: 149, image: "chicken-biryani.jpg", video: "chicken-biryani.mp4" },
|
||
{ id: "chicken-tikka", name: "Chicken Tikka", description: "Boneless chicken pieces marinated in yogurt and spices, grilled in a tandoor.", price: 149, image: "chicken-tikka.jpg", video: "chicken-tikka.mp4" },
|
||
{ id: "tikka-boti", name: "Tikka Boti", description: "Tender chicken chunks marinated in spices and grilled on skewers.", price: 149, image: "chicken-tikka.jpg", video: "tikka-boti.mp4" },
|
||
{ id: "chicken-karahi", name: "Chicken Karahi", description: "Wok-tossed chicken in a robust tomato, chili and ginger gravy.", price: 149, image: "chicken-karahi.jpg", video: "chicken-karahi.mp4" },
|
||
{ id: "lahore-sizzler", name: "Lahore Sizzler", description: "Sizzling platter of marinated chicken with vegetables and spicy sauces.", price: 169, image: "lahore-sizzler.jpg", video: "lahore-sizzler.mp4" },
|
||
{ id: "butter-chicken", name: "Butter Chicken", description: "Tender chicken in a creamy tomato and butter gravy with mild spices.", price: 149, image: "butter-chicken.jpg" },
|
||
{ id: "chicken-haleem", name: "Chicken Haleem", description: "Slow-cooked shredded chicken with lentils, wheat and aromatic spices.", price: 149, image: "chicken-haleem.jpg", video: "chicken-haleem.mp4" },
|
||
],
|
||
},
|
||
{
|
||
id: "pizza",
|
||
name: "Pizza",
|
||
items: [
|
||
{ id: "lahore-pizza", name: "Lahore Pizza", description: "Pizza topped with spiced chicken, onions and special Lahori sauces on a crispy base.", price: 119, image: "lahore-pizza.jpg", video: "lahore-pizza.mp4" },
|
||
{ id: "kebab-pizza", name: "Kebab Pizza", description: "Pizza with minced meat kebab topping, cheese, onions and aromatic spices.", price: 119, image: "kebab-pizza.jpg", video: "kebab-pizza.mp4" },
|
||
{ id: "tikka-boti-pizza", name: "Tikka Boti Pizza", description: "Pizza featuring grilled chicken tikka, cheese, tomatoes and fresh herbs.", price: 119, image: "tikka-boti-pizza.jpg", video: "tikka-boti-pizza.mp4" },
|
||
{ id: "peshawari-pizza", name: "Peshawari Pizza", description: "Naan-style pizza with tender meat, nuts, raisins and Peshawari spices.", price: 119, image: "peshawari-pizza.jpg", video: "peshawari-pizza.mp4" },
|
||
{ id: "veg-pizza", name: "Veg Pizza", description: "Vegetarian pizza loaded with fresh vegetables, cheese and tomato sauce.", price: 109, image: "veg-pizza.jpg", isVegetarian: true },
|
||
],
|
||
},
|
||
{
|
||
id: "naan-roll",
|
||
name: "Naan Roll",
|
||
items: [
|
||
{ id: "tikka-boti-roll", name: "Tikka Boti Roll", description: "Grilled chicken tikka wrapped in soft naan with mint chutney and onions.", price: 99, image: "tikka-boti-roll.jpg", video: "tikka-boti-roll.mp4" },
|
||
{ id: "kebab-roll", name: "Kebab Roll", description: "Spiced minced meat kebab wrapped in naan with chutney, salad and sauces.", price: 99, image: "kebab-roll.jpg", video: "kebab-roll.mp4" },
|
||
{ id: "falafel-roll", name: "Falafel Roll", description: "Crispy falafel wrapped in naan with vegetables, hummus and tangy sauces.", price: 99, image: "falafel-roll.jpg", video: "falafel-roll.mp4", isVegetarian: true },
|
||
{ id: "paneer-roll", name: "Paneer Roll", description: "Grilled paneer cubes wrapped in naan with spices, chutney and fresh vegetables.", price: 99, image: "paneer-roll.jpg", video: "paneer-roll.mp4", isVegetarian: true },
|
||
],
|
||
},
|
||
{
|
||
id: "sweets",
|
||
name: "Sweets / Mithai",
|
||
items: [
|
||
{ id: "namakpare", name: "Namakpare", description: "Crispy, savory fried flour snacks seasoned with carom seeds and salt.", price: 135, image: "namakpare.jpg", video: "namakpare.mp4" },
|
||
{ id: "jalebi", name: "Jalebi", description: "Crispy golden saffron spirals soaked in fragrant sugar syrup.", price: 119, image: "jalebi.jpg", video: "jalebi.mp4" },
|
||
{ id: "gajar-halwa", name: "Gajar Halwa", description: "Sweet carrot pudding cooked slowly with milk, sugar, ghee and nuts.", price: 149, image: "gajar-halwa.jpg", video: "gajar-halwa.mp4" },
|
||
{ id: "rasmalai", name: "Rasmalai", description: "Soft cheese dumplings soaked in chilled sweetened milk with cardamom and saffron.", price: 45, image: "rasmalai.jpg", video: "rasmalai.mp4" },
|
||
{ id: "kulfi", name: "Kulfi", description: "Creamy traditional frozen milk dessert with cardamom, pistachios and saffron.", price: 39, image: "kulfi.jpg", video: "kulfi.mp4" },
|
||
],
|
||
},
|
||
{
|
||
id: "drinks",
|
||
name: "Drinks",
|
||
items: [
|
||
{ id: "masala-chai", name: "Masala Chai", description: "Traditional spiced tea brewed with milk, cardamom, ginger and aromatic spices.", price: 39, image: "masala-chai.jpg" },
|
||
{ id: "mango-lassi", name: "Mango Lassi", description: "Refreshing sweet yogurt drink blended with ripe mango and cardamom.", price: 45, image: "mango-lassi.jpg", video: "mango-lassi.mp4" },
|
||
{ id: "coca-cola", name: "Coca-Cola", description: "Classic chilled cola soft drink.", price: 29 },
|
||
{ id: "pepsi-fanta", name: "Pepsi / Fanta", description: "Refreshing cola or orange flavored carbonated beverage.", price: 29 },
|
||
{ id: "sprite-ramlosa", name: "Sprite / Ramlösa", description: "Crisp lemon-lime soda or sparkling mineral water.", price: 29 },
|
||
{ id: "energy-drink", name: "Energy Drink", description: "Caffeinated beverage for an instant energy boost.", price: 39 },
|
||
{ id: "juice", name: "Juice", description: "Fresh fruit juice, typically mango or other seasonal flavors.", price: 20, image: "mango-juice.jpg" },
|
||
{ id: "coffee", name: "Coffee", description: "Freshly brewed hot coffee.", price: 39, image: "black-coffee.jpg" },
|
||
{ id: "latte", name: "Latte", description: "Espresso coffee with steamed milk and a light layer of foam.", price: 49, image: "latte.jpg", video: "latte.mp4" },
|
||
{ id: "cappuccino", name: "Cappuccino", description: "Espresso topped with steamed milk and thick foam.", price: 49, image: "cappuccino.jpg" },
|
||
{ id: "tea", name: "Tea", description: "Traditional hot black tea, served plain or with milk.", price: 30 },
|
||
],
|
||
},
|
||
];
|
||
|
||
/**
|
||
* UTILITY EXPORT
|
||
*
|
||
* Flattened list of every single menu item across all categories.
|
||
*
|
||
* Current use cases:
|
||
* - Future global search / command palette
|
||
* - Admin tools that need to iterate over everything
|
||
* - Analytics or sitemap generation
|
||
*
|
||
* Example:
|
||
* const butterChicken = allMenuItems.find(i => i.id === "butter-chicken");
|
||
*/
|
||
export const allMenuItems = menuCategories.flatMap((category) => category.items);
|