!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( """
🍔 UniBites — Single Restaurant App
Browse • Add to cart • Checkout • Admin • AI menu helper (Groq)
""", ) 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)