lokeshloki143 commited on
Commit
c4a2b4a
·
verified ·
1 Parent(s): e04397b

Update templates/menu.html

Browse files
Files changed (1) hide show
  1. templates/menu.html +61 -74
templates/menu.html CHANGED
@@ -8,10 +8,10 @@
8
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
9
  <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">
10
  <!-- Preload Critical Resources -->
11
- <link rel="preload" href="/static/placeholder.mp4" as="video" fetchpriority="high">
12
  {% for section, items in ordered_menu.items() %}
13
  {% for item in items[:1] %}
14
- <link rel="preload" href="{{ item.Video1__c | default('/static/placeholder.mp4') }}" as="video" fetchpriority="high">
15
  {% endfor %}
16
  {% endfor %}
17
  <style>
@@ -30,7 +30,6 @@
30
  .menu-card {
31
  max-width: 350px;
32
  border-radius: 15px;
33
- overflow: hidden;
34
  background-color: #fff;
35
  margin: auto;
36
  display: flex;
@@ -45,9 +44,7 @@
45
  position: relative;
46
  width: 100%;
47
  height: 200px;
48
- overflow: hidden;
49
  border-radius: 15px 15px 0 0;
50
- background-color: #000;
51
  transition: transform 0.3s ease;
52
  }
53
  .media-wrapper:hover, .media-wrapper.touched {
@@ -68,11 +65,12 @@
68
  }
69
  .menu-image {
70
  position: absolute;
71
- top: 0;
72
- left: 0;
 
73
  width: 100%;
74
  height: 100%;
75
- object-fit: cover;
76
  opacity: 1;
77
  transition: opacity 0.3s ease;
78
  }
@@ -257,7 +255,6 @@
257
  border-radius: 10px;
258
  margin-bottom: 15px;
259
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
260
- overflow: hidden;
261
  }
262
  .addon-section h6 {
263
  margin: 0;
@@ -341,26 +338,11 @@
341
  }
342
  .addon-options {
343
  max-height: 500px;
344
- overflow: hidden;
345
  transition: max-height 0.3s ease;
346
  }
347
  .addon-options.collapsed {
348
  max-height: 0;
349
- }
350
- .addon-loading {
351
- display: flex;
352
- justify-content: center;
353
- align-items: center;
354
- padding: 15px;
355
- }
356
- .addon-loading::after {
357
- content: '';
358
- width: 20px;
359
- height: 20px;
360
- border: 3px solid #0FAA39;
361
- border-top: 3px solid transparent;
362
- border-radius: 50%;
363
- animation: spin 1s linear infinite;
364
  }
365
  /* Soft Drinks Modal Styling */
366
  #softDrinkModal .modal-dialog {
@@ -393,7 +375,7 @@
393
  #softDrinkModal .modal-body img {
394
  max-height: 160px;
395
  width: 100%;
396
- object-fit: cover;
397
  border-radius: 8px;
398
  margin-bottom: 15px;
399
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
@@ -527,7 +509,7 @@
527
  #veg-toggle:checked {
528
  background-color: #0FAA39; /* Green when on */
529
  }
530
- /* Customized Dish Toggle Retains Original Styling */
531
  #category-CustomizedDish:checked {
532
  background: linear-gradient(45deg, #32CD32, #3CB371);
533
  }
@@ -596,7 +578,7 @@
596
  #micModal .modal-body #mic-item-image {
597
  max-height: 150px;
598
  width: 100%;
599
- object-fit: cover;
600
  border-radius: 8px;
601
  margin-bottom: 10px;
602
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
@@ -624,10 +606,6 @@
624
  from { transform: scale(0); }
625
  to { transform: scale(1); }
626
  }
627
- @keyframes spin {
628
- 0% { transform: rotate(0deg); }
629
- 100% { transform: rotate(360deg); }
630
- }
631
  @keyframes fadeIn {
632
  from { opacity: 0; transform: translateY(10px); }
633
  to { opacity: 1; transform: translateY(0); }
@@ -656,7 +634,7 @@
656
  .modal-body #modal-img {
657
  max-height: 200px;
658
  width: 100%;
659
- object-fit: cover;
660
  border-radius: 8px;
661
  margin-bottom: 10px;
662
  }
@@ -862,12 +840,12 @@
862
  .bottom-action-bar .btn-order-history {
863
  background: linear-gradient(45deg, #FFA07A, #FF69B4, #0FAA39);
864
  border-color: transparent;
865
- color: #000000; /* Black text */
866
  }
867
  .bottom-action-bar .btn-order-history:hover {
868
  background: linear-gradient(45deg, #FF8C61, #FF1493, #0D9232);
869
  border-color: transparent;
870
- color: #000000; /* Black text on hover */
871
  }
872
  .bottom-action-bar .btn-view-cart {
873
  background-color: #0FAA39;
@@ -950,6 +928,7 @@
950
  max-width: 150px;
951
  margin: 0 auto 8px;
952
  display: block;
 
953
  }
954
  .modal-body #modal-name {
955
  font-size: 18px;
@@ -1043,7 +1022,6 @@
1043
  font-size: 10px;
1044
  margin-left: 5px;
1045
  }
1046
- /* Mobile-Specific Addon Styles */
1047
  .addon-section {
1048
  margin-bottom: 10px;
1049
  }
@@ -1072,7 +1050,6 @@
1072
  margin-left: 6px;
1073
  font-size: 0.8rem;
1074
  }
1075
- /* Mobile-Specific Soft Drinks Modal Styles */
1076
  #softDrinkModal .modal-dialog {
1077
  max-width: 90%;
1078
  }
@@ -1124,7 +1101,6 @@
1124
  font-size: 1rem;
1125
  line-height: 28px;
1126
  }
1127
- /* Mobile-Specific Filter Form Styles */
1128
  #filter-form {
1129
  margin-bottom: 15px;
1130
  }
@@ -1150,7 +1126,6 @@
1150
  .toggle-container label {
1151
  font-size: 0.9rem;
1152
  }
1153
- /* Mobile-Specific Microphone Modal Styles */
1154
  #micModal .modal-dialog {
1155
  max-width: 90%;
1156
  }
@@ -1198,7 +1173,6 @@
1198
  <form method="get" action="/menu" class="text-center mb-4" id="filter-form">
1199
  <label class="form-label fw-bold">Filters:</label>
1200
  <div class="toggle-container">
1201
- <!-- Veg Only Toggle -->
1202
  <input type="checkbox" id="veg-toggle" name="veg"
1203
  {% if selected_category == "Veg" %}checked{% endif %}
1204
  class="custom-toggle" onchange="handleToggle('veg')"
@@ -1206,7 +1180,6 @@
1206
  <label for="veg-toggle">Veg</label>
1207
  </div>
1208
  <div class="toggle-container">
1209
- <!-- Customized Dish Toggle -->
1210
  <input type="radio" id="category-CustomizedDish" name="category" value="Customized Dish"
1211
  {% if selected_category == "Customized Dish" %}checked{% endif %}
1212
  class="custom-toggle" onchange="handleToggle('custom')"
@@ -1247,9 +1220,9 @@
1247
  class="menu-image"
1248
  src="{{ item.Image1__c | default('/static/placeholder.jpg') }}"
1249
  alt="{{ item.Name | default('Unnamed Item') }}"
1250
- loading="lazy"
1251
- decoding="async"
1252
- fetchpriority="low">
1253
  <video
1254
  class="menu-video"
1255
  muted
@@ -1257,7 +1230,6 @@
1257
  preload="metadata"
1258
  width="350"
1259
  height="200"
1260
- loading="lazy"
1261
  fetchpriority="low"
1262
  onerror="this.classList.remove('active'); this.previousElementSibling.classList.remove('hidden');">
1263
  <source src="{{ item.Video1__c | default('/static/placeholder.mp4') }}" type="video/mp4">
@@ -1337,13 +1309,13 @@
1337
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
1338
  </div>
1339
  <div class="modal-body">
1340
- <img id="modal-img" class="img-fluid rounded mb-3 d-block mx-auto" alt="Item Image" style="max-height: 200px; object-fit: cover;" loading="lazy" decoding="async">
1341
  <h5 id="modal-name" class="fw-bold text-center"></h5>
1342
  <p id="modal-price" class="text-muted text-center"></p>
1343
  <p id="modal-description" class="text-secondary"></p>
1344
  <div id="modal-addons" class="modal-addons mt-4">
1345
  <h5>Customization Options</h5>
1346
- <div id="addons-list" class="addons-container addon-loading"></div>
1347
  </div>
1348
  <div class="mt-4">
1349
  <h6>Special Instructions</h6>
@@ -1372,7 +1344,7 @@
1372
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
1373
  </div>
1374
  <div class="modal-body">
1375
- <img id="soft-drink-image" class="img-fluid rounded mb-3 d-block mx-auto" alt="Soft Drink Image" loading="lazy" decoding="async">
1376
  <div class="text-center mb-3">
1377
  <h5 id="soft-drink-name"></h5>
1378
  <p id="soft-drink-price"></p>
@@ -1405,7 +1377,7 @@
1405
  <i class="bi bi-mic" id="mic-icon-animation"></i>
1406
  <p id="mic-status" class="mt-3">Say the name of a menu item...</p>
1407
  <div id="mic-item-details" style="display: none;">
1408
- <img id="mic-item-image" class="img-fluid rounded mb-3 d-block mx-auto" alt="Spoken Item Image" loading="lazy" decoding="async">
1409
  <h5 id="mic-item-name" class="fw-bold text-center"></h5>
1410
  </div>
1411
  </div>
@@ -1448,6 +1420,7 @@
1448
  "Tomato Ketchup", "Tomatoes", "Turmeric Powder", "Vinegar", "Water", "Wheat Flour (for dough)",
1449
  "Whole Wheat Flour", "Yogurt (Curd)"
1450
  ];
 
1451
  function addToCartLocalStorage(payload) {
1452
  let cart = JSON.parse(localStorage.getItem('cart')) || [];
1453
  const existingItem = cart.find(item =>
@@ -1463,6 +1436,7 @@
1463
  localStorage.setItem('cart', JSON.stringify(cart));
1464
  return cart;
1465
  }
 
1466
  function removeFromCartLocalStorage(itemName, quantityToRemove, instructions, addons) {
1467
  let cart = JSON.parse(localStorage.getItem('cart')) || [];
1468
  const itemIndex = cart.findIndex(item =>
@@ -1480,9 +1454,11 @@
1480
  localStorage.setItem('cart', JSON.stringify(cart));
1481
  return cart;
1482
  }
 
1483
  function getCartLocalStorage() {
1484
  return JSON.parse(localStorage.getItem('cart')) || [];
1485
  }
 
1486
  function debounce(func, wait) {
1487
  let timeout;
1488
  return function (...args) {
@@ -1490,6 +1466,7 @@
1490
  timeout = setTimeout(() => func.apply(this, args), wait);
1491
  };
1492
  }
 
1493
  function updateModalPrice() {
1494
  const selectedAddOns = Array.from(
1495
  document.querySelectorAll('#addons-list input[type="checkbox"]:checked')
@@ -1498,12 +1475,14 @@
1498
  const totalPrice = baseItemPrice + totalAddOnPrice;
1499
  document.getElementById('modal-price').innerText = `$${totalPrice.toFixed(2)}`;
1500
  }
 
1501
  function updateSoftDrinkQuantity(delta) {
1502
  const quantityInput = document.getElementById('soft-drink-quantity');
1503
  let currentQuantity = parseInt(quantityInput.value) || 1;
1504
  currentQuantity = Math.max(1, currentQuantity + delta);
1505
  quantityInput.value = currentQuantity;
1506
  }
 
1507
  function showSoftDrinkModal(button) {
1508
  currentSoftDrinkButton = button;
1509
  const buttonContainer = button.closest('.button-container');
@@ -1519,6 +1498,7 @@
1519
  const modal = new bootstrap.Modal(document.getElementById('softDrinkModal'));
1520
  modal.show();
1521
  }
 
1522
  function addSoftDrinkToCart() {
1523
  if (!currentSoftDrinkButton) return;
1524
 
@@ -1571,6 +1551,7 @@
1571
  modal.hide();
1572
  });
1573
  }
 
1574
  function updateCartUI(cart) {
1575
  if (!Array.isArray(cart)) {
1576
  console.error('Invalid cart data:', cart);
@@ -1586,8 +1567,10 @@
1586
  cartItemCount.style.display = totalQuantity > 0 ? 'inline-flex' : 'none';
1587
  }
1588
  }
 
1589
  window.most_common_addons = {{ most_common_addons | tojson }};
1590
  console.log("Most common add-ons: ", window.most_common_addons);
 
1591
  function showItemDetails(name, price, image, description, section, selectedCategory) {
1592
  document.getElementById('modal-name').innerText = name;
1593
  baseItemPrice = parseFloat(price) || 0;
@@ -1596,17 +1579,16 @@
1596
  modalImg.src = image || '/static/placeholder.jpg';
1597
  document.getElementById('modal-description').innerText = description || 'No description available.';
1598
  document.getElementById('addons-list').innerHTML = '';
1599
- document.getElementById('addons-list').classList.add('addon-loading');
1600
  document.getElementById('modal-instructions').value = '';
1601
  const modalSectionEl = document.getElementById('modal-section');
1602
  modalSectionEl.setAttribute('data-section', section);
1603
  modalSectionEl.setAttribute('data-category', selectedCategory);
1604
  document.getElementById('quantityInput').value = 1;
 
1605
  fetch(`/api/addons?item_name=${encodeURIComponent(name)}&item_section=${encodeURIComponent(section)}`)
1606
  .then(response => response.json())
1607
  .then(data => {
1608
  const addonsList = document.getElementById('addons-list');
1609
- addonsList.classList.remove('addon-loading');
1610
  addonsList.innerHTML = '';
1611
  if (!data.success || !data.addons || data.addons.length === 0) {
1612
  addonsList.innerHTML = '<p>No customization options available.</p>';
@@ -1698,10 +1680,10 @@
1698
  })
1699
  .catch(err => {
1700
  console.error('Error fetching add-ons:', err);
1701
- document.getElementById('addons-list').classList.remove('addon-loading');
1702
  document.getElementById('addons-list').innerHTML = '<p>Error loading customization options.</p>';
1703
  });
1704
  }
 
1705
  function addToCartFromModal() {
1706
  if (isProcessingRequest) return;
1707
  isProcessingRequest = true;
@@ -1767,6 +1749,7 @@
1767
  isProcessingRequest = false;
1768
  });
1769
  }
 
1770
  function handleToggle(source) {
1771
  const form = document.getElementById("filter-form");
1772
  const veg = document.getElementById("veg-toggle");
@@ -1785,6 +1768,7 @@
1785
  }
1786
  form.submit();
1787
  }
 
1788
  function stopSpeechRecognition() {
1789
  if (recognition) {
1790
  recognition.stop();
@@ -1796,6 +1780,7 @@
1796
  }
1797
  }
1798
  }
 
1799
  function resetMicModal() {
1800
  document.getElementById('mic-status').textContent = 'Say the name of a menu item...';
1801
  document.getElementById('mic-status').style.display = 'block';
@@ -1803,6 +1788,7 @@
1803
  document.getElementById('mic-item-image').src = '';
1804
  document.getElementById('mic-item-name').textContent = '';
1805
  }
 
1806
  document.addEventListener('DOMContentLoaded', function () {
1807
  const avatarContainer = document.querySelector('.avatar-dropdown-container');
1808
  const dropdownMenu = document.querySelector('.dropdown-menu');
@@ -1825,6 +1811,7 @@
1825
  searchBar.addEventListener('click', function () {
1826
  window.location.href = '/search';
1827
  });
 
1828
  const selectedItem = localStorage.getItem('selectedItem');
1829
  if (selectedItem) {
1830
  try {
@@ -1844,32 +1831,32 @@
1844
  if (toggleLink) {
1845
  toggleLink.click();
1846
  }
1847
- }
1848
- });
1849
- if (targetCard && buttonContainer) {
1850
- const name = buttonContainer.getAttribute('data-item-name');
1851
- const price = buttonContainer.getAttribute('data-item-price');
1852
- const image = buttonContainer.getAttribute('data-item-image2');
1853
- const description = buttonContainer.getAttribute('data-item-description');
1854
- const category = buttonContainer.getAttribute('data-item-category');
1855
- setTimeout(() => {
1856
- if (section === 'Soft Drinks') {
1857
- showSoftDrinkModal(buttonContainer.querySelector('.add-to-cart-btn'));
1858
- } else {
1859
- showItemDetails(name, price, image, description, section, category);
1860
- const modal = new bootstrap.Modal(document.getElementById('itemModal'));
1861
- modal.show();
1862
- }
1863
- }, 1000);
1864
  }
1865
- } catch (e) {
1866
- console.error('Error parsing selectedItem:', e);
1867
- } finally {
1868
- localStorage.removeItem('selectedItem');
 
 
 
 
 
 
 
 
 
 
 
 
1869
  }
 
 
 
 
1870
  }
 
1871
 
1872
- // Image-to-Video hover/touch functionality
1873
  const mediaWrappers = document.querySelectorAll('.media-wrapper');
1874
  mediaWrappers.forEach(wrapper => {
1875
  const video = wrapper.querySelector('.menu-video');
 
8
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
9
  <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">
10
  <!-- Preload Critical Resources -->
11
+ <link rel="preload" href="/static/placeholder.jpg" as="image" fetchpriority="high">
12
  {% for section, items in ordered_menu.items() %}
13
  {% for item in items[:1] %}
14
+ <link rel="preload" href="{{ item.Image1__c | default('/static/placeholder.jpg') }}" as="image" fetchpriority="high">
15
  {% endfor %}
16
  {% endfor %}
17
  <style>
 
30
  .menu-card {
31
  max-width: 350px;
32
  border-radius: 15px;
 
33
  background-color: #fff;
34
  margin: auto;
35
  display: flex;
 
44
  position: relative;
45
  width: 100%;
46
  height: 200px;
 
47
  border-radius: 15px 15px 0 0;
 
48
  transition: transform 0.3s ease;
49
  }
50
  .media-wrapper:hover, .media-wrapper.touched {
 
65
  }
66
  .menu-image {
67
  position: absolute;
68
+ top: 50%;
69
+ left: 50%;
70
+ transform: translate(-50%, -50%);
71
  width: 100%;
72
  height: 100%;
73
+ object-fit: contain;
74
  opacity: 1;
75
  transition: opacity 0.3s ease;
76
  }
 
255
  border-radius: 10px;
256
  margin-bottom: 15px;
257
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
 
258
  }
259
  .addon-section h6 {
260
  margin: 0;
 
338
  }
339
  .addon-options {
340
  max-height: 500px;
 
341
  transition: max-height 0.3s ease;
342
  }
343
  .addon-options.collapsed {
344
  max-height: 0;
345
+ overflow: hidden;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
346
  }
347
  /* Soft Drinks Modal Styling */
348
  #softDrinkModal .modal-dialog {
 
375
  #softDrinkModal .modal-body img {
376
  max-height: 160px;
377
  width: 100%;
378
+ object-fit: contain;
379
  border-radius: 8px;
380
  margin-bottom: 15px;
381
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
 
509
  #veg-toggle:checked {
510
  background-color: #0FAA39; /* Green when on */
511
  }
512
+ /* Customized Dish Toggle */
513
  #category-CustomizedDish:checked {
514
  background: linear-gradient(45deg, #32CD32, #3CB371);
515
  }
 
578
  #micModal .modal-body #mic-item-image {
579
  max-height: 150px;
580
  width: 100%;
581
+ object-fit: contain;
582
  border-radius: 8px;
583
  margin-bottom: 10px;
584
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
 
606
  from { transform: scale(0); }
607
  to { transform: scale(1); }
608
  }
 
 
 
 
609
  @keyframes fadeIn {
610
  from { opacity: 0; transform: translateY(10px); }
611
  to { opacity: 1; transform: translateY(0); }
 
634
  .modal-body #modal-img {
635
  max-height: 200px;
636
  width: 100%;
637
+ object-fit: contain;
638
  border-radius: 8px;
639
  margin-bottom: 10px;
640
  }
 
840
  .bottom-action-bar .btn-order-history {
841
  background: linear-gradient(45deg, #FFA07A, #FF69B4, #0FAA39);
842
  border-color: transparent;
843
+ color: #000000;
844
  }
845
  .bottom-action-bar .btn-order-history:hover {
846
  background: linear-gradient(45deg, #FF8C61, #FF1493, #0D9232);
847
  border-color: transparent;
848
+ color: #000000;
849
  }
850
  .bottom-action-bar .btn-view-cart {
851
  background-color: #0FAA39;
 
928
  max-width: 150px;
929
  margin: 0 auto 8px;
930
  display: block;
931
+ object-fit: contain;
932
  }
933
  .modal-body #modal-name {
934
  font-size: 18px;
 
1022
  font-size: 10px;
1023
  margin-left: 5px;
1024
  }
 
1025
  .addon-section {
1026
  margin-bottom: 10px;
1027
  }
 
1050
  margin-left: 6px;
1051
  font-size: 0.8rem;
1052
  }
 
1053
  #softDrinkModal .modal-dialog {
1054
  max-width: 90%;
1055
  }
 
1101
  font-size: 1rem;
1102
  line-height: 28px;
1103
  }
 
1104
  #filter-form {
1105
  margin-bottom: 15px;
1106
  }
 
1126
  .toggle-container label {
1127
  font-size: 0.9rem;
1128
  }
 
1129
  #micModal .modal-dialog {
1130
  max-width: 90%;
1131
  }
 
1173
  <form method="get" action="/menu" class="text-center mb-4" id="filter-form">
1174
  <label class="form-label fw-bold">Filters:</label>
1175
  <div class="toggle-container">
 
1176
  <input type="checkbox" id="veg-toggle" name="veg"
1177
  {% if selected_category == "Veg" %}checked{% endif %}
1178
  class="custom-toggle" onchange="handleToggle('veg')"
 
1180
  <label for="veg-toggle">Veg</label>
1181
  </div>
1182
  <div class="toggle-container">
 
1183
  <input type="radio" id="category-CustomizedDish" name="category" value="Customized Dish"
1184
  {% if selected_category == "Customized Dish" %}checked{% endif %}
1185
  class="custom-toggle" onchange="handleToggle('custom')"
 
1220
  class="menu-image"
1221
  src="{{ item.Image1__c | default('/static/placeholder.jpg') }}"
1222
  alt="{{ item.Name | default('Unnamed Item') }}"
1223
+ preload="auto"
1224
+ fetchpriority="high"
1225
+ decoding="async">
1226
  <video
1227
  class="menu-video"
1228
  muted
 
1230
  preload="metadata"
1231
  width="350"
1232
  height="200"
 
1233
  fetchpriority="low"
1234
  onerror="this.classList.remove('active'); this.previousElementSibling.classList.remove('hidden');">
1235
  <source src="{{ item.Video1__c | default('/static/placeholder.mp4') }}" type="video/mp4">
 
1309
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
1310
  </div>
1311
  <div class="modal-body">
1312
+ <img id="modal-img" class="img-fluid rounded mb-3 d-block mx-auto" alt="Item Image" preload="auto" fetchpriority="high" decoding="async">
1313
  <h5 id="modal-name" class="fw-bold text-center"></h5>
1314
  <p id="modal-price" class="text-muted text-center"></p>
1315
  <p id="modal-description" class="text-secondary"></p>
1316
  <div id="modal-addons" class="modal-addons mt-4">
1317
  <h5>Customization Options</h5>
1318
+ <div id="addons-list" class="addons-container"></div>
1319
  </div>
1320
  <div class="mt-4">
1321
  <h6>Special Instructions</h6>
 
1344
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
1345
  </div>
1346
  <div class="modal-body">
1347
+ <img id="soft-drink-image" class="img-fluid rounded mb-3 d-block mx-auto" alt="Soft Drink Image" preload="auto" fetchpriority="high" decoding="async">
1348
  <div class="text-center mb-3">
1349
  <h5 id="soft-drink-name"></h5>
1350
  <p id="soft-drink-price"></p>
 
1377
  <i class="bi bi-mic" id="mic-icon-animation"></i>
1378
  <p id="mic-status" class="mt-3">Say the name of a menu item...</p>
1379
  <div id="mic-item-details" style="display: none;">
1380
+ <img id="mic-item-image" class="img-fluid rounded mb-3 d-block mx-auto" alt="Spoken Item Image" preload="auto" fetchpriority="high" decoding="async">
1381
  <h5 id="mic-item-name" class="fw-bold text-center"></h5>
1382
  </div>
1383
  </div>
 
1420
  "Tomato Ketchup", "Tomatoes", "Turmeric Powder", "Vinegar", "Water", "Wheat Flour (for dough)",
1421
  "Whole Wheat Flour", "Yogurt (Curd)"
1422
  ];
1423
+
1424
  function addToCartLocalStorage(payload) {
1425
  let cart = JSON.parse(localStorage.getItem('cart')) || [];
1426
  const existingItem = cart.find(item =>
 
1436
  localStorage.setItem('cart', JSON.stringify(cart));
1437
  return cart;
1438
  }
1439
+
1440
  function removeFromCartLocalStorage(itemName, quantityToRemove, instructions, addons) {
1441
  let cart = JSON.parse(localStorage.getItem('cart')) || [];
1442
  const itemIndex = cart.findIndex(item =>
 
1454
  localStorage.setItem('cart', JSON.stringify(cart));
1455
  return cart;
1456
  }
1457
+
1458
  function getCartLocalStorage() {
1459
  return JSON.parse(localStorage.getItem('cart')) || [];
1460
  }
1461
+
1462
  function debounce(func, wait) {
1463
  let timeout;
1464
  return function (...args) {
 
1466
  timeout = setTimeout(() => func.apply(this, args), wait);
1467
  };
1468
  }
1469
+
1470
  function updateModalPrice() {
1471
  const selectedAddOns = Array.from(
1472
  document.querySelectorAll('#addons-list input[type="checkbox"]:checked')
 
1475
  const totalPrice = baseItemPrice + totalAddOnPrice;
1476
  document.getElementById('modal-price').innerText = `$${totalPrice.toFixed(2)}`;
1477
  }
1478
+
1479
  function updateSoftDrinkQuantity(delta) {
1480
  const quantityInput = document.getElementById('soft-drink-quantity');
1481
  let currentQuantity = parseInt(quantityInput.value) || 1;
1482
  currentQuantity = Math.max(1, currentQuantity + delta);
1483
  quantityInput.value = currentQuantity;
1484
  }
1485
+
1486
  function showSoftDrinkModal(button) {
1487
  currentSoftDrinkButton = button;
1488
  const buttonContainer = button.closest('.button-container');
 
1498
  const modal = new bootstrap.Modal(document.getElementById('softDrinkModal'));
1499
  modal.show();
1500
  }
1501
+
1502
  function addSoftDrinkToCart() {
1503
  if (!currentSoftDrinkButton) return;
1504
 
 
1551
  modal.hide();
1552
  });
1553
  }
1554
+
1555
  function updateCartUI(cart) {
1556
  if (!Array.isArray(cart)) {
1557
  console.error('Invalid cart data:', cart);
 
1567
  cartItemCount.style.display = totalQuantity > 0 ? 'inline-flex' : 'none';
1568
  }
1569
  }
1570
+
1571
  window.most_common_addons = {{ most_common_addons | tojson }};
1572
  console.log("Most common add-ons: ", window.most_common_addons);
1573
+
1574
  function showItemDetails(name, price, image, description, section, selectedCategory) {
1575
  document.getElementById('modal-name').innerText = name;
1576
  baseItemPrice = parseFloat(price) || 0;
 
1579
  modalImg.src = image || '/static/placeholder.jpg';
1580
  document.getElementById('modal-description').innerText = description || 'No description available.';
1581
  document.getElementById('addons-list').innerHTML = '';
 
1582
  document.getElementById('modal-instructions').value = '';
1583
  const modalSectionEl = document.getElementById('modal-section');
1584
  modalSectionEl.setAttribute('data-section', section);
1585
  modalSectionEl.setAttribute('data-category', selectedCategory);
1586
  document.getElementById('quantityInput').value = 1;
1587
+
1588
  fetch(`/api/addons?item_name=${encodeURIComponent(name)}&item_section=${encodeURIComponent(section)}`)
1589
  .then(response => response.json())
1590
  .then(data => {
1591
  const addonsList = document.getElementById('addons-list');
 
1592
  addonsList.innerHTML = '';
1593
  if (!data.success || !data.addons || data.addons.length === 0) {
1594
  addonsList.innerHTML = '<p>No customization options available.</p>';
 
1680
  })
1681
  .catch(err => {
1682
  console.error('Error fetching add-ons:', err);
 
1683
  document.getElementById('addons-list').innerHTML = '<p>Error loading customization options.</p>';
1684
  });
1685
  }
1686
+
1687
  function addToCartFromModal() {
1688
  if (isProcessingRequest) return;
1689
  isProcessingRequest = true;
 
1749
  isProcessingRequest = false;
1750
  });
1751
  }
1752
+
1753
  function handleToggle(source) {
1754
  const form = document.getElementById("filter-form");
1755
  const veg = document.getElementById("veg-toggle");
 
1768
  }
1769
  form.submit();
1770
  }
1771
+
1772
  function stopSpeechRecognition() {
1773
  if (recognition) {
1774
  recognition.stop();
 
1780
  }
1781
  }
1782
  }
1783
+
1784
  function resetMicModal() {
1785
  document.getElementById('mic-status').textContent = 'Say the name of a menu item...';
1786
  document.getElementById('mic-status').style.display = 'block';
 
1788
  document.getElementById('mic-item-image').src = '';
1789
  document.getElementById('mic-item-name').textContent = '';
1790
  }
1791
+
1792
  document.addEventListener('DOMContentLoaded', function () {
1793
  const avatarContainer = document.querySelector('.avatar-dropdown-container');
1794
  const dropdownMenu = document.querySelector('.dropdown-menu');
 
1811
  searchBar.addEventListener('click', function () {
1812
  window.location.href = '/search';
1813
  });
1814
+
1815
  const selectedItem = localStorage.getItem('selectedItem');
1816
  if (selectedItem) {
1817
  try {
 
1831
  if (toggleLink) {
1832
  toggleLink.click();
1833
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1834
  }
1835
+ });
1836
+ if (targetCard && buttonContainer) {
1837
+ const name = buttonContainer.getAttribute('data-item-name');
1838
+ const price = buttonContainer.getAttribute('data-item-price');
1839
+ const image = buttonContainer.getAttribute('data-item-image2');
1840
+ const description = buttonContainer.getAttribute('data-item-description');
1841
+ const category = buttonContainer.getAttribute('data-item-category');
1842
+ setTimeout(() => {
1843
+ if (section === 'Soft Drinks') {
1844
+ showSoftDrinkModal(buttonContainer.querySelector('.add-to-cart-btn'));
1845
+ } else {
1846
+ showItemDetails(name, price, image, description, section, category);
1847
+ const modal = new bootstrap.Modal(document.getElementById('itemModal'));
1848
+ modal.show();
1849
+ }
1850
+ }, 1000);
1851
  }
1852
+ } catch (e) {
1853
+ console.error('Error parsing selectedItem:', e);
1854
+ } finally {
1855
+ localStorage.removeItem('selectedItem');
1856
  }
1857
+ }
1858
 
1859
+ // Image-to-Video hover/touch functionality
1860
  const mediaWrappers = document.querySelectorAll('.media-wrapper');
1861
  mediaWrappers.forEach(wrapper => {
1862
  const video = wrapper.querySelector('.menu-video');