geethareddy commited on
Commit
cae89b2
·
verified ·
1 Parent(s): 57462dd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +28 -428
app.py CHANGED
@@ -1,44 +1,13 @@
1
  import gradio as gr
2
  import pandas as pd
3
- from bcrypt import hashpw, gensalt, checkpw
 
4
 
5
- # File for storing user data
6
- USER_FILE = "users.xlsx"
7
-
8
- # Utility Functions
9
- def save_user(name, phone, email, password):
10
- """Save user details to Excel file."""
11
- try:
12
- # Load existing users
13
- try:
14
- users = pd.read_excel(USER_FILE)
15
- except FileNotFoundError:
16
- users = pd.DataFrame(columns=["Name", "Phone", "Email", "Password"])
17
-
18
- # Check if email already exists
19
- if email in users["Email"].values:
20
- return False # User already exists
21
-
22
- # Add new user
23
- hashed_password = hashpw(password.encode(), gensalt()).decode()
24
- new_user = {"Name": name, "Phone": phone, "Email": email, "Password": hashed_password}
25
- users = pd.concat([users, pd.DataFrame([new_user])], ignore_index=True)
26
- users.to_excel(USER_FILE, index=False)
27
- return True
28
- except Exception as e:
29
- print(f"Error saving user: {e}")
30
- return False
31
-
32
- def check_credentials(email, password):
33
- """Check user credentials during login."""
34
- try:
35
- users = pd.read_excel(USER_FILE)
36
- user = users[users["Email"] == email]
37
- if not user.empty:
38
- return checkpw(password.encode(), user.iloc[0]["Password"].encode())
39
- return False
40
- except FileNotFoundError:
41
- return False
42
 
43
  # Function to load the menu data
44
  def load_menu():
@@ -48,7 +17,6 @@ def load_menu():
48
  except Exception as e:
49
  raise ValueError(f"Error loading menu file: {e}")
50
 
51
-
52
  # Function to filter menu items based on preference
53
  def filter_menu(preference):
54
  menu_data = load_menu()
@@ -70,408 +38,40 @@ def filter_menu(preference):
70
  <p style="margin: 5px 0; font-size: 16px; color: #888;">${item['Price ($)']}</p>
71
  <p style="margin: 5px 0; font-size: 14px; color: #555;">{item['Description']}</p>
72
  </div>
73
- <div style="flex-shrink: 0; text-align: center;">
74
- <img src="{item['Image URL']}" alt="{item['Dish Name']}" style="width: 100px; height: 100px; border-radius: 8px; object-fit: cover; margin-bottom: 10px;">
75
- <button style="background-color: #28a745; color: white; border: none; padding: 8px 15px; font-size: 14px; border-radius: 5px; cursor: pointer;" onclick="openModal('{item['Dish Name']}', '{item['Image 2 URL']}', '{item['Description']}', '{item['Price ($)']}')">Add</button>
76
- </div>
77
  </div>
78
  """
79
  return html_content
80
- # Preserving your JavaScript for modal and cart functionality (Your original JavaScript logic)
81
- modal_and_cart_js = """
82
- <style>
83
- .cart-container {
84
- width: 90%; /* Ensure it fits the screen */
85
- margin: auto;
86
- display: flex;
87
- flex-direction: column;
88
- gap: 10px; /* Add space between cart items */
89
- }
90
- .cart-item {
91
- display: flex;
92
- flex-wrap: wrap; /* Wrap content to the next line if needed */
93
- align-items: center; /* Vertically align items */
94
- justify-content: space-between; /* Distribute space between items */
95
- width: 100%; /* Ensure it takes full width */
96
- padding: 10px;
97
- border: 1px solid #ccc;
98
- border-radius: 5px;
99
- background-color: #f9f9f9;
100
- }
101
- .cart-item span {
102
- margin-right: 10px;
103
- flex: 1; /* Allow text to take available space */
104
- min-width: 50px; /* Prevent collapsing */
105
- }
106
- .cart-item .quantity-container {
107
- display: flex;
108
- align-items: center;
109
- gap: 5px;
110
- }
111
- .cart-item button {
112
- background-color: red;
113
- color: white;
114
- border: none;
115
- padding: 5px 10px;
116
- cursor: pointer;
117
- border-radius: 5px;
118
- flex-shrink: 0; /* Prevent the button from shrinking */
119
- }
120
- .cart-total {
121
- font-size: 1.2em;
122
- font-weight: bold;
123
- text-align: center;
124
- }
125
- button {
126
- margin-top: 10px;
127
- background-color: #007bff;
128
- color: white;
129
- border: none;
130
- padding: 10px;
131
- border-radius: 5px;
132
- width: 100%;
133
- cursor: pointer;
134
- }
135
- @media (max-width: 768px) {
136
- .cart-item {
137
- flex-direction: column; /* Stack items on mobile */
138
- align-items: flex-start; /* Align to the left */
139
- }
140
- .cart-item button {
141
- align-self: flex-end; /* Place the remove button at the end */
142
- margin-top: 5px; /* Add some space on top */
143
- }
144
- }
145
- </style>
146
- <script>
147
- let cart = [];
148
- const extrasPrices = {
149
- "Thums up": 2,
150
- "Sprite": 2,
151
- "Extra Raitha": 1,
152
- "Extra Salan": 2,
153
- "Extra Onion & Lemon": 2,
154
- "Chilli Chicken": 14,
155
- "Veg Manchurian": 12
156
- };
157
- let finalized = false;
158
- function openModal(name, image2, description, price) {
159
- if (finalized) {
160
- alert("You cannot add more items after finalizing your order.");
161
- return;
162
- }
163
- const modal = document.getElementById('modal');
164
- modal.style.display = 'block';
165
- modal.style.position = 'fixed';
166
- if (window.innerWidth <= 768) {
167
- modal.style.width = '90%';
168
- modal.style.top = `${event.touches ? event.touches[0].screenY : event.clientY}px`;
169
- } else {
170
- modal.style.width = '30%';
171
- modal.style.top = `${event.clientY}px`;// Use mouse Y position for laptop
172
- }
173
- modal.style.left = '50%';
174
- modal.style.transform = 'translate(-50%, -50%)';
175
- document.getElementById('modal-image').src = image2;
176
- document.getElementById('modal-name').innerText = name;
177
- document.getElementById('modal-description').innerText = description;
178
- document.getElementById('modal-price').innerText = price;
179
- const extrasInputs = document.querySelectorAll('input[name="biryani-extra"]');
180
- extrasInputs.forEach(input => input.checked = false);
181
- document.getElementById('quantity').value = 1;
182
- document.getElementById('special-instructions').value = '';
183
- }
184
- function closeModal() {
185
- document.getElementById('modal').style.display = 'none';
186
- }
187
- function addToCart() {
188
- if (finalized) {
189
- alert("You cannot add more items after finalizing your order.");
190
- return;
191
- }
192
- const name = document.getElementById('modal-name').innerText;
193
- const price = parseFloat(document.getElementById('modal-price').innerText.replace('$', ''));
194
- const quantity = parseInt(document.getElementById('quantity').value) || 1;
195
- const instructions = document.getElementById('special-instructions').value;
196
- const extras = Array.from(document.querySelectorAll('input[name="biryani-extra"]:checked')).map(extra => extra.value);
197
- const extrasCost = extras.reduce((sum, extra) => sum + (extrasPrices[extra] || 0), 0);
198
- const itemTotal = (price + extrasCost) * quantity;
199
- const cartItem = { name, price, quantity, instructions, extras, itemTotal, extrasQuantities: extras.map(() => 1) };
200
- cart.push(cartItem);
201
- alert(`${name} added to cart!`);
202
- updateCartDisplay();
203
- closeModal();
204
- }
205
- function updateCartDisplay() {
206
- let totalBill = 0;
207
- let cartHTML = "<div class='cart-container'>";
208
- cart.forEach((item, index) => {
209
- totalBill += item.itemTotal;
210
- const extras = item.extras.map((extra, i) => {
211
- const extraQuantity = item.extrasQuantities ? item.extrasQuantities[i] || 1 : 1;
212
- const extraTotal = extrasPrices[extra] * extraQuantity;
213
- totalBill += extraTotal;
214
- return `<div class='cart-item'>
215
- <span>${extra}</span>
216
- <span>Price: $${extrasPrices[extra].toFixed(2)}</span>
217
- <div class='quantity-container'>
218
- <label for='extra-quantity-${index}-${i}'>Quantity:</label>
219
- <input type='number' id='extra-quantity-${index}-${i}' value='${extraQuantity}' min='1' style='width: 50px;' onchange='updateExtraQuantity(${index}, ${i}, this.value)'>
220
- </div>
221
- <span>Total: $${extraTotal.toFixed(2)}</span>
222
- <button style='background-color: red; color: white; border: none; padding: 5px 10px; cursor: pointer;' onclick='removeExtra(${index}, ${i})'>Remove</button>
223
- </div>`;
224
- }).join('');
225
- cartHTML += `<div class='cart-item'>
226
- <span>${item.name}</span>
227
- <span>Item Price: $${item.price.toFixed(2)}</span>
228
- <div class='quantity-container'>
229
- <label for='item-quantity-${index}'>Quantity:</label>
230
- <input type='number' id='item-quantity-${index}' value='${item.quantity}' min='1' style='width: 50px;' onchange='updateItemQuantity(${index}, this.value)'>
231
- </div>
232
- <span>Total: $${(item.price * item.quantity).toFixed(2)}</span>
233
- <button style='background-color: red; color: white; border: none; padding: 5px 10px; cursor: pointer;' onclick='removeItem(${index})'>Remove</button>
234
- </div>
235
- ${extras}
236
- <div class='cart-item'><strong>Instructions:</strong> ${item.instructions || "None"}</div>`;
237
- });
238
- cartHTML += `</div><p class='cart-total'>Total Bill: $${totalBill.toFixed(2)}</p>`;
239
- cartHTML += `<button style='margin-top: 10px; background-color: #007bff; color: white; border: none; padding: 10px; border-radius: 5px; width: 100%; cursor: pointer;' onclick='submitCart()'>Submit</button>`;
240
- document.getElementById('floating-cart').innerHTML = cartHTML;
241
- }
242
- function updateItemQuantity(index, newQuantity) {
243
- const quantity = parseInt(newQuantity) || 1;
244
- cart[index].quantity = quantity;
245
- cart[index].itemTotal = cart[index].price * quantity;
246
- updateCartDisplay();
247
- }
248
- function updateExtraQuantity(cartIndex, extraIndex, newQuantity) {
249
- const quantity = parseInt(newQuantity) || 1;
250
- cart[cartIndex].extrasQuantities = cart[cartIndex].extrasQuantities || [];
251
- cart[cartIndex].extrasQuantities[extraIndex] = quantity;
252
- updateCartDisplay();
253
- }
254
- function removeExtra(cartIndex, extraIndex) {
255
- cart[cartIndex].extras.splice(extraIndex, 1);
256
- if (cart[cartIndex].extrasQuantities) {
257
- cart[cartIndex].extrasQuantities.splice(extraIndex, 1);
258
- }
259
- updateCartDisplay();
260
- }
261
- function removeItem(index) {
262
- cart.splice(index, 1);
263
- updateCartDisplay();
264
- }
265
- function submitCart() {
266
- let finalOrderHTML = "<h3>Final Order:</h3><ul>";
267
- let totalBill = 0;
268
- cart.forEach(item => {
269
- totalBill += item.itemTotal;
270
- const extras = item.extras.map((extra, i) => {
271
- const extraQuantity = item.extrasQuantities ? item.extrasQuantities[i] || 1 : 1;
272
- const extraTotal = extrasPrices[extra] * extraQuantity;
273
- totalBill += extraTotal;
274
- return `${extra} (x${extraQuantity}) - $${extraTotal.toFixed(2)}`;
275
- }).join(', ');
276
- finalOrderHTML += `<li>
277
- ${item.name} (x${item.quantity}) - $${item.itemTotal.toFixed(2)}
278
- <br>Extras: ${extras}
279
- <br>Instructions: ${item.instructions || "None"}
280
- </li>`;
281
- });
282
- finalOrderHTML += `</ul><p><strong>Total Bill: $${totalBill.toFixed(2)}</strong></p>`;
283
- document.getElementById('final-order').innerHTML = finalOrderHTML;
284
- // Trigger navigation to the final order page
285
- const finalOrderPage = document.getElementById('final-order-section');
286
- const cartPage = document.getElementById('cart-section');
287
- cartPage.style.display = 'none';
288
- finalOrderPage.style.display = 'block';
289
- }
290
-
291
- </script>
292
- """
293
- # Authentication and Navigation Logic
294
- def authenticate_user(email, password):
295
- if check_credentials(email, password):
296
- return gr.update(visible=False), gr.update(visible=True), ""
297
- else:
298
- return gr.update(visible=True), gr.update(visible=False), "Invalid email or password. Try again."
299
-
300
- def navigate_to_signup():
301
- return gr.update(visible=False), gr.update(visible=True)
302
 
303
- def create_account(name, phone, email, password):
304
- if save_user(name, phone, email, password):
305
- return "Account created successfully! You can now log in.", gr.update(visible=True), gr.update(visible=False)
306
- else:
307
- return "Email already exists. Try logging in.", gr.update(visible=False), gr.update(visible=True)
308
-
309
- def navigate_to_login():
310
- return gr.update(visible=True), gr.update(visible=False)
311
 
312
  # Gradio App
313
  def app():
314
  with gr.Blocks() as demo:
315
- # Login Page
316
- with gr.Column(visible=True) as login_section:
317
- gr.Markdown("# Login Page")
318
- login_email = gr.Textbox(label="Email", placeholder="Enter your email")
319
- login_password = gr.Textbox(label="Password", placeholder="Enter your password", type="password")
320
- login_error = gr.Label("")
321
- login_button = gr.Button("Login")
322
- go_to_signup = gr.Button("Create an Account")
323
-
324
- # Signup Page
325
- with gr.Column(visible=False) as signup_section:
326
- gr.Markdown("# Signup Page")
327
- signup_name = gr.Textbox(label="Name", placeholder="Enter your full name")
328
- signup_phone = gr.Textbox(label="Phone", placeholder="Enter your phone number")
329
- signup_email = gr.Textbox(label="Email", placeholder="Enter your email")
330
- signup_password = gr.Textbox(label="Password", placeholder="Enter your password", type="password")
331
- signup_message = gr.Label("")
332
- signup_button = gr.Button("Sign Up")
333
- go_to_login = gr.Button("Back to Login")
334
-
335
- # Menu Page
336
- with gr.Column(visible=False) as menu_section:
337
- gr.Markdown("### Menu Page (Accessible Only After Login)")
338
-
339
- # View Cart Button (Top Position)
340
- view_cart_button_top = gr.Button("View Cart")
341
-
342
- # Radio button for selecting preference
343
- selected_preference = gr.Radio(
344
- choices=["All", "Vegetarian", "Halal/Non-Veg", "Guilt Free"],
345
- value="All",
346
- label="Choose a Preference",
347
- )
348
- empty_div = gr.HTML('<div style="height: 20px;"></div>')
349
-
350
- # Output area for menu items
351
- menu_output = gr.HTML(value=filter_menu("All"))
352
-
353
- # View Cart Button (Original Position)
354
- view_cart_button_bottom = gr.Button("View Cart")
355
- empty_div = gr.HTML('<div style="height: 300px;"></div>')
356
-
357
- # Modal window
358
- modal_window = gr.HTML("""
359
- <div id="modal" style="display: none; position: fixed; background: white; border-radius: 8px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); padding: 20px; z-index: 1000;">
360
- <div style="text-align: right;">
361
- <button onclick="closeModal()" style="background: none; border: none; font-size: 18px; cursor: pointer;">&times;</button>
362
- </div>
363
- <img id="modal-image" style="width: 100%; height: 300px; border-radius: 8px; margin-bottom: 20px;" />
364
- <h2 id="modal-name"></h2>
365
- <p id="modal-description"></p>
366
- <p id="modal-price"></p>
367
- <!-- Biryani Extras -->
368
- <label for="biryani-extras"><strong>Add-ons :</strong></label>
369
- <div id="biryani-extras-options" style="display: flex; flex-wrap: wrap; gap: 10px; margin: 10px 0;">
370
- <label><input type="checkbox" name="biryani-extra" value="Thums up" /> Thums up + $2.00</label>
371
- <label><input type="checkbox" name="biryani-extra" value="Sprite" /> Sprite + $2.00</label>
372
- <label><input type="checkbox" name="biryani-extra" value="Extra Raitha" /> Extra Raitha + $1.00</label>
373
- <label><input type="checkbox" name="biryani-extra" value="Extra Salan" /> Extra Salan + $2.00</label>
374
- <label><input type="checkbox" name="biryani-extra" value="Extra Onion & Lemon" /> Extra Onion & Lemon + $2.00</label>
375
- <label><input type="checkbox" name="biryani-extra" value="Chilli Chicken" /> Chilli Chicken + $14.00</label>
376
- <label><input type="checkbox" name="biryani-extra" value="Veg Manchurian" /> Veg Manchurian + $12.00</label>
377
- </div>
378
- <!-- Quantity and Special Instructions -->
379
- <label for="quantity">Quantity:</label>
380
- <input type="number" id="quantity" value="1" min="1" style="width: 50px;" />
381
- <br><br>
382
- <textarea id="special-instructions" placeholder="Add your special instructions here..." style="width: 100%; height: 60px;"></textarea>
383
- <br><br>
384
- <!-- Add to Cart Button -->
385
- <button style="background-color: #28a745; color: white; border: none; padding: 10px 20px; font-size: 14px; border-radius: 5px; cursor: pointer;" onclick="addToCart()">Add to Cart</button>
386
- </div>
387
- """)
388
-
389
- # Update menu dynamically based on preference
390
- selected_preference.change(filter_menu, inputs=[selected_preference], outputs=[menu_output])
391
-
392
- # Layout
393
- gr.Row(view_cart_button_top) # View Cart button at the top
394
- gr.Row([selected_preference])
395
- gr.Row(menu_output)
396
- gr.Row(view_cart_button_bottom) # View Cart button at the bottom
397
- gr.Row(modal_window)
398
- gr.HTML(modal_and_cart_js)
399
-
400
- # Cart & Final Order Page
401
- with gr.Column(visible=False, elem_id="cart-section") as cart_section:
402
- gr.Markdown("### Cart Page")
403
- cart_output = gr.HTML(value="Your cart is empty.", elem_id="floating-cart")
404
- #submitCart_button = gr.Button("Submit Cart") # Keep only this button
405
- back_to_menu_button = gr.Button("Back to Menu")
406
-
407
-
408
- with gr.Column(visible=False, elem_id="final-order-section") as final_order_section:
409
- gr.Markdown("### Final Order")
410
- final_order_output = gr.HTML(value="", elem_id="final-order")
411
-
412
-
413
-
414
- # Floating cart display
415
- #cart_output = gr.HTML(value="Your cart is empty.", elem_id="floating-cart")
416
-
417
- # Final order display
418
- #final_order_output = gr.HTML(value="", elem_id="final-order")
419
-
420
- # Button to navigate back to Menu Page
421
- #back_to_menu_button = gr.Button("Back to Menu")
422
-
423
- gr.Row(cart_output)
424
- gr.Row(final_order_output)
425
-
426
- # Button Bindings
427
- # Login Button
428
- login_button.click(
429
- lambda email, password: (gr.update(visible=False), gr.update(visible=True), "") if check_credentials(email, password) else (gr.update(), gr.update(), "Invalid email or password."),
430
- inputs=[login_email, login_password],
431
- outputs=[login_section, menu_section, login_error],
432
- )
433
- # Signup Button
434
- signup_button.click(
435
- lambda name, phone, email, password: ("Signup successful! Please login.", gr.update(visible=True), gr.update(visible=False)) if save_user(name, phone, email, password) else ("Email already exists.", gr.update(visible=False), gr.update(visible=True)),
436
- inputs=[signup_name, signup_phone, signup_email, signup_password],
437
- outputs=[signup_message, login_section, signup_section],
438
- )
439
- # Navigate to Signup Page
440
- go_to_signup.click(
441
- lambda: (gr.update(visible=False), gr.update(visible=True)),
442
- outputs=[login_section, signup_section],
443
- )
444
- # Navigate Back to Login Page
445
- go_to_login.click(
446
- lambda: (gr.update(visible=True), gr.update(visible=False)),
447
- outputs=[login_section, signup_section],
448
- )
449
- # Navigate to Cart Page (Both Buttons Use the Same Logic)
450
- view_cart_button_top.click(
451
- lambda: (gr.update(visible=False), gr.update(visible=True)),
452
- outputs=[menu_section, cart_section],
453
- )
454
- view_cart_button_bottom.click(
455
- lambda: (gr.update(visible=False), gr.update(visible=True)),
456
- outputs=[menu_section, cart_section],
457
- )
458
-
459
- # Navigate to Final Order Page
460
- # Navigate to Final Order Page
461
- #submitCart_button.click(
462
- #lambda: (gr.update(visible=False), gr.update(visible=True)),
463
- #outputs=[cart_section, final_order_section],
464
- #)
465
- # Navigate Back to Menu Page
466
- back_to_menu_button.click(
467
- lambda: (gr.update(visible=True), gr.update(visible=False)),
468
- outputs=[menu_section, cart_section], # Show menu, hide cart
469
  )
470
 
 
 
471
 
 
 
472
 
 
 
 
473
 
474
  return demo
475
 
476
  if __name__ == "__main__":
477
- app().launch()
 
1
  import gradio as gr
2
  import pandas as pd
3
+ import pyttsx3
4
+ import time
5
 
6
+ # Initialize text-to-speech engine
7
+ def speak_text(text):
8
+ engine = pyttsx3.init()
9
+ engine.say(text)
10
+ engine.runAndWait()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
  # Function to load the menu data
13
  def load_menu():
 
17
  except Exception as e:
18
  raise ValueError(f"Error loading menu file: {e}")
19
 
 
20
  # Function to filter menu items based on preference
21
  def filter_menu(preference):
22
  menu_data = load_menu()
 
38
  <p style="margin: 5px 0; font-size: 16px; color: #888;">${item['Price ($)']}</p>
39
  <p style="margin: 5px 0; font-size: 14px; color: #555;">{item['Description']}</p>
40
  </div>
 
 
 
 
41
  </div>
42
  """
43
  return html_content
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
 
45
+ # Function to announce menu page entry
46
+ def announce_menu():
47
+ speak_text("Welcome to menu page")
48
+ time.sleep(2)
49
+ speak_text("Choose a preference")
 
 
 
50
 
51
  # Gradio App
52
  def app():
53
  with gr.Blocks() as demo:
54
+ gr.Markdown("### Menu Page")
55
+ announce_menu()
56
+
57
+ # Radio button for selecting preference
58
+ selected_preference = gr.Radio(
59
+ choices=["All", "Vegetarian", "Halal/Non-Veg", "Guilt Free"],
60
+ value="All",
61
+ label="Choose a Preference",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  )
63
 
64
+ # Output area for menu items
65
+ menu_output = gr.HTML(value=filter_menu("All"))
66
 
67
+ # Update menu dynamically based on preference
68
+ selected_preference.change(filter_menu, inputs=[selected_preference], outputs=[menu_output])
69
 
70
+ # Layout
71
+ gr.Row([selected_preference])
72
+ gr.Row(menu_output)
73
 
74
  return demo
75
 
76
  if __name__ == "__main__":
77
+ app().launch()