ResturantApp / app.py
ZaibiShah's picture
Create app.py
7abe619 verified
Raw
History Blame Contribute Delete
29.9 kB
!pip -q install gradio groq pandas
import os
# Paste your key inside quotes:
os.environ["GROQ_API_KEY"] = "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"
import os
import uuid
import time
import pandas as pd
import gradio as gr
from groq import Groq
# -----------------------------
# 1) SAMPLE MENU (with images)
# -----------------------------
def starter_menu():
# NOTE: These are public image URLs for demo. You can replace with your own.
return [
{
"id": "PZ001",
"name": "Pepperoni Pizza",
"category": "Pizza",
"price": 1299,
"desc": "Cheesy, crispy, and a lil’ spicy.",
"tags": ["spicy", "halal"],
"image": "https://images.unsplash.com/photo-1601924638867-3ec4d4baf4e1?auto=format&fit=crop&w=800&q=60",
"available": True,
},
{
"id": "PZ002",
"name": "Margherita Pizza",
"category": "Pizza",
"price": 1099,
"desc": "Classic tomato + basil vibes.",
"tags": ["veg", "halal"],
"image": "https://images.unsplash.com/photo-1604068549290-dea0e4a305ca?auto=format&fit=crop&w=800&q=60",
"available": True,
},
{
"id": "BBQ001",
"name": "BBQ Chicken Burger",
"category": "Burgers",
"price": 699,
"desc": "Smoky BBQ sauce + crunchy bite.",
"tags": ["halal"],
"image": "https://images.unsplash.com/photo-1568901346375-23c9450c58cd?auto=format&fit=crop&w=800&q=60",
"available": True,
},
{
"id": "BBQ002",
"name": "Zinger Burger",
"category": "Burgers",
"price": 749,
"desc": "Spicy fried chicken — main character energy.",
"tags": ["spicy", "halal"],
"image": "https://images.unsplash.com/photo-1550547660-d9450f859349?auto=format&fit=crop&w=800&q=60",
"available": True,
},
{
"id": "PA001",
"name": "Alfredo Pasta",
"category": "Pasta",
"price": 999,
"desc": "Creamy comfort with extra sauce points.",
"tags": ["halal"],
"image": "https://images.unsplash.com/photo-1523986371872-9d3ba2e2f5a8?auto=format&fit=crop&w=800&q=60",
"available": True,
},
{
"id": "PA002",
"name": "Arrabbiata Pasta",
"category": "Pasta",
"price": 949,
"desc": "Spicy tomato pasta for heat lovers.",
"tags": ["spicy", "veg", "halal"],
"image": "https://images.unsplash.com/photo-1611270629569-8b357cb88da9?auto=format&fit=crop&w=800&q=60",
"available": True,
},
{
"id": "BBQ003",
"name": "BBQ Platter",
"category": "BBQ",
"price": 1799,
"desc": "Mixed grill — shareable, but you won’t.",
"tags": ["halal"],
"image": "https://images.unsplash.com/photo-1544025162-d76694265947?auto=format&fit=crop&w=800&q=60",
"available": True,
},
{
"id": "SD001",
"name": "Loaded Fries",
"category": "Sides",
"price": 499,
"desc": "Cheese + sauce + chaos (the good kind).",
"tags": ["veg", "halal"],
"image": "https://images.unsplash.com/photo-1541592106381-b31e9677c0e5?auto=format&fit=crop&w=800&q=60",
"available": True,
},
{
"id": "SD002",
"name": "Nuggets (6 pcs)",
"category": "Sides",
"price": 399,
"desc": "Crispy bites for quick wins.",
"tags": ["halal"],
"image": "https://images.unsplash.com/photo-1606755962773-d324e0a13086?auto=format&fit=crop&w=800&q=60",
"available": True,
},
{
"id": "DR001",
"name": "Mint Lemonade",
"category": "Drinks",
"price": 249,
"desc": "Fresh, chill, and super refreshing.",
"tags": ["veg"],
"image": "https://images.unsplash.com/photo-1551024709-8f23befc6f87?auto=format&fit=crop&w=800&q=60",
"available": True,
},
{
"id": "DR002",
"name": "Iced Coffee",
"category": "Drinks",
"price": 349,
"desc": "For assignments + deadlines (we get it).",
"tags": ["veg"],
"image": "https://images.unsplash.com/photo-1517701604599-bb29b565090c?auto=format&fit=crop&w=800&q=60",
"available": True,
},
{
"id": "DS001",
"name": "Chocolate Brownie",
"category": "Desserts",
"price": 399,
"desc": "Fudgy, gooey, happiness.",
"tags": ["veg"],
"image": "https://images.unsplash.com/photo-1606313564200-e75d5e30476c?auto=format&fit=crop&w=800&q=60",
"available": True,
},
{
"id": "DS002",
"name": "Cheesecake Slice",
"category": "Desserts",
"price": 499,
"desc": "Creamy slice of peace.",
"tags": ["veg"],
"image": "https://images.unsplash.com/photo-1542826438-5b0b65e02c76?auto=format&fit=crop&w=800&q=60",
"available": True,
},
{
"id": "VL001",
"name": "Veggie Bowl",
"category": "Healthy",
"price": 699,
"desc": "Light, filling, and gym-friendly.",
"tags": ["veg", "high-protein"],
"image": "https://images.unsplash.com/photo-1512621776951-a57141f2eefd?auto=format&fit=crop&w=800&q=60",
"available": True,
},
{
"id": "VL002",
"name": "Grilled Chicken Bowl",
"category": "Healthy",
"price": 799,
"desc": "Protein + flavor = W.",
"tags": ["high-protein", "halal"],
"image": "https://images.unsplash.com/photo-1546069901-ba9599a7e63c?auto=format&fit=crop&w=800&q=60",
"available": True,
},
]
# -----------------------------
# 2) HELPERS (HCI-friendly)
# -----------------------------
def money(pkr: int) -> str:
return f"Rs {pkr:,}"
def menu_df(menu):
rows = []
for m in menu:
if m.get("available", True):
rows.append({
"ID": m["id"],
"Item": m["name"],
"Category": m["category"],
"Price (PKR)": m["price"],
"Tags": ", ".join(m.get("tags", [])),
"Available": "Yes" if m.get("available", True) else "No",
})
df = pd.DataFrame(rows)
if not df.empty:
df = df.sort_values(["Category", "Item"]).reset_index(drop=True)
return df
def categories(menu):
cats = sorted(set([m["category"] for m in menu]))
return ["All"] + cats
def items_by_category(menu, cat):
items = []
for m in menu:
if not m.get("available", True):
continue
if cat == "All" or m["category"] == cat:
items.append(m)
return items
def gallery_items(menu, cat):
items = items_by_category(menu, cat)
gal = []
for m in items:
caption = f"{m['name']}{money(m['price'])}{m['category']}{', '.join(m.get('tags', []))}"
gal.append((m["image"], caption))
return gal
def dropdown_choices(menu, cat):
items = items_by_category(menu, cat)
# show name + price for clarity
return [f"{m['name']} ({money(m['price'])}) [{m['id']}]" for m in items]
def find_item(menu, item_id):
for m in menu:
if m["id"] == item_id:
return m
return None
def parse_id_from_choice(choice):
# "Name (Rs x) [ID]"
if not choice:
return None
if "[" in choice and "]" in choice:
return choice.split("[")[-1].split("]")[0].strip()
return None
def cart_to_df(cart, menu):
rows = []
subtotal = 0
for item_id, qty in cart.items():
it = find_item(menu, item_id)
if not it:
continue
line = it["price"] * qty
subtotal += line
rows.append({
"Item": it["name"],
"Qty": qty,
"Unit": it["price"],
"Line Total": line,
})
df = pd.DataFrame(rows)
if df.empty:
df = pd.DataFrame([{"Item":"(Cart is empty)", "Qty":"-", "Unit":"-", "Line Total":"-"}])
return df, subtotal
def calc_totals(subtotal, service_pct=5, tax_pct=0):
service = int(round(subtotal * (service_pct / 100)))
tax = int(round(subtotal * (tax_pct / 100)))
total = subtotal + service + tax
return service, tax, total
# -----------------------------
# 3) GROQ LLM (Required style)
# -----------------------------
def groq_reply(user_text: str, menu: list) -> str:
# Required style
import os
from groq import Groq
if not os.environ.get("GROQ_API_KEY"):
return "⚠️ Groq key missing. Please set `os.environ['GROQ_API_KEY']` in Cell 2."
client = Groq(
api_key=os.environ.get("GROQ_API_KEY"),
)
# Provide menu context to LLM
menu_summary = []
for m in menu:
if m.get("available", True):
menu_summary.append({
"id": m["id"],
"name": m["name"],
"category": m["category"],
"price_pkr": m["price"],
"tags": m.get("tags", []),
"desc": m.get("desc", ""),
})
system_msg = (
"You are a friendly restaurant assistant for undergraduate students. "
"Use short, clear answers. Recommend items based on budget/taste. "
"If user mentions allergies, advise to confirm with restaurant staff (disclaimer). "
"Return 3-5 suggestions max with prices in PKR. Keep it GenZ but respectful."
)
chat_completion = client.chat.completions.create(
messages=[
{"role": "system", "content": system_msg},
{"role": "system", "content": f"MENU_JSON: {menu_summary}"},
{"role": "user", "content": user_text},
],
model="llama-3.3-70b-versatile",
)
return chat_completion.choices[0].message.content
# -----------------------------
# 4) GRADIO APP STATE
# -----------------------------
def init_states():
menu = starter_menu()
cart = {} # {item_id: qty}
orders = [] # list of orders
return menu, cart, orders
# -----------------------------
# 5) CUSTOMER ACTIONS
# -----------------------------
def customer_refresh(menu, cat):
gal = gallery_items(menu, cat)
choices = dropdown_choices(menu, cat)
df = menu_df(menu)
return gal, gr.update(choices=choices, value=None), df
def show_item_preview(menu, item_choice):
item_id = parse_id_from_choice(item_choice)
it = find_item(menu, item_id) if item_id else None
if not it:
return None, "Pick an item to preview 👀"
return it["image"], f"**{it['name']}**\n\n{it['desc']}\n\n**Price:** {money(it['price'])}\n\n**Tags:** {', '.join(it.get('tags', []))}"
def add_to_cart(menu, cart, item_choice, qty):
item_id = parse_id_from_choice(item_choice)
if not item_id:
return cart, "⚠️ Please select an item first.", *cart_view(menu, cart)
if qty is None or qty < 1:
return cart, "⚠️ Quantity must be at least 1.", *cart_view(menu, cart)
it = find_item(menu, item_id)
if not it or not it.get("available", True):
return cart, "⚠️ That item is not available right now.", *cart_view(menu, cart)
cart = dict(cart)
cart[item_id] = cart.get(item_id, 0) + int(qty)
msg = f"✅ Added **{it['name']}** x{qty} to cart. Let’s gooo 🛒✨"
return cart, msg, *cart_view(menu, cart)
def remove_from_cart(menu, cart, item_choice):
item_id = parse_id_from_choice(item_choice)
if not item_id:
return cart, "⚠️ Select an item to remove.", *cart_view(menu, cart)
cart = dict(cart)
if item_id in cart:
del cart[item_id]
it = find_item(menu, item_id)
name = it["name"] if it else item_id
return cart, f"🗑️ Removed **{name}** from cart.", *cart_view(menu, cart)
return cart, "ℹ️ Item not found in cart.", *cart_view(menu, cart)
def clear_cart(menu, cart):
cart = {}
return cart, "🧹 Cart cleared. Fresh start.", *cart_view(menu, cart)
def cart_view(menu, cart):
df, subtotal = cart_to_df(cart, menu)
service, tax, total = calc_totals(subtotal, service_pct=5, tax_pct=0)
summary = (
f"**Subtotal:** {money(subtotal)} \n"
f"**Service (5%):** {money(service)} \n"
f"**Tax (0%):** {money(tax)} \n"
f"### **Total:** {money(total)}"
)
return df, summary
def checkout(menu, cart, orders, cust_name, phone, method, address, notes):
# HCI: Validate required inputs
if not cart:
return orders, "⚠️ Your cart is empty. Add something tasty first."
if not cust_name or len(cust_name.strip()) < 2:
return orders, "⚠️ Please enter your name."
if not phone or len(phone.strip()) < 7:
return orders, "⚠️ Please enter a valid phone number."
if method == "Delivery" and (not address or len(address.strip()) < 5):
return orders, "⚠️ Delivery needs an address."
# build order
df, subtotal = cart_to_df(cart, menu)
service, tax, total = calc_totals(subtotal, 5, 0)
order_id = "ORD-" + uuid.uuid4().hex[:8].upper()
order = {
"order_id": order_id,
"time": time.strftime("%Y-%m-%d %H:%M:%S"),
"name": cust_name.strip(),
"phone": phone.strip(),
"method": method,
"address": (address.strip() if address else ""),
"notes": (notes.strip() if notes else ""),
"items": dict(cart),
"subtotal": subtotal,
"service": service,
"tax": tax,
"total": total,
"status": "Pending",
}
orders = list(orders)
orders.insert(0, order) # newest on top
# create a readable slip
slip_lines = [f"🧾 **Order Slip — {order_id}**", f"**Time:** {order['time']}", ""]
for item_id, qty in cart.items():
it = find_item(menu, item_id)
if it:
slip_lines.append(f"- {it['name']} x{qty} ({money(it['price'])} each)")
slip_lines += [
"",
f"**Subtotal:** {money(subtotal)}",
f"**Service (5%):** {money(service)}",
f"**Total:** **{money(total)}**",
"",
f"**Method:** {method}",
f"**Customer:** {order['name']} ({order['phone']})",
]
if method == "Delivery":
slip_lines.append(f"**Address:** {order['address']}")
if order["notes"]:
slip_lines.append(f"**Notes:** {order['notes']}")
slip = "\n".join(slip_lines)
return orders, f"✅ Order placed! {order_id} is in progress. You ate that 😌🔥\n\n{slip}"
# -----------------------------
# 6) ADMIN ACTIONS
# -----------------------------
def orders_table(menu, orders):
rows = []
for o in orders:
rows.append({
"Order ID": o["order_id"],
"Time": o["time"],
"Customer": o["name"],
"Method": o["method"],
"Total": o["total"],
"Status": o["status"],
})
df = pd.DataFrame(rows)
if df.empty:
df = pd.DataFrame([{"Order ID":"(No orders yet)", "Time":"-", "Customer":"-", "Method":"-", "Total":"-", "Status":"-"}])
return df
def order_detail_text(menu, orders, order_id):
if not order_id:
return "Pick an Order ID to view details."
o = next((x for x in orders if x["order_id"] == order_id), None)
if not o:
return "Order not found."
lines = [
f"## {o['order_id']}",
f"**Time:** {o['time']}",
f"**Customer:** {o['name']}{o['phone']}",
f"**Method:** {o['method']}",
]
if o["method"] == "Delivery":
lines.append(f"**Address:** {o['address']}")
if o.get("notes"):
lines.append(f"**Notes:** {o['notes']}")
lines.append("")
lines.append("### Items")
for item_id, qty in o["items"].items():
it = find_item(menu, item_id)
if it:
lines.append(f"- {it['name']} x{qty} ({money(it['price'])} each)")
lines.append("")
lines.append(f"**Subtotal:** {money(o['subtotal'])}")
lines.append(f"**Service:** {money(o['service'])}")
lines.append(f"**Total:** **{money(o['total'])}**")
lines.append(f"**Status:** {o['status']}")
return "\n".join(lines)
def update_order_status(orders, order_id, new_status):
if not order_id:
return orders, "⚠️ Select an Order ID first."
orders = list(orders)
for o in orders:
if o["order_id"] == order_id:
o["status"] = new_status
return orders, f"✅ Status updated: {order_id} → **{new_status}**"
return orders, "⚠️ Order not found."
def admin_add_item(menu, item_id, name, category, price, desc, tags_csv, image_url, available):
# Validation
if not item_id or len(item_id.strip()) < 3:
return menu, "⚠️ Item ID is required (e.g., BB001).", menu_df(menu)
if not name or len(name.strip()) < 2:
return menu, "⚠️ Item name is required.", menu_df(menu)
if not category or len(category.strip()) < 2:
return menu, "⚠️ Category is required.", menu_df(menu)
try:
price = int(price)
if price <= 0:
raise ValueError()
except:
return menu, "⚠️ Price must be a positive number.", menu_df(menu)
if not image_url or not image_url.startswith("http"):
return menu, "⚠️ Image URL must be a valid http(s) link.", menu_df(menu)
tags = [t.strip() for t in (tags_csv or "").split(",") if t.strip()]
menu = list(menu)
# prevent duplicates
if any(m["id"] == item_id.strip() for m in menu):
return menu, "⚠️ Item ID already exists. Use Edit flow (or change ID).", menu_df(menu)
menu.append({
"id": item_id.strip(),
"name": name.strip(),
"category": category.strip(),
"price": price,
"desc": (desc or "").strip(),
"tags": tags,
"image": image_url.strip(),
"available": bool(available),
})
return menu, f"✅ Added **{name.strip()}** to menu.", menu_df(menu)
def admin_delete_item(menu, delete_id):
if not delete_id:
return menu, "⚠️ Provide an Item ID to delete.", menu_df(menu)
menu = [m for m in menu if m["id"] != delete_id.strip()]
return menu, f"🗑️ Deleted item **{delete_id.strip()}** (if it existed).", menu_df(menu)
def admin_toggle_availability(menu, toggle_id):
if not toggle_id:
return menu, "⚠️ Provide an Item ID to toggle.", menu_df(menu)
menu = list(menu)
for m in menu:
if m["id"] == toggle_id.strip():
m["available"] = not m.get("available", True)
state = "Available ✅" if m["available"] else "Unavailable 🚫"
return menu, f"🔁 {m['name']} is now: **{state}**", menu_df(menu)
return menu, "⚠️ Item not found.", menu_df(menu)
# -----------------------------
# 7) AI CHAT
# -----------------------------
def chat_send(chat_history, user_msg, menu):
user_msg = (user_msg or "").strip()
if not user_msg:
return chat_history, ""
chat_history = list(chat_history)
chat_history.append(("You", user_msg))
try:
bot = groq_reply(user_msg, menu)
except Exception as e:
bot = f"⚠️ LLM error: {e}"
chat_history.append(("Assistant", bot))
return chat_history, ""
# -----------------------------
# 8) BUILD UI (GenZ + HCI)
# -----------------------------
menu0, cart0, orders0 = init_states()
with gr.Blocks(
title="UniBites — Restaurant Web App (Python + Gradio + Groq)",
theme=gr.themes.Soft(),
css="""
.title {font-size: 26px; font-weight: 800;}
.subtitle {opacity: 0.85;}
.card {border-radius: 16px;}
"""
) as demo:
menu_state = gr.State(menu0)
cart_state = gr.State(cart0)
orders_state = gr.State(orders0)
gr.Markdown(
"""
<div class="title">🍔 UniBites — Single Restaurant App</div>
<div class="subtitle">Browse • Add to cart • Checkout • Admin • AI menu helper (Groq)</div>
""",
)
with gr.Tabs():
# ---------------- CUSTOMER TAB ----------------
with gr.Tab("🍽️ Customer"):
with gr.Row():
category = gr.Dropdown(choices=categories(menu0), value="All", label="Choose Category")
refresh_btn = gr.Button("🔄 Refresh Menu", variant="secondary")
gallery = gr.Gallery(label="Menu (tap to vibe)", columns=3, rows=2, height=360)
menu_table = gr.Dataframe(label="Menu Table (for clarity)", interactive=False)
with gr.Row():
item_choice = gr.Dropdown(choices=dropdown_choices(menu0, "All"), label="Pick Item (for cart)")
qty = gr.Slider(1, 10, value=1, step=1, label="Qty")
with gr.Row():
preview_img = gr.Image(label="Preview Image", height=220)
preview_txt = gr.Markdown("Pick an item to preview 👀")
with gr.Row():
add_btn = gr.Button("➕ Add to Cart", variant="primary")
remove_btn = gr.Button("➖ Remove from Cart", variant="secondary")
clear_btn = gr.Button("🧹 Clear Cart", variant="secondary")
cart_msg = gr.Markdown("")
cart_df = gr.Dataframe(label="Cart", interactive=False)
cart_summary = gr.Markdown("")
gr.Markdown("## ✅ Checkout (no stress, just fill basics)")
with gr.Row():
cust_name = gr.Textbox(label="Your Name", placeholder="e.g., Ali / Ayesha")
phone = gr.Textbox(label="Phone", placeholder="03xx-xxxxxxx")
method = gr.Radio(["Delivery", "Pickup"], value="Delivery", label="Delivery or Pickup?")
address = gr.Textbox(label="Address (required for delivery)", placeholder="Hostel / home address")
notes = gr.Textbox(label="Notes (optional)", placeholder="Less spicy / no onions / etc.")
place_btn = gr.Button("🧾 Place Order", variant="primary")
order_out = gr.Markdown("")
# ---------------- ADMIN TAB ----------------
with gr.Tab("🧑‍🍳 Admin"):
gr.Markdown("### Admin Panel (simple, beginner-friendly)")
admin_menu_df = gr.Dataframe(label="Current Menu", interactive=False)
with gr.Accordion("➕ Add New Menu Item", open=False):
with gr.Row():
a_id = gr.Textbox(label="Item ID", placeholder="e.g., SD010")
a_name = gr.Textbox(label="Name", placeholder="e.g., Garlic Bread")
a_cat = gr.Textbox(label="Category", placeholder="e.g., Sides")
with gr.Row():
a_price = gr.Number(label="Price (PKR)", value=399)
a_tags = gr.Textbox(label="Tags (comma separated)", placeholder="veg, halal")
a_avail = gr.Checkbox(label="Available", value=True)
a_desc = gr.Textbox(label="Description", placeholder="Short description for customers")
a_img = gr.Textbox(label="Image URL", placeholder="https://... (public image link)")
add_item_btn = gr.Button("✅ Add Item", variant="primary")
admin_msg = gr.Markdown("")
with gr.Accordion("🗑️ Delete Item / 🔁 Toggle Availability", open=False):
with gr.Row():
del_id = gr.Textbox(label="Item ID to Delete", placeholder="e.g., SD010")
del_btn = gr.Button("🗑️ Delete", variant="secondary")
with gr.Row():
tog_id = gr.Textbox(label="Item ID to Toggle", placeholder="e.g., SD001")
tog_btn = gr.Button("🔁 Toggle Availability", variant="secondary")
admin_msg2 = gr.Markdown("")
gr.Markdown("### Orders")
orders_df = gr.Dataframe(label="Orders List", interactive=False)
with gr.Row():
order_id_pick = gr.Dropdown(choices=[], label="Select Order ID")
new_status = gr.Dropdown(
["Pending", "Preparing", "Ready", "Completed", "Cancelled"],
value="Preparing",
label="Update Status"
)
with gr.Row():
view_order_btn = gr.Button("👀 View Order Detail", variant="secondary")
update_status_btn = gr.Button("✅ Update Status", variant="primary")
order_detail = gr.Markdown("Pick an order to see details.")
admin_order_msg = gr.Markdown("")
# ---------------- AI TAB ----------------
with gr.Tab("🤖 AI Assistant"):
gr.Markdown(
"""
### Ask me anything about the menu 😌
Try:
- “I have Rs 800, recommend something spicy”
- “Suggest high-protein items”
- “I’m lactose intolerant, what’s safe?” (I’ll still tell you to confirm with staff)
"""
)
chatbot = gr.Chatbot(label="Chat", height=360)
user_msg = gr.Textbox(label="Message", placeholder="Type here…")
send_btn = gr.Button("Send 🚀", variant="primary")
# --------- INIT LOAD ---------
def initial_load(menu):
cat = "All"
gal = gallery_items(menu, cat)
choices = dropdown_choices(menu, cat)
return (
gal,
gr.update(choices=categories(menu), value=cat),
gr.update(choices=choices, value=None),
menu_df(menu),
menu_df(menu),
orders_table(menu, []),
gr.update(choices=[], value=None),
*cart_view(menu, {})
)
demo.load(
initial_load,
inputs=[menu_state],
outputs=[gallery, category, item_choice, menu_table, admin_menu_df, orders_df, order_id_pick, cart_df, cart_summary]
)
# --------- CUSTOMER EVENTS ---------
refresh_btn.click(
customer_refresh,
inputs=[menu_state, category],
outputs=[gallery, item_choice, menu_table]
)
category.change(
customer_refresh,
inputs=[menu_state, category],
outputs=[gallery, item_choice, menu_table]
)
item_choice.change(
show_item_preview,
inputs=[menu_state, item_choice],
outputs=[preview_img, preview_txt]
)
add_btn.click(
add_to_cart,
inputs=[menu_state, cart_state, item_choice, qty],
outputs=[cart_state, cart_msg, cart_df, cart_summary]
)
remove_btn.click(
remove_from_cart,
inputs=[menu_state, cart_state, item_choice],
outputs=[cart_state, cart_msg, cart_df, cart_summary]
)
clear_btn.click(
clear_cart,
inputs=[menu_state, cart_state],
outputs=[cart_state, cart_msg, cart_df, cart_summary]
)
place_btn.click(
checkout,
inputs=[menu_state, cart_state, orders_state, cust_name, phone, method, address, notes],
outputs=[orders_state, order_out]
).then(
lambda menu, orders: (orders_table(menu, orders), gr.update(choices=[o["order_id"] for o in orders], value=(orders[0]["order_id"] if orders else None))),
inputs=[menu_state, orders_state],
outputs=[orders_df, order_id_pick]
).then(
lambda menu: (*cart_view(menu, {}), {}),
inputs=[menu_state],
outputs=[cart_df, cart_summary, cart_state]
)
# --------- ADMIN EVENTS ---------
add_item_btn.click(
admin_add_item,
inputs=[menu_state, a_id, a_name, a_cat, a_price, a_desc, a_tags, a_img, a_avail],
outputs=[menu_state, admin_msg, admin_menu_df]
).then(
customer_refresh,
inputs=[menu_state, category],
outputs=[gallery, item_choice, menu_table]
)
del_btn.click(
admin_delete_item,
inputs=[menu_state, del_id],
outputs=[menu_state, admin_msg2, admin_menu_df]
).then(
customer_refresh,
inputs=[menu_state, category],
outputs=[gallery, item_choice, menu_table]
)
tog_btn.click(
admin_toggle_availability,
inputs=[menu_state, tog_id],
outputs=[menu_state, admin_msg2, admin_menu_df]
).then(
customer_refresh,
inputs=[menu_state, category],
outputs=[gallery, item_choice, menu_table]
)
view_order_btn.click(
order_detail_text,
inputs=[menu_state, orders_state, order_id_pick],
outputs=[order_detail]
)
update_status_btn.click(
update_order_status,
inputs=[orders_state, order_id_pick, new_status],
outputs=[orders_state, admin_order_msg]
).then(
lambda menu, orders: (orders_table(menu, orders)),
inputs=[menu_state, orders_state],
outputs=[orders_df]
).then(
order_detail_text,
inputs=[menu_state, orders_state, order_id_pick],
outputs=[order_detail]
)
# --------- AI CHAT EVENTS ---------
send_btn.click(
chat_send,
inputs=[chatbot, user_msg, menu_state],
outputs=[chatbot, user_msg]
)
user_msg.submit(
chat_send,
inputs=[chatbot, user_msg, menu_state],
outputs=[chatbot, user_msg]
)
demo.launch(share=True, debug=True)