lokeshloki143 commited on
Commit
8580a47
·
verified ·
1 Parent(s): 3cfa13d

Update templates/menu.html

Browse files
Files changed (1) hide show
  1. templates/menu.html +358 -284
templates/menu.html CHANGED
@@ -36,6 +36,10 @@
36
  display: flex;
37
  flex-direction: column;
38
  box-shadow: 0 4px 8px rgba(0,0,0,0.1);
 
 
 
 
39
  }
40
  .menu-card.highlighted {
41
  border: 3px solid #0FAA39;
@@ -78,6 +82,7 @@
78
  transition: opacity 0.3s ease;
79
  }
80
  .menu-image.hidden {
 
81
  opacity: 0;
82
  }
83
  .menu-card .card-body .card-title {
@@ -93,18 +98,19 @@
93
  margin-bottom: 5px;
94
  }
95
  .addbutton .btn {
96
- background-color: #28a745;
97
  color: white;
98
  padding: 10px 20px;
99
  font-size: 16px;
100
  font-weight: bold;
101
- border-radius: 5px;
102
  border: none;
103
- transition: background-color 0.3s ease;
104
  margin-left: 13px;
105
  }
106
  .addbutton .btn:hover {
107
- background-color: #218838;
 
108
  }
109
  .button-container {
110
  display: flex;
@@ -133,11 +139,12 @@
133
  align-items: center;
134
  justify-content: center;
135
  padding: 0;
136
- transition: background-color 0.3s ease;
137
  }
138
  .btn-primary:hover {
139
  background-color: #0D9232;
140
  border-color: #0D9232;
 
141
  }
142
  .btn-primary:active,
143
  .btn-primary:focus {
@@ -236,6 +243,7 @@
236
  justify-content: space-between;
237
  align-items: center;
238
  z-index: 1000;
 
239
  }
240
  .search-bar-container {
241
  position: absolute;
@@ -257,13 +265,14 @@
257
  background-color: #fff;
258
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
259
  outline: none;
 
 
 
 
260
  }
261
  .search-bar-container input::placeholder {
262
  color: #888;
263
  }
264
- .search-bar-container input:focus {
265
- border-bottom: 2px solid #FFA07A;
266
- }
267
  .search-icon {
268
  position: absolute;
269
  left: 15px;
@@ -276,10 +285,15 @@
276
  font-size: 18px;
277
  color: #888;
278
  cursor: pointer;
279
- transition: color 0.3s ease;
 
 
 
 
280
  }
281
  .mic-icon.active {
282
  color: #DC3545;
 
283
  }
284
  /* Addon Section */
285
  .addon-section {
@@ -401,7 +415,7 @@
401
  #softDrinkModal .modal-content {
402
  border-radius: 12px;
403
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
404
- background-color: #fff;
405
  overflow: hidden;
406
  }
407
  #softDrinkModal .modal-header {
@@ -428,6 +442,10 @@
428
  border-radius: 8px;
429
  margin-bottom: 15px;
430
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
 
 
 
 
431
  }
432
  #softDrinkModal .modal-body h5 {
433
  font-size: 1.4rem;
@@ -455,26 +473,27 @@
455
  margin-bottom: 20px;
456
  }
457
  #softDrinkModal .quantity-controls .btn {
458
- width: 40px;
459
- height: 40px;
460
  border-radius: 50%;
461
  padding: 0;
462
- font-size: 1.2rem;
463
- line-height: 40px;
464
  text-align: center;
465
  background-color: #e9ecef;
466
  border: none;
467
  color: #333;
468
- transition: background-color 0.2s ease;
469
  }
470
  #softDrinkModal .quantity-controls .btn:hover {
471
  background-color: #d1d4d7;
 
472
  }
473
  #softDrinkModal .quantity-controls input {
474
  width: 60px;
475
- height: 40px;
476
  text-align: center;
477
- font-size: 1.1rem;
478
  font-weight: 600;
479
  border: 1px solid #ced4da;
480
  border-radius: 6px;
@@ -489,18 +508,59 @@
489
  #softDrinkModal .modal-footer .btn-primary {
490
  background-color: #0FAA39;
491
  border-color: #0FAA39;
492
- padding: 10px 30px;
493
  text-align: center;
494
- font-size: 1rem;
495
  font-weight: 600;
496
  border-radius: 8px;
497
- transition: background-color 0.2s ease;
498
  width: auto;
499
  }
500
  #softDrinkModal .modal-footer .btn-primary:hover {
501
  background-color: #0D9232;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
502
  }
503
- /* Item Modal Quantity Controls */
504
  #itemModal .quantity-controls {
505
  display: flex;
506
  justify-content: center;
@@ -509,31 +569,45 @@
509
  margin-bottom: 20px;
510
  }
511
  #itemModal .quantity-controls .btn {
512
- width: 40px;
513
- height: 40px;
514
  border-radius: 50%;
515
  padding: 0;
516
- font-size: 1.2rem;
517
- line-height: 40px;
518
  text-align: center;
519
  background-color: #e9ecef;
520
  border: none;
521
  color: #333;
522
- transition: background-color 0.2s ease;
523
  }
524
  #itemModal .quantity-controls .btn:hover {
525
  background-color: #d1d4d7;
 
526
  }
527
  #itemModal .quantity-controls input {
528
  width: 60px;
529
- height: 40px;
530
  text-align: center;
531
- font-size: 1.1rem;
532
  font-weight: 600;
533
  border: 1px solid #ced4da;
534
  border-radius: 6px;
535
  background-color: #f8f9fa;
536
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
537
  /* Filter Form Styling */
538
  #filter-form {
539
  display: flex;
@@ -602,7 +676,7 @@
602
  #micModal .modal-content {
603
  border-radius: 12px;
604
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
605
- background-color: #fff;
606
  text-align: center;
607
  }
608
  #micModal .modal-header {
@@ -625,12 +699,26 @@
625
  align-items: center;
626
  gap: 15px;
627
  min-height: 200px;
 
628
  }
629
  #micModal .modal-body i#mic-icon-animation {
630
  font-size: 2.5rem;
631
  color: #DC3545;
 
632
  animation: pulse 2s infinite;
633
  }
 
 
 
 
 
 
 
 
 
 
 
 
634
  #micModal .modal-body p#mic-status {
635
  font-size: 1.1rem;
636
  color: #333;
@@ -644,6 +732,14 @@
644
  border-radius: 8px;
645
  margin-bottom: 10px;
646
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
 
 
 
 
 
 
 
 
647
  }
648
  #micModal .modal-body #mic-item-details.show {
649
  animation: fadeIn 0.3s ease;
@@ -659,11 +755,63 @@
659
  padding: 10px 20px;
660
  font-size: 1rem;
661
  border-radius: 8px;
 
662
  }
663
  #micModal .modal-footer .btn-secondary:hover {
664
  background-color: #5a6268;
665
- border-color: #5a6268;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
666
  }
 
 
 
 
667
  @keyframes checkmark {
668
  from { transform: scale(0); }
669
  to { transform: scale(1); }
@@ -685,6 +833,17 @@
685
  50% { transform: scale(1.2); }
686
  100% { transform: scale(1); }
687
  }
 
 
 
 
 
 
 
 
 
 
 
688
  .modal-header {
689
  padding: 10px 15px;
690
  }
@@ -905,6 +1064,10 @@
905
  text-align: center;
906
  min-width: 0;
907
  white-space: nowrap;
 
 
 
 
908
  }
909
  .bottom-action-bar .btn-order-history {
910
  background: linear-gradient(45deg, #FF8C00, #32CD32);
@@ -913,7 +1076,6 @@
913
  }
914
  .bottom-action-bar .btn-order-history:hover {
915
  background: linear-gradient(45deg, #FF4500, #228B22);
916
- border-color: transparent;
917
  color: #000000;
918
  }
919
  .bottom-action-bar .btn-view-cart {
@@ -923,7 +1085,6 @@
923
  }
924
  .bottom-action-bar .btn-view-cart:hover {
925
  background-color: #0D9232;
926
- border-color: #0D9232;
927
  color: white;
928
  }
929
  .cart-icon-badge {
@@ -937,6 +1098,7 @@
937
  justify-content: center;
938
  font-size: 12px;
939
  margin-left: 8px;
 
940
  }
941
  /* Mobile-Specific Styles */
942
  @media (max-width: 576px) {
@@ -1156,38 +1318,45 @@
1156
  margin-bottom: 15px;
1157
  }
1158
  #softDrinkModal .quantity-controls .btn {
1159
- width: 32px;
1160
- height: 32px;
1161
- font-size: 1rem;
1162
- line-height: 32px;
1163
  }
1164
  #softDrinkModal .quantity-controls input {
1165
  width: 50px;
1166
- height: 32px;
1167
- font-size: 0.9rem;
1168
  }
1169
  #softDrinkModal .modal-footer {
1170
  padding: 10px;
1171
  }
1172
  #softDrinkModal .modal-footer .btn-primary {
1173
- padding: 8px 20px;
1174
- font-size: 0.9rem;
1175
  }
1176
  /* Mobile-Specific Item Modal Styles */
 
 
 
 
 
 
 
1177
  #itemModal .quantity-controls .btn {
1178
- width: 32px;
1179
- height: 32px;
1180
- font-size: 1rem;
1181
- line-height: 32px;
1182
  }
1183
  #itemModal .quantity-controls input {
1184
  width: 50px;
1185
- height: 32px;
1186
- font-size: 0.9rem;
1187
  }
1188
  #itemModal .modal-footer .btn-primary {
1189
- padding: 8px 15px;
1190
- font-size: 0.9rem;
1191
  }
1192
  /* Mobile-Specific Filter Form Styles */
1193
  #filter-form {
@@ -1238,43 +1407,10 @@
1238
  padding: 8px 15px;
1239
  font-size: 0.9rem;
1240
  }
1241
- }
1242
- .autocomplete-suggestions {
1243
- position: absolute;
1244
- top: 100%;
1245
- left: 0;
1246
- right: 0;
1247
- background-color: #fff;
1248
- border: 1px solid #ced4da;
1249
- border-radius: 4px;
1250
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
1251
- max-height: 150px;
1252
- overflow-y: auto;
1253
- z-index: 1000;
1254
- display: none;
1255
- }
1256
- .autocomplete-suggestion {
1257
- padding: 8px 12px;
1258
- cursor: pointer;
1259
- font-size: 0.9rem;
1260
- color: #333;
1261
- transition: background-color 0.2s ease;
1262
- }
1263
- .autocomplete-suggestion:hover {
1264
- background-color: #e6f4ea;
1265
- }
1266
- .autocomplete-suggestions::-webkit-scrollbar {
1267
- width: 6px;
1268
- }
1269
- .autocomplete-suggestions::-webkit-scrollbar-track {
1270
- background: #f1f1f1;
1271
- }
1272
- .autocomplete-suggestions::-webkit-scrollbar-thumb {
1273
- background: #0FAA39;
1274
- border-radius: 10px;
1275
- }
1276
- .autocomplete-suggestions::-webkit-scrollbar-thumb:hover {
1277
- background: #0D9232;
1278
  }
1279
  </style>
1280
  </head>
@@ -1334,7 +1470,7 @@
1334
  <div id="descriptionSuggestions" class="autocomplete-suggestions"></div>
1335
  </div>
1336
  <button type="submit" class="btn btn-primary">Submit Custom Dish</button>
1337
- </form>
1338
  </div>
1339
  {% else %}
1340
  {% if ordered_menu.items()|length == 0 %}
@@ -1389,7 +1525,10 @@
1389
  <button class="btn btn-primary"
1390
  data-bs-toggle="modal"
1391
  data-bs-target="#itemModal"
1392
- onclick="showItemDetails('{{ item.Name | default('Unnamed Item') }}', '{{ item.Price__c | default('0.00') }}', '{{ item.Image2__c | default(item.Image1__c) }}', '{{ item.Description__c | default('No description') }}', '{{ item.Section__c | default(section) }}', '{{ selected_category }}')">
 
 
 
1393
  ADD
1394
  </button>
1395
  {% if item.Section__c != 'Apetizer' and item.Section__c != 'Customized dish' %}
@@ -1713,126 +1852,84 @@
1713
  addonsList.classList.remove('addon-loading');
1714
  addonsList.innerHTML = '';
1715
  if (!data.success || !data.addons || data.addons.length === 0) {
1716
- addonsList.innerHTML = '<p>No customization options available.</p>';
1717
- return;
1718
- }
1719
- data.addons.forEach(addon => {
1720
- const sectionDiv = document.createElement('div');
1721
- sectionDiv.classList.add('addon-section');
1722
- const title = document.createElement('h6');
1723
- title.innerText = addon.name;
1724
- sectionDiv.appendChild(title);
1725
- const optionsContainer = document.createElement('div');
1726
- optionsContainer.classList.add('addon-options');
1727
- addon.options.forEach((option, index) => {
1728
- const optionId = `addon-${addon.name.replace(/\s+/g, '')}-${index}`;
1729
- const listItem = document.createElement('div');
1730
- listItem.classList.add('form-check');
1731
- listItem.innerHTML = `
1732
- <input type="checkbox" class="form-check-input addon-option" id="${optionId}" value="${option}"
1733
- data-name="${option}" data-group="${addon.name}" data-price="${addon.extra_charge ? addon.extra_charge_amount : 0}"
1734
- aria-label="Select ${option} for ${addon.name}">
1735
- <label class="form-check-label" for="${optionId}">
1736
- ${option} ${addon.extra_charge ? `<span class="extra-charge">($${addon.extra_charge_amount.toFixed(2)})</span>` : ''}
1737
- </label>
1738
- `;
1739
- optionsContainer.appendChild(listItem);
1740
- });
1741
- sectionDiv.appendChild(optionsContainer);
1742
- addonsList.appendChild(sectionDiv);
1743
- });
1744
- const addonSections = addonsList.querySelectorAll('.addon-section');
1745
- addonSections.forEach(section => {
1746
- const title = section.querySelector('h6');
1747
- const options = section.querySelector('.addon-options');
1748
- title.addEventListener('click', () => {
1749
- section.classList.toggle('collapsed');
1750
- options.classList.toggle('collapsed');
1751
- });
1752
- });
1753
- document.querySelectorAll('.addon-option').forEach(checkbox => {
1754
- checkbox.addEventListener('change', updateModalPrice);
1755
- });
1756
- document.querySelectorAll('.addon-option').forEach(checkbox => {
1757
- checkbox.addEventListener('change', function () {
1758
- const groupName = this.getAttribute('data-group');
1759
- const isMultiSelectGroup = ["Extra Toppings", "Choose Raita/Sides", "Select Dip/Sauce", "Extra Add-ons", "Make it a Combo", "Beverages", "Sauces"].includes(groupName);
1760
- if (!isMultiSelectGroup && this.checked) {
1761
- document.querySelectorAll(`.addon-option[data-group="${groupName}"]`).forEach(otherCheckbox => {
1762
- if (otherCheckbox !== this) {
1763
- otherCheckbox.checked = false;
1764
- }
1765
- });
1766
- }
1767
- });
1768
- });
1769
- if (window.most_common_addons && window.most_common_addons.length > 0) {
1770
- const checkboxes = document.querySelectorAll('.addon-option');
1771
- const categorySelection = {
1772
- "Select Spice Level": null,
1773
- "Choose Spice Level": null,
1774
- "Raita/Sides": [],
1775
- };
1776
- for (let spice of window.most_common_addons) {
1777
- const isSpiceLevel = ["Mild", "Medium", "Spicy", "Extra Spicy"].includes(spice);
1778
- if (isSpiceLevel) {
1779
- checkboxes.forEach(checkbox => {
1780
- const checkboxName = checkbox.getAttribute('data-name').trim();
1781
- const checkboxGroup = checkbox.getAttribute('data-group');
1782
- if ((checkboxGroup === "Select Spice Level" || checkboxGroup === "Choose Spice Level") &&
1783
- checkboxName === spice && categorySelection[checkboxGroup] === null) {
1784
- console.log(`Pre-selecting highest-count spice level: ${checkboxName}`);
1785
- checkbox.checked = true;
1786
- categorySelection[checkboxGroup] = checkboxName;
1787
- }
1788
- });
1789
- if (categorySelection["Select Spice Level"] || categorySelection["Choose Spice Level"]) break;
1790
- }
1791
- }
1792
- checkboxes.forEach(checkbox => {
1793
- const checkboxName = checkbox.getAttribute('data-name').trim();
1794
- const checkboxGroup = checkbox.getAttribute('data-group');
1795
- if (checkboxGroup === "Raita/Sides" && window.most_common_addons.includes(checkboxName)) {
1796
- console.log(`Pre-selecting add-on: ${checkboxName}`);
1797
- checkbox.checked = true;
1798
- categorySelection["Raita/Sides"].push(checkboxName);
1799
- }
1800
  });
1801
  }
1802
  })
1803
  .catch(err => {
1804
- console.error('Error fetching add-ons:', err);
1805
- document.getElementById('addons-list').classList.remove('addon-loading');
1806
- document.getElementById('addons-list').innerHTML = '<p>Error loading customization options.</p>';
 
1807
  });
1808
  }
1809
  function addToCartFromModal() {
1810
  if (isProcessingRequest) return;
1811
  isProcessingRequest = true;
1812
- const modalSectionEl = document.getElementById('modal-section');
1813
- const section = modalSectionEl.getAttribute('data-section');
1814
- const selectedCategory = modalSectionEl.getAttribute('data-category');
1815
  const itemName = document.getElementById('modal-name').innerText;
1816
- const itemPrice = parseFloat(document.getElementById('modal-price').innerText.replace('$', '')) || 0;
1817
- const itemImage = document.getElementById('modal-img').src;
1818
  const quantity = parseInt(document.getElementById('quantityInput').value) || 1;
1819
  const instructions = document.getElementById('modal-instructions').value;
1820
  const selectedAddOns = Array.from(
1821
  document.querySelectorAll('#addons-list input[type="checkbox"]:checked')
1822
  ).map(addon => ({
 
1823
  name: addon.getAttribute('data-name'),
1824
  price: parseFloat(addon.getAttribute('data-price')) || 0
1825
  }));
1826
- if (!itemName || isNaN(itemPrice) || !section || !itemImage || quantity < 1) {
1827
- console.error('Invalid cart item data:', { itemName, itemPrice, section, itemImage, quantity });
1828
- alert('Invalid item data. Please try again.');
1829
- isProcessingRequest = false;
1830
- return;
1831
- }
1832
  const cartPayload = {
1833
  itemName: itemName,
1834
- itemPrice: itemPrice,
1835
- itemImage: itemImage,
1836
  section: section,
1837
  category: selectedCategory,
1838
  addons: selectedAddOns,
@@ -1848,6 +1945,7 @@
1848
  })
1849
  .then(response => response.json())
1850
  .then(data => {
 
1851
  if (data.success) {
1852
  updateCartUI(data.cart);
1853
  const modal = bootstrap.Modal.getInstance(document.getElementById('itemModal'));
@@ -1861,38 +1959,28 @@
1861
  }
1862
  })
1863
  .catch(err => {
 
1864
  console.error('Error adding item to cart:', err);
1865
  const cart = addToCartLocalStorage(cartPayload);
1866
  updateCartUI(cart);
1867
  const modal = bootstrap.Modal.getInstance(document.getElementById('itemModal'));
1868
  modal.hide();
1869
- })
1870
- .finally(() => {
1871
- isProcessingRequest = false;
1872
  });
1873
  }
1874
- function handleToggle(source) {
1875
- const form = document.getElementById("filter-form");
1876
- const veg = document.getElementById("veg-toggle");
1877
- const custom = document.getElementById("category-CustomizedDish");
1878
- if (source === 'veg') {
1879
- if (veg.checked) {
1880
- custom.checked = false;
1881
- }
1882
- } else if (source === 'custom') {
1883
- if (custom.checked) {
1884
- veg.checked = false;
1885
- }
1886
- }
1887
- if (!custom.checked && !veg.checked) {
1888
- custom.checked = false;
1889
- }
1890
- form.submit();
1891
  }
1892
  function stopSpeechRecognition() {
1893
  if (recognition) {
1894
  recognition.stop();
1895
- document.getElementById('micIcon').classList.remove('active');
1896
  const micModal = bootstrap.Modal.getInstance(document.getElementById('micModal'));
1897
  if (micModal) {
1898
  micModal.hide();
@@ -1900,30 +1988,34 @@
1900
  }
1901
  }
1902
  }
1903
- function resetMicModal() {
1904
- document.getElementById('mic-status').textContent = 'Say the name of a menu item...';
1905
- document.getElementById('mic-status').style.display = 'block';
1906
- document.getElementById('mic-item-details').style.display = 'none';
1907
- document.getElementById('mic-item-image').src = '';
1908
- document.getElementById('mic-item-name').textContent = '';
 
 
 
 
 
 
 
 
1909
  }
1910
  document.addEventListener('DOMContentLoaded', function () {
1911
- const avatarIcon = document.querySelector('.avatar-icon');
1912
  const dropdownMenu = document.querySelector('.dropdown-menu');
1913
-
1914
  avatarIcon.addEventListener('click', function () {
1915
  dropdownMenu.classList.toggle('show');
1916
  });
1917
-
1918
  document.addEventListener('click', function (event) {
1919
  if (!avatarIcon.contains(event.target) && !dropdownMenu.contains(event.target)) {
1920
  dropdownMenu.classList.remove('show');
1921
  }
1922
  });
1923
-
1924
  const searchBar = document.getElementById('searchBar');
1925
  const searchSuggestions = document.getElementById('searchSuggestions');
1926
-
1927
  searchBar.addEventListener('input', debounce(function () {
1928
  const query = searchBar.value.trim().toLowerCase();
1929
  searchSuggestions.innerHTML = '';
@@ -1931,20 +2023,23 @@
1931
  searchSuggestions.style.display = 'none';
1932
  return;
1933
  }
1934
-
1935
  const filteredItems = menuItems.filter(item =>
1936
  item.name.toLowerCase().includes(query) || item.section.toLowerCase().includes(query)
1937
  );
1938
-
1939
  if (filteredItems.length === 0) {
1940
  searchSuggestions.style.display = 'none';
1941
  return;
1942
  }
1943
-
1944
  filteredItems.forEach(item => {
1945
  const suggestion = document.createElement('div');
1946
  suggestion.classList.add('autocomplete-suggestion');
1947
- suggestion.textContent = item.name;
 
 
 
 
 
 
1948
  suggestion.addEventListener('click', () => {
1949
  const card = document.querySelector(`.menu-card[data-item-name="${item.name}"]`);
1950
  if (card) {
@@ -1973,16 +2068,13 @@
1973
  });
1974
  searchSuggestions.appendChild(suggestion);
1975
  });
1976
-
1977
  searchSuggestions.style.display = 'block';
1978
  }, 300));
1979
-
1980
  document.addEventListener('click', function (event) {
1981
  if (!searchBar.contains(event.target) && !searchSuggestions.contains(event.target)) {
1982
  searchSuggestions.style.display = 'none';
1983
  }
1984
  });
1985
-
1986
  if (localStorage.getItem('selectedItem')) {
1987
  try {
1988
  const selectedItem = JSON.parse(localStorage.getItem('selectedItem'));
@@ -2013,11 +2105,9 @@
2013
  localStorage.removeItem('selectedItem');
2014
  }
2015
  }
2016
-
2017
  document.querySelectorAll('.media-wrapper').forEach(wrapper => {
2018
  const video = wrapper.querySelector('.menu-video');
2019
  const image = wrapper.querySelector('.menu-image');
2020
-
2021
  wrapper.addEventListener('mouseenter', () => {
2022
  image.classList.add('hidden');
2023
  video.classList.add('active');
@@ -2033,7 +2123,6 @@
2033
  video.currentTime = 0;
2034
  image.classList.remove('hidden');
2035
  });
2036
-
2037
  let touchTimeout;
2038
  wrapper.addEventListener('touchstart', (e) => {
2039
  e.preventDefault();
@@ -2057,23 +2146,19 @@
2057
  }, 500);
2058
  });
2059
  });
2060
-
2061
  const decreaseBtn = document.getElementById('decreaseQuantity');
2062
  const increaseBtn = document.getElementById('increaseQuantity');
2063
  const quantityInput = document.getElementById('quantityInput');
2064
-
2065
  decreaseBtn.addEventListener('click', () => {
2066
  let value = parseInt(quantityInput.value) || 1;
2067
  if (value > 1) {
2068
  quantityInput.value = value - 1;
2069
  }
2070
  });
2071
-
2072
  increaseBtn.addEventListener('click', () => {
2073
  let value = parseInt(quantityInput.value) || 1;
2074
  quantityInput.value = value + 1;
2075
  });
2076
-
2077
  document.querySelectorAll('.toggle-details').forEach(link => {
2078
  link.addEventListener('click', () => {
2079
  const details = link.nextElementSibling;
@@ -2086,7 +2171,6 @@
2086
  }
2087
  });
2088
  });
2089
-
2090
  fetch('/cart')
2091
  .then(response => response.json())
2092
  .then(data => {
@@ -2100,74 +2184,73 @@
2100
  console.error('Error fetching cart:', err);
2101
  updateCartUI(getCartLocalStorage());
2102
  });
2103
-
2104
  if ('webkitSpeechRecognition' in window) {
2105
  recognition = new webkitSpeechRecognition();
2106
  recognition.continuous = false;
2107
  recognition.interimResults = false;
2108
  recognition.lang = 'en-US';
2109
-
2110
  recognition.onstart = () => {
2111
- document.getElementById('micIcon').classList.add('active');
2112
  document.getElementById('mic-status').textContent = 'Listening...';
2113
  };
2114
-
2115
  recognition.onresult = (event) => {
2116
  const transcript = event.results[0][0].transcript.trim().toLowerCase();
2117
  console.log('Recognized speech:', transcript);
2118
  const matchedItem = menuItems.find(item =>
2119
  item.name.toLowerCase().includes(transcript)
2120
  );
2121
-
2122
  if (matchedItem) {
2123
- recognition.stop();
2124
- document.getElementById('mic-status').style.display = 'none';
2125
- document.getElementById('mic-item-details').style.display = 'block';
2126
- document.getElementById('mic-item-name').textContent = matchedItem.name;
2127
- document.getElementById('mic-item-image').src = matchedItem.image || '/static/placeholder.jpg';
2128
-
2129
- const card = document.querySelector(`.menu-card[data-item-name="${matchedItem.name}"]`);
2130
- if (card) {
2131
- card.classList.add('highlighted');
2132
- card.scrollIntoView({ behavior: 'smooth', block: 'center' });
2133
- const buttonContainer = card.querySelector('.button-container');
2134
- if (buttonContainer) {
2135
- if (matchedItem.section === 'Soft Drinks') {
2136
- showSoftDrinkModal(buttonContainer.querySelector('.add-to-cart-btn'));
2137
- } else {
2138
- showItemDetails(
2139
- matchedItem.name,
2140
- matchedItem.price,
2141
- matchedItem.image2 || matchedItem.image,
2142
- matchedItem.description,
2143
- matchedItem.section,
2144
- matchedItem.category
2145
- );
2146
- const modal = new bootstrap.Modal(document.getElementById('itemModal'));
2147
- modal.show();
 
 
 
 
 
 
 
 
 
 
 
2148
  }
2149
  }
2150
- const micModal = bootstrap.Modal.getInstance(document.getElementById('micModal'));
2151
- if (micModal) {
2152
- micModal.hide();
2153
- resetMicModal();
2154
- }
2155
- }
2156
  } else {
2157
  document.getElementById('mic-status').textContent = 'Item not found. Try again.';
2158
  }
2159
  };
2160
-
2161
  recognition.onerror = (event) => {
2162
  console.error('Speech recognition error:', event.error);
2163
  document.getElementById('mic-status').textContent = 'Error occurred. Please try again.';
2164
- document.getElementById('micIcon').classList.remove('active');
2165
  };
2166
-
2167
  recognition.onend = () => {
2168
- document.getElementById('micIcon').classList.remove('active');
2169
  };
2170
-
2171
  document.getElementById('micIcon').addEventListener('click', () => {
2172
  if (!recognition) return;
2173
  const micModal = new bootstrap.Modal(document.getElementById('micModal'));
@@ -2175,34 +2258,27 @@
2175
  resetMicModal();
2176
  recognition.start();
2177
  });
2178
-
2179
  document.getElementById('stopMicBtn').addEventListener('click', stopSpeechRecognition);
2180
  } else {
2181
  document.getElementById('micIcon').style.display = 'none';
2182
  }
2183
-
2184
  const descriptionInput = document.getElementById('custom-dish-description');
2185
  const suggestionsContainer = document.getElementById('descriptionSuggestions');
2186
-
2187
  if (descriptionInput && suggestionsContainer) {
2188
  descriptionInput.addEventListener('input', debounce(() => {
2189
  const query = descriptionInput.value.toLowerCase();
2190
  suggestionsContainer.innerHTML = '';
2191
-
2192
  if (query.length < 2) {
2193
  suggestionsContainer.style.display = 'none';
2194
  return;
2195
  }
2196
-
2197
  const filteredIngredients = ingredientsList.filter(ingredient =>
2198
  ingredient.toLowerCase().includes(query)
2199
  );
2200
-
2201
  if (filteredIngredients.length === 0) {
2202
  suggestionsContainer.style.display = 'none';
2203
  return;
2204
  }
2205
-
2206
  filteredIngredients.forEach(ingredient => {
2207
  const suggestionItem = document.createElement('div');
2208
  suggestionItem.classList.add('autocomplete-suggestion');
@@ -2218,10 +2294,8 @@
2218
  });
2219
  suggestionsContainer.appendChild(suggestionItem);
2220
  });
2221
-
2222
  suggestionsContainer.style.display = 'block';
2223
  }, 300));
2224
-
2225
  document.addEventListener('click', (event) => {
2226
  if (!descriptionInput.contains(event.target) && !suggestionsContainer.contains(event.target)) {
2227
  suggestionsContainer.style.display = 'none';
 
36
  display: flex;
37
  flex-direction: column;
38
  box-shadow: 0 4px 8px rgba(0,0,0,0.1);
39
+ transition: transform 0.2s ease;
40
+ }
41
+ .menu-card:hover {
42
+ transform: translateY(-5px);
43
  }
44
  .menu-card.highlighted {
45
  border: 3px solid #0FAA39;
 
82
  transition: opacity 0.3s ease;
83
  }
84
  .menu-image.hidden {
85
+  W
86
  opacity: 0;
87
  }
88
  .menu-card .card-body .card-title {
 
98
  margin-bottom: 5px;
99
  }
100
  .addbutton .btn {
101
+ background-color: #0FAA39;
102
  color: white;
103
  padding: 10px 20px;
104
  font-size: 16px;
105
  font-weight: bold;
106
+ border-radius: 8px;
107
  border: none;
108
+ transition: background-color 0.3s ease, transform 0.2s ease;
109
  margin-left: 13px;
110
  }
111
  .addbutton .btn:hover {
112
+ background-color: #0D9232;
113
+ transform: scale(1.05);
114
  }
115
  .button-container {
116
  display: flex;
 
139
  align-items: center;
140
  justify-content: center;
141
  padding: 0;
142
+ transition: background-color 0.3s ease, transform 0.2s ease;
143
  }
144
  .btn-primary:hover {
145
  background-color: #0D9232;
146
  border-color: #0D9232;
147
+ transform: scale(1.05);
148
  }
149
  .btn-primary:active,
150
  .btn-primary:focus {
 
243
  justify-content: space-between;
244
  align-items: center;
245
  z-index: 1000;
246
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
247
  }
248
  .search-bar-container {
249
  position: absolute;
 
265
  background-color: #fff;
266
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
267
  outline: none;
268
+ transition: box-shadow 0.2s ease;
269
+ }
270
+ .search-bar-container input:focus {
271
+ box-shadow: 0 0 0 3px rgba(255, 160, 122, 0.3);
272
  }
273
  .search-bar-container input::placeholder {
274
  color: #888;
275
  }
 
 
 
276
  .search-icon {
277
  position: absolute;
278
  left: 15px;
 
285
  font-size: 18px;
286
  color: #888;
287
  cursor: pointer;
288
+ transition: color 0.3s ease, transform 0.2s ease;
289
+ }
290
+ .mic-icon:hover {
291
+ color: #DC3545;
292
+ transform: scale(1.1);
293
  }
294
  .mic-icon.active {
295
  color: #DC3545;
296
+ animation: pulseMic 1.5s infinite;
297
  }
298
  /* Addon Section */
299
  .addon-section {
 
415
  #softDrinkModal .modal-content {
416
  border-radius: 12px;
417
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
418
+ background: linear-gradient(180deg, #ffffff, #f8f9fa);
419
  overflow: hidden;
420
  }
421
  #softDrinkModal .modal-header {
 
442
  border-radius: 8px;
443
  margin-bottom: 15px;
444
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
445
+ transition: transform 0.3s ease;
446
+ }
447
+ #softDrinkModal .modal-body img:hover {
448
+ transform: scale(1.05);
449
  }
450
  #softDrinkModal .modal-body h5 {
451
  font-size: 1.4rem;
 
473
  margin-bottom: 20px;
474
  }
475
  #softDrinkModal .quantity-controls .btn {
476
+ width: 48px;
477
+ height: 48px;
478
  border-radius: 50%;
479
  padding: 0;
480
+ font-size: 1.4rem;
481
+ line-height: 48px;
482
  text-align: center;
483
  background-color: #e9ecef;
484
  border: none;
485
  color: #333;
486
+ transition: background-color 0.2s ease, transform 0.2s ease;
487
  }
488
  #softDrinkModal .quantity-controls .btn:hover {
489
  background-color: #d1d4d7;
490
+ transform: scale(1.1);
491
  }
492
  #softDrinkModal .quantity-controls input {
493
  width: 60px;
494
+ height: 48px;
495
  text-align: center;
496
+ font-size: 1.2rem;
497
  font-weight: 600;
498
  border: 1px solid #ced4da;
499
  border-radius: 6px;
 
508
  #softDrinkModal .modal-footer .btn-primary {
509
  background-color: #0FAA39;
510
  border-color: #0FAA39;
511
+ padding: 12px 40px;
512
  text-align: center;
513
+ font-size: 1.1rem;
514
  font-weight: 600;
515
  border-radius: 8px;
516
+ transition: background-color 0.2s ease, transform 0.2s ease;
517
  width: auto;
518
  }
519
  #softDrinkModal .modal-footer .btn-primary:hover {
520
  background-color: #0D9232;
521
+ transform: scale(1.05);
522
+ }
523
+ /* Item Modal Styling */
524
+ #itemModal .modal-dialog {
525
+ max-width: 500px;
526
+ margin: 1.75rem auto;
527
+ animation: fadeInModal 0.3s ease-out;
528
+ }
529
+ #itemModal .modal-content {
530
+ border-radius: 12px;
531
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
532
+ background: linear-gradient(180deg, #ffffff, #f8f9fa);
533
+ overflow: hidden;
534
+ }
535
+ #itemModal .modal-header {
536
+ background: linear-gradient(45deg, #FFA07A, #FFB347);
537
+ border-top-left-radius: 12px;
538
+ border-top-right-radius: 12px;
539
+ padding: 12px 15px;
540
+ border-bottom: none;
541
+ }
542
+ #itemModal .modal-title {
543
+ font-size: 1.3rem;
544
+ font-weight: 600;
545
+ color: #fff;
546
+ }
547
+ #itemModal .modal-body {
548
+ padding: 20px;
549
+ }
550
+ #itemModal .modal-body img {
551
+ width: 200px;
552
+ height: 200px;
553
+ object-fit: cover;
554
+ aspect-ratio: 1/1;
555
+ border-radius: 8px;
556
+ margin: 0 auto 15px;
557
+ display: block;
558
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
559
+ transition: transform 0.3s ease;
560
+ }
561
+ #itemModal .modal-body img:hover {
562
+ transform: scale(1.05);
563
  }
 
564
  #itemModal .quantity-controls {
565
  display: flex;
566
  justify-content: center;
 
569
  margin-bottom: 20px;
570
  }
571
  #itemModal .quantity-controls .btn {
572
+ width: 48px;
573
+ height: 48px;
574
  border-radius: 50%;
575
  padding: 0;
576
+ font-size: 1.4rem;
577
+ line-height: 48px;
578
  text-align: center;
579
  background-color: #e9ecef;
580
  border: none;
581
  color: #333;
582
+ transition: background-color 0.2s ease, transform 0.2s ease;
583
  }
584
  #itemModal .quantity-controls .btn:hover {
585
  background-color: #d1d4d7;
586
+ transform: scale(1.1);
587
  }
588
  #itemModal .quantity-controls input {
589
  width: 60px;
590
+ height: 48px;
591
  text-align: center;
592
+ font-size: 1.2rem;
593
  font-weight: 600;
594
  border: 1px solid #ced4da;
595
  border-radius: 6px;
596
  background-color: #f8f9fa;
597
  }
598
+ #itemModal .modal-footer .btn-primary {
599
+ background-color: #0FAA39;
600
+ border-color: #0FAA39;
601
+ padding: 12px 40px;
602
+ font-size: 1.1rem;
603
+ font-weight: 600;
604
+ border-radius: 8px;
605
+ transition: background-color 0.2s ease, transform 0.2s ease;
606
+ }
607
+ #itemModal .modal-footer .btn-primary:hover {
608
+ background-color: #0D9232;
609
+ transform: scale(1.05);
610
+ }
611
  /* Filter Form Styling */
612
  #filter-form {
613
  display: flex;
 
676
  #micModal .modal-content {
677
  border-radius: 12px;
678
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
679
+ background: linear-gradient(180deg, #ffffff, #f8f9fa);
680
  text-align: center;
681
  }
682
  #micModal .modal-header {
 
699
  align-items: center;
700
  gap: 15px;
701
  min-height: 200px;
702
+ position: relative;
703
  }
704
  #micModal .modal-body i#mic-icon-animation {
705
  font-size: 2.5rem;
706
  color: #DC3545;
707
+ position: relative;
708
  animation: pulse 2s infinite;
709
  }
710
+ #micModal .modal-body i#mic-icon-animation::before {
711
+ content: '';
712
+ position: absolute;
713
+ top: -10px;
714
+ left: -10px;
715
+ right: -10px;
716
+ bottom: -10px;
717
+ border: 2px solid #DC3545;
718
+ border-radius: 50%;
719
+ opacity: 0.5;
720
+ animation: ripple 2s infinite;
721
+ }
722
  #micModal .modal-body p#mic-status {
723
  font-size: 1.1rem;
724
  color: #333;
 
732
  border-radius: 8px;
733
  margin-bottom: 10px;
734
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
735
+ animation: fadeIn 0.3s ease;
736
+ }
737
+ #micModal .modal-body #mic-item-name {
738
+ font-size: 1.2rem;
739
+ font-weight: 600;
740
+ color: #333;
741
+ margin-bottom: 10px;
742
+ animation: fadeIn 0.3s ease;
743
  }
744
  #micModal .modal-body #mic-item-details.show {
745
  animation: fadeIn 0.3s ease;
 
755
  padding: 10px 20px;
756
  font-size: 1rem;
757
  border-radius: 8px;
758
+ transition: background-color 0.2s ease, transform 0.2s ease;
759
  }
760
  #micModal .modal-footer .btn-secondary:hover {
761
  background-color: #5a6268;
762
+ transform: scale(1.05);
763
+ }
764
+ /* Search Suggestions Styling */
765
+ .autocomplete-suggestions {
766
+ position: absolute;
767
+ top: 100%;
768
+ left: 0;
769
+ right: 0;
770
+ background-color: #fff;
771
+ border: 1px solid #ced4da;
772
+ border-radius: 8px;
773
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
774
+ max-height: 200px;
775
+ overflow-y: auto;
776
+ z-index: 1000;
777
+ display: none;
778
+ animation: slideDown 0.3s ease-out;
779
+ }
780
+ .autocomplete-suggestion {
781
+ display: flex;
782
+ align-items: center;
783
+ padding: 8px 12px;
784
+ cursor: pointer;
785
+ font-size: 0.9rem;
786
+ color: #333;
787
+ transition: background-color 0.2s ease, transform 0.2s ease;
788
+ }
789
+ .autocomplete-suggestion:hover {
790
+ background-color: #e6f4ea;
791
+ transform: translateX(5px);
792
+ }
793
+ .autocomplete-suggestion img {
794
+ width: 40px;
795
+ height: 40px;
796
+ object-fit: cover;
797
+ border-radius: 4px;
798
+ margin-right: 10px;
799
+ }
800
+ .autocomplete-suggestions::-webkit-scrollbar {
801
+ width: 6px;
802
+ }
803
+ .autocomplete-suggestions::-webkit-scrollbar-track {
804
+ background: #f1f1f1;
805
+ border-radius: 10px;
806
+ }
807
+ .autocomplete-suggestions::-webkit-scrollbar-thumb {
808
+ background: #0FAA39;
809
+ border-radius: 10px;
810
  }
811
+ .autocomplete-suggestions::-webkit-scrollbar-thumb:hover {
812
+ background: #0D9232;
813
+ }
814
+ /* Animations */
815
  @keyframes checkmark {
816
  from { transform: scale(0); }
817
  to { transform: scale(1); }
 
833
  50% { transform: scale(1.2); }
834
  100% { transform: scale(1); }
835
  }
836
+ @keyframes pulseMic {
837
+ 0% { transform: scale(1); }
838
+ 50% { transform: scale(1.15); }
839
+ 100% { transform: scale(1); }
840
+ }
841
+ @keyframes ripple {
842
+ 0% { transform: scale(0.8); opacity: 0.5; }
843
+ 50% { transform: scale(1.2); opacity: 0.2; }
844
+ 100% { transform: scale(1.6); opacity: 0; }
845
+ }
846
+ /* Modal General Styles */
847
  .modal-header {
848
  padding: 10px 15px;
849
  }
 
1064
  text-align: center;
1065
  min-width: 0;
1066
  white-space: nowrap;
1067
+ transition: transform 0.2s ease;
1068
+ }
1069
+ .bottom-action-bar .btn:hover {
1070
+ transform: scale(1.05);
1071
  }
1072
  .bottom-action-bar .btn-order-history {
1073
  background: linear-gradient(45deg, #FF8C00, #32CD32);
 
1076
  }
1077
  .bottom-action-bar .btn-order-history:hover {
1078
  background: linear-gradient(45deg, #FF4500, #228B22);
 
1079
  color: #000000;
1080
  }
1081
  .bottom-action-bar .btn-view-cart {
 
1085
  }
1086
  .bottom-action-bar .btn-view-cart:hover {
1087
  background-color: #0D9232;
 
1088
  color: white;
1089
  }
1090
  .cart-icon-badge {
 
1098
  justify-content: center;
1099
  font-size: 12px;
1100
  margin-left: 8px;
1101
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
1102
  }
1103
  /* Mobile-Specific Styles */
1104
  @media (max-width: 576px) {
 
1318
  margin-bottom: 15px;
1319
  }
1320
  #softDrinkModal .quantity-controls .btn {
1321
+ width: 40px;
1322
+ height: 40px;
1323
+ font-size: 1.2rem;
1324
+ line-height: 40px;
1325
  }
1326
  #softDrinkModal .quantity-controls input {
1327
  width: 50px;
1328
+ height: 40px;
1329
+ font-size: 1rem;
1330
  }
1331
  #softDrinkModal .modal-footer {
1332
  padding: 10px;
1333
  }
1334
  #softDrinkModal .modal-footer .btn-primary {
1335
+ padding: 10px 30px;
1336
+ font-size: 1rem;
1337
  }
1338
  /* Mobile-Specific Item Modal Styles */
1339
+ #itemModal .modal-dialog {
1340
+ max-width: 90%;
1341
+ }
1342
+ #itemModal .modal-body img {
1343
+ width: 150px;
1344
+ height: 150px;
1345
+ }
1346
  #itemModal .quantity-controls .btn {
1347
+ width: 40px;
1348
+ height: 40px;
1349
+ font-size: 1.2rem;
1350
+ line-height: 40px;
1351
  }
1352
  #itemModal .quantity-controls input {
1353
  width: 50px;
1354
+ height: 40px;
1355
+ font-size: 1rem;
1356
  }
1357
  #itemModal .modal-footer .btn-primary {
1358
+ padding: 10px 30px;
1359
+ font-size: 1rem;
1360
  }
1361
  /* Mobile-Specific Filter Form Styles */
1362
  #filter-form {
 
1407
  padding: 8px 15px;
1408
  font-size: 0.9rem;
1409
  }
1410
+ .autocomplete-suggestion img {
1411
+ width: 32px;
1412
+ height: 32px;
1413
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1414
  }
1415
  </style>
1416
  </head>
 
1470
  <div id="descriptionSuggestions" class="autocomplete-suggestions"></div>
1471
  </div>
1472
  <button type="submit" class="btn btn-primary">Submit Custom Dish</button>
1473
+ </form>
1474
  </div>
1475
  {% else %}
1476
  {% if ordered_menu.items()|length == 0 %}
 
1525
  <button class="btn btn-primary"
1526
  data-bs-toggle="modal"
1527
  data-bs-target="#itemModal"
1528
+ onclick="showItemDetails('{{ item.Name | default('Unnamed Item') }}', '{{ item.Price__c | default('0.00') }}', '{{ item.Image 🙂
1529
+
1530
+ System: ```javascript
1531
+ 2__c | default(item.Image1__c) }}', '{{ item.Description__c | default('No description') }}', '{{ item.Section__c | default(section) }}', '{{ selected_category }}')">
1532
  ADD
1533
  </button>
1534
  {% if item.Section__c != 'Apetizer' and item.Section__c != 'Customized dish' %}
 
1852
  addonsList.classList.remove('addon-loading');
1853
  addonsList.innerHTML = '';
1854
  if (!data.success || !data.addons || data.addons.length === 0) {
1855
+ const noAddonsMessage = document.createElement('p');
1856
+ noAddonsMessage.textContent = 'No add-ons available for this item.';
1857
+ noAddonsMessage.className = 'text-muted';
1858
+ addonsList.appendChild(noAddonsMessage);
1859
+ } else {
1860
+ data.addons.forEach(addon => {
1861
+ const addonSection = document.createElement('div');
1862
+ addonSection.className = 'addon-section';
1863
+ const addonHeader = document.createElement('h6');
1864
+ addonHeader.textContent = addon.section;
1865
+ addonHeader.setAttribute('data-bs-toggle', 'collapse');
1866
+ addonHeader.setAttribute('data-bs-target', `#addon-collapse-${addon.section.replace(/\s+/g, '-')}`);
1867
+ addonHeader.setAttribute('aria-expanded', 'true');
1868
+ addonHeader.setAttribute('aria-controls', `addon-collapse-${addon.section.replace(/\s+/g, '-')}`);
1869
+ addonSection.appendChild(addonHeader);
1870
+ const addonCollapse = document.createElement('div');
1871
+ addonCollapse.id = `addon-collapse-${addon.section.replace(/\s+/g, '-')}`;
1872
+ addonCollapse.className = 'addon-options collapse show';
1873
+ addon.items.forEach(item => {
1874
+ const addonItem = document.createElement('div');
1875
+ addonItem.className = 'form-check';
1876
+ const input = document.createElement('input');
1877
+ input.type = 'checkbox';
1878
+ input.className = 'form-check-input';
1879
+ input.id = `addon-${item.name.replace(/\s+/g, '-')}`;
1880
+ input.setAttribute('data-price', item.price || 0);
1881
+ input.setAttribute('data-name', item.name);
1882
+ input.setAttribute('data-section', addon.section);
1883
+ input.addEventListener('change', updateModalPrice);
1884
+ const label = document.createElement('label');
1885
+ label.className = 'form-check-label';
1886
+ label.htmlFor = `addon-${item.name.replace(/\s+/g, '-')}`;
1887
+ label.textContent = item.name;
1888
+ if (item.price > 0) {
1889
+ const priceSpan = document.createElement('span');
1890
+ priceSpan.className = 'extra-charge';
1891
+ priceSpan.textContent = `+$${parseFloat(item.price).toFixed(2)}`;
1892
+ label.appendChild(priceSpan);
1893
+ }
1894
+ addonItem.appendChild(label);
1895
+ addonItem.appendChild(input);
1896
+ addonCollapse.appendChild(addonItem);
1897
+ });
1898
+ addonSection.appendChild(addonCollapse);
1899
+ addonsList.appendChild(addonSection);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1900
  });
1901
  }
1902
  })
1903
  .catch(err => {
1904
+ console.error('Error fetching addons:', err);
1905
+ const addonsList = document.getElementById('addons-list');
1906
+ addonsList.classList.remove('addon-loading');
1907
+ addonsList.innerHTML = '<p class="text-muted">Failed to load add-ons.</p>';
1908
  });
1909
  }
1910
  function addToCartFromModal() {
1911
  if (isProcessingRequest) return;
1912
  isProcessingRequest = true;
 
 
 
1913
  const itemName = document.getElementById('modal-name').innerText;
 
 
1914
  const quantity = parseInt(document.getElementById('quantityInput').value) || 1;
1915
  const instructions = document.getElementById('modal-instructions').value;
1916
  const selectedAddOns = Array.from(
1917
  document.querySelectorAll('#addons-list input[type="checkbox"]:checked')
1918
  ).map(addon => ({
1919
+ section: addon.getAttribute('data-section'),
1920
  name: addon.getAttribute('data-name'),
1921
  price: parseFloat(addon.getAttribute('data-price')) || 0
1922
  }));
1923
+ const modalSectionEl = document.getElementById('modal-section');
1924
+ const section = modalSectionEl.getAttribute('data-section');
1925
+ const selectedCategory = modalSectionEl.getAttribute('data-category');
1926
+ const totalAddOnPrice = selectedAddOns.reduce((sum, addon) => sum + addon.price, 0);
1927
+ const totalPrice = (baseItemPrice + totalAddOnPrice);
1928
+ const modalImg = document.getElementById('modal-img').src;
1929
  const cartPayload = {
1930
  itemName: itemName,
1931
+ itemPrice: totalPrice,
1932
+ itemImage: modalImg,
1933
  section: section,
1934
  category: selectedCategory,
1935
  addons: selectedAddOns,
 
1945
  })
1946
  .then(response => response.json())
1947
  .then(data => {
1948
+ isProcessingRequest = false;
1949
  if (data.success) {
1950
  updateCartUI(data.cart);
1951
  const modal = bootstrap.Modal.getInstance(document.getElementById('itemModal'));
 
1959
  }
1960
  })
1961
  .catch(err => {
1962
+ isProcessingRequest = false;
1963
  console.error('Error adding item to cart:', err);
1964
  const cart = addToCartLocalStorage(cartPayload);
1965
  updateCartUI(cart);
1966
  const modal = bootstrap.Modal.getInstance(document.getElementById('itemModal'));
1967
  modal.hide();
 
 
 
1968
  });
1969
  }
1970
+ function resetMicModal() {
1971
+ const micStatus = document.getElementById('mic-status');
1972
+ const micItemDetails = document.getElementById('mic-item-details');
1973
+ const micItemName = document.getElementById('mic-item-name');
1974
+ const micItemImage = document.getElementById('mic-item-image');
1975
+ micStatus.textContent = 'Say the name of a menu item...';
1976
+ micStatus.style.display = 'block';
1977
+ micItemDetails.style.display = 'none';
1978
+ micItemName.textContent = '';
1979
+ micItemImage.src = '/static/placeholder.jpg';
 
 
 
 
 
 
 
1980
  }
1981
  function stopSpeechRecognition() {
1982
  if (recognition) {
1983
  recognition.stop();
 
1984
  const micModal = bootstrap.Modal.getInstance(document.getElementById('micModal'));
1985
  if (micModal) {
1986
  micModal.hide();
 
1988
  }
1989
  }
1990
  }
1991
+ function handleToggle(toggleType) {
1992
+ const vegToggle = document.getElementById('veg-toggle');
1993
+ const customToggle = document.getElementById('category-CustomizedDish');
1994
+ let url = '/menu?';
1995
+ const params = [];
1996
+ if (toggleType === 'veg' && vegToggle.checked) {
1997
+ params.push('veg=Veg');
1998
+ customToggle.checked = false;
1999
+ } else if (toggleType === 'custom' && customToggle.checked) {
2000
+ params.push('category=Customized+Dish');
2001
+ vegToggle.checked = false;
2002
+ }
2003
+ url += params.join('&');
2004
+ window.location.href = url;
2005
  }
2006
  document.addEventListener('DOMContentLoaded', function () {
2007
+ const avatarIcon = document.querySelector('.avatar-icon');
2008
  const dropdownMenu = document.querySelector('.dropdown-menu');
 
2009
  avatarIcon.addEventListener('click', function () {
2010
  dropdownMenu.classList.toggle('show');
2011
  });
 
2012
  document.addEventListener('click', function (event) {
2013
  if (!avatarIcon.contains(event.target) && !dropdownMenu.contains(event.target)) {
2014
  dropdownMenu.classList.remove('show');
2015
  }
2016
  });
 
2017
  const searchBar = document.getElementById('searchBar');
2018
  const searchSuggestions = document.getElementById('searchSuggestions');
 
2019
  searchBar.addEventListener('input', debounce(function () {
2020
  const query = searchBar.value.trim().toLowerCase();
2021
  searchSuggestions.innerHTML = '';
 
2023
  searchSuggestions.style.display = 'none';
2024
  return;
2025
  }
 
2026
  const filteredItems = menuItems.filter(item =>
2027
  item.name.toLowerCase().includes(query) || item.section.toLowerCase().includes(query)
2028
  );
 
2029
  if (filteredItems.length === 0) {
2030
  searchSuggestions.style.display = 'none';
2031
  return;
2032
  }
 
2033
  filteredItems.forEach(item => {
2034
  const suggestion = document.createElement('div');
2035
  suggestion.classList.add('autocomplete-suggestion');
2036
+ const img = document.createElement('img');
2037
+ img.src = item.image || '/static/placeholder.jpg';
2038
+ img.alt = item.name;
2039
+ suggestion.appendChild(img);
2040
+ const text = document.createElement('span');
2041
+ text.textContent = item.name;
2042
+ suggestion.appendChild(text);
2043
  suggestion.addEventListener('click', () => {
2044
  const card = document.querySelector(`.menu-card[data-item-name="${item.name}"]`);
2045
  if (card) {
 
2068
  });
2069
  searchSuggestions.appendChild(suggestion);
2070
  });
 
2071
  searchSuggestions.style.display = 'block';
2072
  }, 300));
 
2073
  document.addEventListener('click', function (event) {
2074
  if (!searchBar.contains(event.target) && !searchSuggestions.contains(event.target)) {
2075
  searchSuggestions.style.display = 'none';
2076
  }
2077
  });
 
2078
  if (localStorage.getItem('selectedItem')) {
2079
  try {
2080
  const selectedItem = JSON.parse(localStorage.getItem('selectedItem'));
 
2105
  localStorage.removeItem('selectedItem');
2106
  }
2107
  }
 
2108
  document.querySelectorAll('.media-wrapper').forEach(wrapper => {
2109
  const video = wrapper.querySelector('.menu-video');
2110
  const image = wrapper.querySelector('.menu-image');
 
2111
  wrapper.addEventListener('mouseenter', () => {
2112
  image.classList.add('hidden');
2113
  video.classList.add('active');
 
2123
  video.currentTime = 0;
2124
  image.classList.remove('hidden');
2125
  });
 
2126
  let touchTimeout;
2127
  wrapper.addEventListener('touchstart', (e) => {
2128
  e.preventDefault();
 
2146
  }, 500);
2147
  });
2148
  });
 
2149
  const decreaseBtn = document.getElementById('decreaseQuantity');
2150
  const increaseBtn = document.getElementById('increaseQuantity');
2151
  const quantityInput = document.getElementById('quantityInput');
 
2152
  decreaseBtn.addEventListener('click', () => {
2153
  let value = parseInt(quantityInput.value) || 1;
2154
  if (value > 1) {
2155
  quantityInput.value = value - 1;
2156
  }
2157
  });
 
2158
  increaseBtn.addEventListener('click', () => {
2159
  let value = parseInt(quantityInput.value) || 1;
2160
  quantityInput.value = value + 1;
2161
  });
 
2162
  document.querySelectorAll('.toggle-details').forEach(link => {
2163
  link.addEventListener('click', () => {
2164
  const details = link.nextElementSibling;
 
2171
  }
2172
  });
2173
  });
 
2174
  fetch('/cart')
2175
  .then(response => response.json())
2176
  .then(data => {
 
2184
  console.error('Error fetching cart:', err);
2185
  updateCartUI(getCartLocalStorage());
2186
  });
 
2187
  if ('webkitSpeechRecognition' in window) {
2188
  recognition = new webkitSpeechRecognition();
2189
  recognition.continuous = false;
2190
  recognition.interimResults = false;
2191
  recognition.lang = 'en-US';
 
2192
  recognition.onstart = () => {
2193
+ document.getElementById('mic-icon-animation').classList.add('active');
2194
  document.getElementById('mic-status').textContent = 'Listening...';
2195
  };
 
2196
  recognition.onresult = (event) => {
2197
  const transcript = event.results[0][0].transcript.trim().toLowerCase();
2198
  console.log('Recognized speech:', transcript);
2199
  const matchedItem = menuItems.find(item =>
2200
  item.name.toLowerCase().includes(transcript)
2201
  );
 
2202
  if (matchedItem) {
2203
+ const micStatus = document.getElementById('mic-status');
2204
+ const micItemDetails = document.getElementById('mic-item-details');
2205
+ const micItemName = document.getElementById('mic-item-name');
2206
+ const micItemImage = document.getElementById('mic-item-image');
2207
+ micStatus.style.display = 'none';
2208
+ micItemDetails.style.display = 'block';
2209
+ micItemName.textContent = matchedItem.name;
2210
+ micItemImage.src = matchedItem.image || '/static/placeholder.jpg';
2211
+ setTimeout(() => {
2212
+ recognition.stop();
2213
+ const card = document.querySelector(`.menu-card[data-item-name="${matchedItem.name}"]`);
2214
+ if (card) {
2215
+ card.classList.add('highlighted');
2216
+ card.scrollIntoView({ behavior: 'smooth', block: 'center' });
2217
+ setTimeout(() => card.classList.remove('highlighted'), 2000);
2218
+ const buttonContainer = card.querySelector('.button-container');
2219
+ if (buttonContainer) {
2220
+ if (matchedItem.section === 'Soft Drinks') {
2221
+ showSoftDrinkModal(buttonContainer.querySelector('.add-to-cart-btn'));
2222
+ } else {
2223
+ showItemDetails(
2224
+ matchedItem.name,
2225
+ matchedItem.price,
2226
+ matchedItem.image2 || matchedItem.image,
2227
+ matchedItem.description,
2228
+ matchedItem.section,
2229
+ matchedItem.category
2230
+ );
2231
+ const modal = new bootstrap.Modal(document.getElementById('itemModal'));
2232
+ modal.show();
2233
+ }
2234
+ }
2235
+ const micModal = bootstrap.Modal.getInstance(document.getElementById('micModal'));
2236
+ if (micModal) {
2237
+ micModal.hide();
2238
+ resetMicModal();
2239
  }
2240
  }
2241
+ }, 2000);
 
 
 
 
 
2242
  } else {
2243
  document.getElementById('mic-status').textContent = 'Item not found. Try again.';
2244
  }
2245
  };
 
2246
  recognition.onerror = (event) => {
2247
  console.error('Speech recognition error:', event.error);
2248
  document.getElementById('mic-status').textContent = 'Error occurred. Please try again.';
2249
+ document.getElementById('mic-icon-animation').classList.remove('active');
2250
  };
 
2251
  recognition.onend = () => {
2252
+ document.getElementById('mic-icon-animation').classList.remove('active');
2253
  };
 
2254
  document.getElementById('micIcon').addEventListener('click', () => {
2255
  if (!recognition) return;
2256
  const micModal = new bootstrap.Modal(document.getElementById('micModal'));
 
2258
  resetMicModal();
2259
  recognition.start();
2260
  });
 
2261
  document.getElementById('stopMicBtn').addEventListener('click', stopSpeechRecognition);
2262
  } else {
2263
  document.getElementById('micIcon').style.display = 'none';
2264
  }
 
2265
  const descriptionInput = document.getElementById('custom-dish-description');
2266
  const suggestionsContainer = document.getElementById('descriptionSuggestions');
 
2267
  if (descriptionInput && suggestionsContainer) {
2268
  descriptionInput.addEventListener('input', debounce(() => {
2269
  const query = descriptionInput.value.toLowerCase();
2270
  suggestionsContainer.innerHTML = '';
 
2271
  if (query.length < 2) {
2272
  suggestionsContainer.style.display = 'none';
2273
  return;
2274
  }
 
2275
  const filteredIngredients = ingredientsList.filter(ingredient =>
2276
  ingredient.toLowerCase().includes(query)
2277
  );
 
2278
  if (filteredIngredients.length === 0) {
2279
  suggestionsContainer.style.display = 'none';
2280
  return;
2281
  }
 
2282
  filteredIngredients.forEach(ingredient => {
2283
  const suggestionItem = document.createElement('div');
2284
  suggestionItem.classList.add('autocomplete-suggestion');
 
2294
  });
2295
  suggestionsContainer.appendChild(suggestionItem);
2296
  });
 
2297
  suggestionsContainer.style.display = 'block';
2298
  }, 300));
 
2299
  document.addEventListener('click', (event) => {
2300
  if (!descriptionInput.contains(event.target) && !suggestionsContainer.contains(event.target)) {
2301
  suggestionsContainer.style.display = 'none';