lokesh341 commited on
Commit
4b5baa7
·
verified ·
1 Parent(s): 91a4a53

Update templates/menu.html

Browse files
Files changed (1) hide show
  1. templates/menu.html +1097 -334
templates/menu.html CHANGED
@@ -1,14 +1,18 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
 
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Menu with Auto-Play Videos</title>
7
- <!-- Bootstrap CSS -->
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">
 
 
 
 
 
12
  <style>
13
  body {
14
  font-family: Arial, sans-serif;
@@ -30,17 +34,12 @@
30
  display: flex;
31
  flex-direction: column;
32
  opacity: 0;
33
- transition: opacity 0.3s ease-in-out, transform 0.3s ease;
34
- box-shadow: 0 4px 8px rgba(0,0,0,0.1);
35
  }
36
  .menu-card.visible {
37
  opacity: 1;
38
  }
39
- .menu-card:hover {
40
- transform: translateY(-5px);
41
- }
42
 
43
- /* Video Container Styles */
44
  .video-container {
45
  position: relative;
46
  width: 100%;
@@ -48,6 +47,7 @@
48
  overflow: hidden;
49
  border-radius: 15px 15px 0 0;
50
  background-color: #000;
 
51
  }
52
 
53
  .video-container video {
@@ -55,6 +55,8 @@
55
  height: 100%;
56
  object-fit: cover;
57
  transition: opacity 0.5s ease;
 
 
58
  }
59
 
60
  .video-container .video-placeholder {
@@ -71,6 +73,46 @@
71
  font-size: 14px;
72
  }
73
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  .card-title {
75
  font-size: 1.2rem;
76
  font-weight: bold;
@@ -692,22 +734,6 @@
692
  height: 20px;
693
  font-size: 10px;
694
  }
695
-
696
- /* Mobile video adjustments */
697
- .video-container {
698
- height: 150px;
699
- }
700
- }
701
-
702
- /* Touch device specific styles */
703
- @media (hover: none) and (pointer: coarse) {
704
- .video-container {
705
- height: 200px;
706
- }
707
-
708
- .video-container video {
709
- pointer-events: auto;
710
- }
711
  }
712
  </style>
713
  </head>
@@ -716,12 +742,12 @@
716
  <div class="fixed-top-bar">
717
  <div class="avatar-dropdown-container">
718
  <div class="avatar-icon">
719
- <span>U</span>
720
  </div>
721
  <div class="dropdown-menu">
722
- <a href="/user_details" class="dropdown-item">View Profile</a>
723
- <a href="/orderhistory" class="dropdown-item">Order History</a>
724
- <a href="/logout" class="dropdown-item">Logout</a>
725
  </div>
726
  </div>
727
  <div class="search-bar-container">
@@ -734,199 +760,118 @@
734
  <form method="get" action="/menu" class="text-center mb-4" id="categoryForm">
735
  <label class="form-label fw-bold">Select a Category:</label>
736
  <div class="category-buttons">
737
- <button type="button" class="category-button selected" data-category="All">All</button>
738
- <button type="button" class="category-button" data-category="Starters">Starters</button>
739
- <button type="button" class="category-button" data-category="Main Course">Main Course</button>
740
- <button type="button" class="category-button" data-category="Desserts">Desserts</button>
741
- <button type="button" class="category-button" data-category="Drinks">Drinks</button>
742
- <button type="button" class="category-button" data-category="Customized Dish">Customized Dish</button>
743
  </div>
744
- <input type="hidden" name="category" id="selectedCategoryInput" value="All">
745
  </form>
746
 
747
  <div class="container mt-4">
748
- <h3>Main Course</h3>
749
- <div class="row">
750
- <div class="col-md-6 mb-4">
751
- <div class="card menu-card visible">
752
- <div class="video-container">
753
- <video
754
- id="video-1"
755
- preload="metadata"
756
- poster="https://via.placeholder.com/350x200"
757
- data-src="https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4"
758
- muted
759
- loop
760
- playsinline
761
- >
762
- <source src="https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" type="video/mp4">
763
- Your browser does not support the video tag.
764
- </video>
765
- </div>
766
-
767
- <div class="addbutton">
768
- <div class="card-body d-flex align-items-center justify-content-between">
769
- <div>
770
- <h5 class="card-title">Veg Biryani</h5>
771
- <p class="card-text">$12.99</p>
772
- </div>
773
- <div class="d-flex flex-column align-item-center justify-content-center">
774
- <div class="button-container" data-item-name="Veg Biryani" data-item-price="12.99" data-item-image="https://via.placeholder.com/350x200" data-item-section="Main Course" data-item-category="Main Course">
775
- <button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#itemModal"
776
- onclick="showItemDetails('Veg Biryani', '12.99', 'https://via.placeholder.com/350x200', 'Fragrant basmati rice cooked with mixed vegetables and aromatic spices', 'Main Course','Main Course')">
777
- ADD
778
- </button>
779
- <span class="customisable-text">Customisable</span>
780
- </div>
781
- </div>
782
- </div>
783
  </div>
784
- <div class="toggle-details" data-item-name="Veg Biryani">Show Details</div>
785
- <div class="item-details" id="details-Veg-Biryani">
786
- <h6>Ingredients</h6>
787
- <p>Basmati Rice, Mixed Vegetables (Carrot, Peas, Potato, Cauliflower), Ginger, Garlic, Biryani Masala, Mint Leaves, Curd, Onion, Ghee</p>
788
- <h6>Nutritional Info</h6>
789
- <div class="nutritional-info">
790
- <span>Calories: 300 kcal</span>
791
- <span>Carbs: 50g</span>
792
- <span>Protein: 6g</span>
793
- <span>Fats: 12g</span>
794
- </div>
795
- <h6>Allergens</h6>
796
- <p>Dairy</p>
797
  </div>
798
- </div>
 
799
  </div>
800
-
801
- <div class="col-md-6 mb-4">
802
- <div class="card menu-card visible">
803
- <div class="video-container">
804
- <video
805
- id="video-2"
806
- preload="metadata"
807
- poster="https://via.placeholder.com/350x200"
808
- data-src="https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4"
809
- muted
810
- loop
811
- playsinline
812
- >
813
- <source src="https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" type="video/mp4">
814
- Your browser does not support the video tag.
815
- </video>
816
- </div>
817
-
818
- <div class="addbutton">
819
- <div class="card-body d-flex align-items-center justify-content-between">
820
- <div>
821
- <h5 class="card-title">Butter Chicken</h5>
822
- <p class="card-text">$14.99</p>
823
- </div>
824
- <div class="d-flex flex-column align-item-center justify-content-center">
825
- <div class="button-container" data-item-name="Butter Chicken" data-item-price="14.99" data-item-image="https://via.placeholder.com/350x200" data-item-section="Main Course" data-item-category="Main Course">
826
- <button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#itemModal"
827
- onclick="showItemDetails('Butter Chicken', '14.99', 'https://via.placeholder.com/350x200', 'Tender chicken in a rich, creamy tomato sauce', 'Main Course','Main Course')">
828
- ADD
829
- </button>
830
- <span class="customisable-text">Customisable</span>
831
  </div>
832
- </div>
833
- </div>
834
- </div>
835
- <div class="toggle-details" data-item-name="Butter Chicken">Show Details</div>
836
- <div class="item-details" id="details-Butter-Chicken">
837
- <h6>Ingredients</h6>
838
- <p>Chicken, Butter, Cream, Tomato Puree, Onion, Ginger, Garlic, Garam Masala</p>
839
- <h6>Nutritional Info</h6>
840
- <div class="nutritional-info">
841
- <span>Calories: 400 kcal</span>
842
- <span>Carbs: 20g</span>
843
- <span>Protein: 15g</span>
844
- <span>Fats: 25g</span>
845
- </div>
846
- <h6>Allergens</h6>
847
- <p>Dairy</p>
848
- </div>
849
- </div>
850
- </div>
851
- </div>
852
-
853
- <h3>Drinks</h3>
854
- <div class="row">
855
- <div class="col-md-6 mb-4">
856
- <div class="card menu-card visible">
857
- <div class="video-container">
858
- <video
859
- id="video-3"
860
- preload="metadata"
861
- poster="https://via.placeholder.com/350x200"
862
- data-src="https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4"
863
- muted
864
- loop
865
- playsinline
866
- >
867
- <source src="https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" type="video/mp4">
868
- Your browser does not support the video tag.
869
- </video>
870
- </div>
871
-
872
- <div class="addbutton">
873
- <div class="card-body d-flex align-items-center justify-content-between">
874
- <div>
875
- <h5 class="card-title">Mango Lassi</h5>
876
- <p class="card-text">$4.99</p>
877
- </div>
878
- <div class="d-flex flex-column align-item-center justify-content-center">
879
- <div class="button-container" data-item-name="Mango Lassi" data-item-price="4.99" data-item-image="https://via.placeholder.com/350x200" data-item-section="Drinks" data-item-category="Drinks">
880
- <button class="btn btn-primary add-to-cart-btn" onclick="handleSoftDrinkAdd(this)">ADD</button>
881
- <div class="quantity-selector" style="display: none;">
882
- <button class="btn btn-outline-secondary decrease-btn" onclick="decreaseQuantity(this)">-</button>
883
- <select class="quantity-to-remove">
884
- {% for i in range(1, 21) %}
885
- <option value="{{ i }}">{{ i }}</option>
886
- {% endfor %}
887
- </select>
888
- <span class="quantity-display">0</span>
889
- <button class="btn btn-outline-secondary increase-btn" onclick="increaseQuantity(this)">+</button>
890
- <select class="quantity-to-add">
891
- {% for i in range(1, 21) %}
892
- <option value="{{ i }}">{{ i }}</option>
893
- {% endfor %}
894
- </select>
895
  </div>
896
  </div>
 
 
897
  </div>
898
  </div>
899
- </div>
900
- <div class="toggle-details" data-item-name="Mango Lassi">Show Details</div>
901
- <div class="item-details" id="details-Mango-Lassi">
902
- <h6>Ingredients</h6>
903
- <p>Yogurt, Mango Pulp, Sugar, Cardamom, Ice</p>
904
- <h6>Nutritional Info</h6>
905
- <div class="nutritional-info">
906
- <span>Calories: 250 kcal</span>
907
- <span>Carbs: 45g</span>
908
- <span>Protein: 8g</span>
909
- <span>Fats: 5g</span>
910
- </div>
911
- <h6>Allergens</h6>
912
- <p>Dairy</p>
913
- </div>
914
  </div>
915
- </div>
916
- </div>
917
  </div>
918
 
919
  <div class="view-cart-container">
920
- <a href="/cart" class="view-cart-button">
921
  <i class="bi bi-cart"></i>
922
  view Cart
923
- <span id="cart-item-count" class="cart-icon-badge">
924
- 0
925
  </span>
926
  </a>
927
  </div>
928
 
929
- <!-- Item Modal -->
930
  <div class="modal fade" id="itemModal" tabindex="-1" aria-labelledby="itemModalLabel" aria-hidden="true">
931
  <div class="modal-dialog modal-dialog-centered">
932
  <div class="modal-content">
@@ -935,11 +880,11 @@
935
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
936
  </div>
937
  <div class="modal-body">
938
- <img id="modal-img" class="img-fluid rounded mb-3 d-block mx-auto" src="https://via.placeholder.com/350x200" alt="Item Image">
939
- <h5 id="modal-name" class="fw-bold text-center">Item Name</h5>
940
- <p id="modal-price" class="text-muted text-center">$0.00</p>
941
- <p id="modal-description" class="text-secondary">Item description goes here</p>
942
- <p class="nutritional-info" id="modal-nutritional-info">[Energy: 0 kcal, Protein: 0g, Carbohydrates: 0g, Fiber: 0g, Fat: 0g, Sugar: 0g]</p>
943
 
944
  <div id="first-row">
945
  <h6 id="first-row-title" style="display: none;">Customization Options</h6>
@@ -959,19 +904,7 @@
959
 
960
  <div id="modal-addons" class="modal-addons mt-4">
961
  <h6 id="addons-title">Customization Options</h6>
962
- <div id="addons-list" class="addons-container">
963
- <div class="addon-section">
964
- <h6>Sauces</h6>
965
- <div class="form-check">
966
- <input type="checkbox" class="form-check-input" id="sauce1" value="Mint Chutney" data-name="Mint Chutney" data-group="Sauces" data-price="0">
967
- <label class="form-check-label" for="sauce1">Mint Chutney</label>
968
- </div>
969
- <div class="form-check">
970
- <input type="checkbox" class="form-check-input" id="sauce2" value="Tomato Sauce" data-name="Tomato Sauce" data-group="Sauces" data-price="0">
971
- <label class="form-check-label" for="sauce2">Tomato Sauce</label>
972
- </div>
973
- </div>
974
- </div>
975
  </div>
976
 
977
  <div class="mt-4">
@@ -992,18 +925,189 @@
992
  </div>
993
  </div>
994
 
995
- <!-- Bootstrap JS -->
996
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
997
-
998
  <script>
999
- // Video Handling Functions
1000
- function setupVideoHover() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1001
  const videoContainers = document.querySelectorAll('.video-container');
1002
 
1003
  videoContainers.forEach(container => {
1004
  const video = container.querySelector('video');
 
1005
 
1006
- // Load video source when container is in viewport
1007
  const observer = new IntersectionObserver((entries) => {
1008
  entries.forEach(entry => {
1009
  if (entry.isIntersecting && video.dataset.src && !video.src) {
@@ -1018,58 +1122,114 @@
1018
 
1019
  observer.observe(container);
1020
 
1021
- // Desktop hover behavior
1022
  container.addEventListener('mouseenter', () => {
1023
- if (video.src) {
1024
- video.play().catch(e => console.log('Autoplay prevented:', e));
 
 
 
1025
  }
1026
  });
1027
 
1028
  container.addEventListener('mouseleave', () => {
1029
- if (!video.paused) {
1030
- video.pause();
1031
- video.currentTime = 0;
 
 
 
 
1032
  }
1033
  });
1034
-
1035
- // Touch device behavior
1036
  container.addEventListener('touchstart', (e) => {
1037
- if (video.src) {
1038
- // Prevent default to avoid double-tap zoom
1039
- e.preventDefault();
1040
- video.play().catch(e => console.log('Autoplay prevented:', e));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1041
  }
1042
  }, { passive: false });
1043
-
1044
- // Pause when touching elsewhere
1045
- document.addEventListener('touchstart', (e) => {
1046
- if (!container.contains(e.target) && !video.paused) {
1047
- video.pause();
1048
- video.currentTime = 0;
1049
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
1050
  });
1051
  });
1052
-
1053
- // Handle window resize to reset videos
1054
- window.addEventListener('resize', function() {
1055
- videoContainers.forEach(container => {
1056
- const video = container.querySelector('video');
1057
- if (!video.paused) {
1058
- video.pause();
1059
- video.currentTime = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1060
  }
1061
  });
 
 
 
 
1062
  });
1063
- }
1064
 
1065
- // Initialize when DOM is loaded
1066
- document.addEventListener('DOMContentLoaded', function() {
1067
- setupVideoHover();
1068
-
1069
- // Initialize other functionality
1070
  const toggleLinks = document.querySelectorAll('.toggle-details');
1071
  toggleLinks.forEach(link => {
1072
- link.addEventListener('click', function() {
1073
  const itemName = this.getAttribute('data-item-name').replace(/ /g, '-');
1074
  const detailsDiv = document.getElementById(`details-${itemName}`);
1075
  detailsDiv.classList.toggle('show');
@@ -1077,23 +1237,153 @@
1077
  });
1078
  });
1079
 
1080
- // Category buttons
1081
  const categoryButtons = document.querySelectorAll('.category-button');
 
 
 
 
 
 
 
 
1082
  categoryButtons.forEach(button => {
1083
- button.addEventListener('click', function() {
1084
  categoryButtons.forEach(btn => btn.classList.remove('selected'));
1085
  this.classList.add('selected');
1086
- document.getElementById('selectedCategoryInput').value = this.getAttribute('data-category');
1087
- document.getElementById('categoryForm').submit();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1088
  });
 
 
 
 
 
1089
  });
1090
 
1091
- // Modal quantity controls
1092
  const decreaseBtn = document.getElementById('decreaseQuantity');
1093
  const increaseBtn = document.getElementById('increaseQuantity');
1094
  const quantityInput = document.getElementById('quantityInput');
1095
 
1096
- decreaseBtn.addEventListener('click', function() {
1097
  let currentQuantity = parseInt(quantityInput.value);
1098
  if (currentQuantity > 1) {
1099
  currentQuantity--;
@@ -1101,49 +1391,360 @@
1101
  }
1102
  });
1103
 
1104
- increaseBtn.addEventListener('click', function() {
1105
  let currentQuantity = parseInt(quantityInput.value);
1106
  currentQuantity++;
1107
  quantityInput.value = currentQuantity;
1108
  });
1109
  });
1110
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1111
  function showItemDetails(name, price, image, description, section, selectedCategory) {
1112
  document.getElementById('modal-name').innerText = name;
1113
  document.getElementById('modal-price').innerText = `$${price}`;
1114
- document.getElementById('modal-img').src = image || '/static/placeholder.jpg';
 
 
 
 
 
 
1115
  document.getElementById('modal-description').innerText = description || 'No description available.';
1116
-
1117
- // Set section and category data
 
 
 
 
 
 
 
 
 
1118
  const modalSectionEl = document.getElementById('modal-section');
1119
  modalSectionEl.setAttribute('data-section', section);
1120
  modalSectionEl.setAttribute('data-category', selectedCategory);
1121
-
1122
- // Reset quantity
1123
  document.getElementById('quantityInput').value = 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1124
  }
1125
 
1126
  function addToCartFromModal() {
1127
  const itemName = document.getElementById('modal-name').innerText;
1128
- const itemPrice = parseFloat(document.getElementById('modal-price').innerText.replace('$', ''));
 
 
 
 
1129
  const itemImage = document.getElementById('modal-img').src;
1130
  const modalSectionEl = document.getElementById('modal-section');
1131
  const section = modalSectionEl.getAttribute('data-section');
1132
  const selectedCategory = modalSectionEl.getAttribute('data-category');
1133
- const quantity = parseInt(document.getElementById('quantityInput').value) || 1;
1134
- const instructions = document.getElementById('modal-instructions').value;
1135
-
1136
- // Get selected addons
 
1137
  let selectedAddOns = [];
1138
- const addonOptions = document.querySelectorAll('.addon-option:checked, .spice-level-option:checked');
1139
- addonOptions.forEach(option => {
1140
- selectedAddOns.push({
1141
- name: option.getAttribute('data-name'),
1142
- price: parseFloat(option.getAttribute('data-price') || 0)
1143
- });
 
 
1144
  });
1145
 
1146
- // Create cart payload
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1147
  const cartPayload = {
1148
  itemName: itemName,
1149
  itemPrice: itemPrice,
@@ -1154,16 +1755,41 @@
1154
  instructions: instructions,
1155
  quantity: quantity
1156
  };
1157
-
1158
- // Here you would typically send this to your server
1159
- console.log('Adding to cart:', cartPayload);
1160
- alert(`${quantity} ${itemName} added to cart!`);
1161
-
1162
- // Close modal
1163
- const modal = bootstrap.Modal.getInstance(document.getElementById('itemModal'));
1164
- modal.hide();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1165
  }
1166
-
1167
  function handleSoftDrinkAdd(button) {
1168
  const buttonContainer = button.closest('.button-container');
1169
  const quantitySelector = buttonContainer.querySelector('.quantity-selector');
@@ -1171,22 +1797,16 @@
1171
  const quantityDisplay = quantitySelector.querySelector('.quantity-display');
1172
  const quantityToAddSelect = quantitySelector.querySelector('.quantity-to-add');
1173
  const quantityToAdd = parseInt(quantityToAddSelect.value);
1174
-
1175
- addButton.style.display = 'none';
1176
- quantitySelector.style.display = 'flex';
1177
-
1178
- let currentQuantity = parseInt(quantityDisplay.innerText) || 0;
1179
- currentQuantity += quantityToAdd;
1180
- quantityDisplay.innerText = currentQuantity;
1181
-
1182
- // Get item details
1183
  const itemName = buttonContainer.getAttribute('data-item-name');
1184
  const itemPrice = parseFloat(buttonContainer.getAttribute('data-item-price'));
1185
  const itemImage = buttonContainer.getAttribute('data-item-image');
1186
  const section = buttonContainer.getAttribute('data-item-section');
1187
  const selectedCategory = buttonContainer.getAttribute('data-item-category');
1188
-
1189
- // Create cart payload
 
 
 
1190
  const cartPayload = {
1191
  itemName: itemName,
1192
  itemPrice: itemPrice,
@@ -1197,30 +1817,54 @@
1197
  instructions: '',
1198
  quantity: quantityToAdd
1199
  };
1200
-
1201
- // Here you would typically send this to your server
1202
- console.log('Adding to cart:', cartPayload);
1203
- alert(`${quantityToAdd} ${itemName} added to cart!`);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1204
  }
1205
-
1206
  function increaseQuantity(button) {
1207
  const buttonContainer = button.closest('.button-container');
1208
  const quantityDisplay = buttonContainer.querySelector('.quantity-display');
1209
  const quantityToAddSelect = buttonContainer.querySelector('.quantity-to-add');
1210
  const quantityToAdd = parseInt(quantityToAddSelect.value);
1211
-
1212
- let currentQuantity = parseInt(quantityDisplay.innerText) || 0;
1213
- currentQuantity += quantityToAdd;
1214
- quantityDisplay.innerText = currentQuantity;
1215
-
1216
- // Get item details
1217
  const itemName = buttonContainer.getAttribute('data-item-name');
1218
  const itemPrice = parseFloat(buttonContainer.getAttribute('data-item-price'));
1219
  const itemImage = buttonContainer.getAttribute('data-item-image');
1220
  const section = buttonContainer.getAttribute('data-item-section');
1221
  const selectedCategory = buttonContainer.getAttribute('data-item-category');
1222
-
1223
- // Create cart payload
 
1224
  const cartPayload = {
1225
  itemName: itemName,
1226
  itemPrice: itemPrice,
@@ -1231,12 +1875,37 @@
1231
  instructions: '',
1232
  quantity: quantityToAdd
1233
  };
1234
-
1235
- // Here you would typically send this to your server
1236
- console.log('Adding to cart:', cartPayload);
1237
- alert(`${quantityToAdd} ${itemName} added to cart!`);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1238
  }
1239
-
1240
  function decreaseQuantity(button) {
1241
  const buttonContainer = button.closest('.button-container');
1242
  const quantityDisplay = buttonContainer.querySelector('.quantity-display');
@@ -1245,26 +1914,120 @@
1245
  const addButton = buttonContainer.querySelector('.add-to-cart-btn');
1246
  const quantitySelector = buttonContainer.querySelector('.quantity-selector');
1247
  let currentQuantity = parseInt(quantityDisplay.innerText);
1248
-
1249
  if (currentQuantity <= quantityToRemove) {
1250
- // Remove completely
1251
  const itemName = buttonContainer.getAttribute('data-item-name');
1252
- console.log(`Removing all ${itemName} from cart`);
1253
- alert(`Removed all ${itemName} from cart!`);
1254
-
1255
- addButton.style.display = 'block';
1256
- quantitySelector.style.display = 'none';
1257
- quantityDisplay.innerText = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1258
  } else {
1259
- // Decrease quantity
1260
  currentQuantity -= quantityToRemove;
1261
  quantityDisplay.innerText = currentQuantity;
1262
-
1263
  const itemName = buttonContainer.getAttribute('data-item-name');
1264
- console.log(`Removing ${quantityToRemove} ${itemName} from cart`);
1265
- alert(`Removed ${quantityToRemove} ${itemName} from cart!`);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1266
  }
1267
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1268
  </script>
1269
  </body>
1270
  </html>
 
1
+
2
+ <!DOCTYPE html>
3
+ <html lang="en">
4
+ <head>
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Menu</title>
 
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
  <link rel="preload" href="/static/placeholder.jpg" as="image">
11
+ {% for section, items in ordered_menu.items() %}
12
+ {% for item in items[:1] %}
13
+ <link rel="preload" href="{{ item.Image1__c }}" as="image" fetchpriority="high">
14
+ {% endfor %}
15
+ {% endfor %}
16
  <style>
17
  body {
18
  font-family: Arial, sans-serif;
 
34
  display: flex;
35
  flex-direction: column;
36
  opacity: 0;
37
+ transition: opacity 0.3s ease-in-out;
 
38
  }
39
  .menu-card.visible {
40
  opacity: 1;
41
  }
 
 
 
42
 
 
43
  .video-container {
44
  position: relative;
45
  width: 100%;
 
47
  overflow: hidden;
48
  border-radius: 15px 15px 0 0;
49
  background-color: #000;
50
+ touch-action: manipulation;
51
  }
52
 
53
  .video-container video {
 
55
  height: 100%;
56
  object-fit: cover;
57
  transition: opacity 0.5s ease;
58
+ -webkit-user-select: none;
59
+ user-select: none;
60
  }
61
 
62
  .video-container .video-placeholder {
 
73
  font-size: 14px;
74
  }
75
 
76
+ .video-container .play-button {
77
+ position: absolute;
78
+ top: 50%;
79
+ left: 50%;
80
+ transform: translate(-50%, -50%);
81
+ width: 50px;
82
+ height: 50px;
83
+ background-color: rgba(0, 0, 0, 0.7);
84
+ border-radius: 50%;
85
+ display: flex;
86
+ align-items: center;
87
+ justify-content: center;
88
+ cursor: pointer;
89
+ z-index: 10;
90
+ opacity: 0;
91
+ transition: opacity 0.3s ease;
92
+ }
93
+
94
+ .video-container:hover .play-button {
95
+ opacity: 1;
96
+ }
97
+
98
+ .video-container .play-button i {
99
+ color: white;
100
+ font-size: 20px;
101
+ margin-left: 3px;
102
+ }
103
+
104
+ @media (max-width: 768px) {
105
+ .video-container .play-button {
106
+ opacity: 1;
107
+ }
108
+ .video-container:hover .play-button {
109
+ opacity: 1;
110
+ }
111
+ .video-container {
112
+ height: 150px;
113
+ }
114
+ }
115
+
116
  .card-title {
117
  font-size: 1.2rem;
118
  font-weight: bold;
 
734
  height: 20px;
735
  font-size: 10px;
736
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
737
  }
738
  </style>
739
  </head>
 
742
  <div class="fixed-top-bar">
743
  <div class="avatar-dropdown-container">
744
  <div class="avatar-icon">
745
+ <span>{{ first_letter }}</span>
746
  </div>
747
  <div class="dropdown-menu">
748
+ <a href="{{ url_for('user_details.customer_details') }}" class="dropdown-item">View Profile</a>
749
+ <a href="{{ url_for('orderhistory.order_history') }}" class="dropdown-item">Order History</a>
750
+ <a href="{{ url_for('logout') }}" class="dropdown-item">Logout</a>
751
  </div>
752
  </div>
753
  <div class="search-bar-container">
 
760
  <form method="get" action="/menu" class="text-center mb-4" id="categoryForm">
761
  <label class="form-label fw-bold">Select a Category:</label>
762
  <div class="category-buttons">
763
+ {% for category in categories %}
764
+ <button type="button" class="category-button {% if selected_category == category %}selected{% endif %}" data-category="{{ category }}">{{ category }}</button>
765
+ {% endfor %}
766
+ <button type="button" class="category-button {% if selected_category == 'Customized Dish' %}selected{% endif %}" data-category="Customized Dish">Customized Dish</button>
 
 
767
  </div>
768
+ <input type="hidden" name="category" id="selectedCategoryInput" value="{{ selected_category }}">
769
  </form>
770
 
771
  <div class="container mt-4">
772
+ {% if selected_category == "Customized Dish" %}
773
+ <div id="custom-dish-form" class="mt-4">
774
+ <h3>Create Your Custom Dish</h3>
775
+ <form method="POST" action="/customdish/generate_custom_dish">
776
+ <div class="mb-3">
777
+ <label for="custom-dish-name" class="form-label">Dish Name</label>
778
+ <input type="text" class="form-control" id="custom-dish-name" name="name" required>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
779
  </div>
780
+ <div class="mb-3 position-relative">
781
+ <label for="custom-dish-description" class="form-label">Dish Description</label>
782
+ <textarea class="form-control" id="custom-dish-description" name="description" required></textarea>
783
+ <div id="descriptionSuggestions" class="autocomplete-suggestions"></div>
 
 
 
 
 
 
 
 
 
784
  </div>
785
+ <button type="submit" class="btn btn-primary">Submit</button>
786
+ </form>
787
  </div>
788
+ {% else %}
789
+ {% for section, items in ordered_menu.items() %}
790
+ <h3>{{ section }}</h3>
791
+ <div class="row">
792
+ {% for item in items %}
793
+ <div class="col-md-6 mb-4">
794
+ <div class="card menu-card">
795
+ <div class="video-container">
796
+ <video
797
+ id="video-{{ loop.index }}"
798
+ preload="metadata"
799
+ poster="{{ item.Image1__c if item.Image1__c else '/static/placeholder.jpg' }}"
800
+ data-src="{{ item.Video1__c }}"
801
+ muted
802
+ loop
803
+ >
804
+ <source src="{{ item.Video1__c }}" type="video/mp4">
805
+ Your browser does not support the video tag.
806
+ </video>
807
+ {% if not item.Video1__c %}
808
+ <div class="video-placeholder">
809
+ No video available
810
+ </div>
811
+ {% endif %}
812
+ <div class="play-button" onclick="togglePlay(this)">
813
+ <i class="bi bi-play-fill"></i>
814
+ </div>
 
 
 
 
815
  </div>
816
+
817
+ <div class="addbutton">
818
+ <div class="card-body d-flex align-items-center justify-content-between">
819
+ <div>
820
+ <h5 class="card-title">{{ item.Name }}</h5>
821
+ <p class="card-text">${{ item.Price__c }}</p>
822
+ </div>
823
+ <div class="d-flex flex-column align-item-center justify-content-center">
824
+ <div class="button-container" data-item-name="{{ item.Name }}" data-item-price="{{ item.Price__c }}" data-item-image="{{ item.Image1__c }}" data-item-section="{{ item.Section__c }}" data-item-category="{{ selected_category }}">
825
+ {% if item.Section__c == 'Soft Drinks' %}
826
+ <button class="btn btn-primary add-to-cart-btn" onclick="handleSoftDrinkAdd(this)">ADD</button>
827
+ <div class="quantity-selector" style="display: none;">
828
+ <button class="btn btn-outline-secondary decrease-btn" onclick="decreaseQuantity(this)">-</button>
829
+ <select class="quantity-to-remove">
830
+ {% for i in range(1, 21) %}
831
+ <option value="{{ i }}">{{ i }}</option>
832
+ {% endfor %}
833
+ </select>
834
+ <span class="quantity-display">0</span>
835
+ <button class="btn btn-outline-secondary increase-btn" onclick="increaseQuantity(this)">+</button>
836
+ <select class="quantity-to-add">
837
+ {% for i in range(1, 21) %}
838
+ <option value="{{ i }}">{{ i }}</option>
839
+ {% endfor %}
840
+ </select>
841
+ </div>
842
+ {% else %}
843
+ <button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#itemModal"
844
+ onclick="showItemDetails('{{ item.Name }}', '{{ item.Price__c }}', '{{ item.Image2__c }}', '{{ item.Description__c }}', '{{ item.Section__c }}','{{ selected_category }}')">
845
+ ADD
846
+ </button>
847
+ {% endif %}
848
+ {% if item.Section__c != 'Apetizer' and item.Section__c != 'Customized dish' and item.Section__c !='Soft Drinks' %}
849
+ <span class="customisable-text">Customisable</span>
850
+ {% endif %}
851
+ </div>
852
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
853
  </div>
854
  </div>
855
+ <div class="toggle-details" data-item-name="{{ item.Name }}">Show Details</div>
856
+ <div class="item-details" id="details-{{ item.Name | replace(' ', '-') }}"></div>
857
  </div>
858
  </div>
859
+ {% endfor %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
860
  </div>
861
+ {% endfor %}
862
+ {% endif %}
863
  </div>
864
 
865
  <div class="view-cart-container">
866
+ <a href="{{ url_for('cart.cart') }}" class="view-cart-button">
867
  <i class="bi bi-cart"></i>
868
  view Cart
869
+ <span id="cart-item-count" class="cart-icon-badge {% if cart_item_count > 0 %}active{% endif %}">
870
+ {{ cart_item_count if cart_item_count > 0 else '' }}
871
  </span>
872
  </a>
873
  </div>
874
 
 
875
  <div class="modal fade" id="itemModal" tabindex="-1" aria-labelledby="itemModalLabel" aria-hidden="true">
876
  <div class="modal-dialog modal-dialog-centered">
877
  <div class="modal-content">
 
880
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
881
  </div>
882
  <div class="modal-body">
883
+ <img id="modal-img" class="img-fluid rounded mb-3 d-block mx-auto" alt="Item Image">
884
+ <h5 id="modal-name" class="fw-bold text-center"></h5>
885
+ <p id="modal-price" class="text-muted text-center"></p>
886
+ <p id="modal-description" class="text-secondary"></p>
887
+ <p class="nutritional-info" id="modal-nutritional-info"></p>
888
 
889
  <div id="first-row">
890
  <h6 id="first-row-title" style="display: none;">Customization Options</h6>
 
904
 
905
  <div id="modal-addons" class="modal-addons mt-4">
906
  <h6 id="addons-title">Customization Options</h6>
907
+ <div id="addons-list" class="addons-container">Loading customization options...</div>
 
 
 
 
 
 
 
 
 
 
 
 
908
  </div>
909
 
910
  <div class="mt-4">
 
925
  </div>
926
  </div>
927
 
 
928
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
 
929
  <script>
930
+ function togglePlay(button) {
931
+ const videoContainer = button.closest('.video-container');
932
+ const video = videoContainer.querySelector('video');
933
+
934
+ if (video.paused) {
935
+ if (!video.src && video.dataset.src) {
936
+ video.src = video.dataset.src;
937
+ }
938
+ video.play()
939
+ .then(() => {
940
+ button.innerHTML = '<i class="bi bi-pause-fill"></i>';
941
+ })
942
+ .catch(e => console.log('Video play error:', e));
943
+ } else {
944
+ video.pause();
945
+ button.innerHTML = '<i class="bi bi-play-fill"></i>';
946
+ }
947
+ }
948
+
949
+ const menuItems = [
950
+ {% for section, items in ordered_menu.items() %}
951
+ {% for item in items %}
952
+ "{{ item.Name }}",
953
+ {% endfor %}
954
+ {% endfor %}
955
+ ];
956
+
957
+ const ingredientsList = [
958
+ "Basmati Rice", "Bell Pepper", "Biryani Masala", "Butter", "Capsicum", "Cauliflower",
959
+ "Chickpea Flour (Besan)", "Chickpea Flour (for batter)", "Chickpeas (Channa)", "Chili Powder",
960
+ "Chili Sauce", "Coconut Milk", "Coriander Powder", "Cornflour", "Cream", "Cumin Powder",
961
+ "Cumin Seeds", "Curd (Yogurt)", "Curry Leaves", "Fish (e.g., King Fish or Salmon)",
962
+ "Fresh Coriander Leaves", "Garam Masala", "Garlic", "Ghee (Clarified Butter)", "Ginger",
963
+ "Ginger-Garlic Paste", "Goat Meat (Mutton)", "Green Chilies", "Honey",
964
+ "Kasuri Methi (dried fenugreek leaves)", "Lemon Juice", "Mango Puree", "Mint Leaves",
965
+ "Mixed Vegetables (Carrot, Peas, Potato, Cauliflower)", "Mixed Vegetables (Carrot, Peas, Potato)",
966
+ "Mustard Seeds", "Mutton (Goat Meat)", "Oil", "Oil (for frying)", "Onion",
967
+ "Paneer (Indian Cottage Cheese)", "Peas", "Potatoes", "Prawns", "Red Chili Powder",
968
+ "Rice Flour", "Saffron", "Salt", "Soy Sauce", "Spring Onion", "Tamarind (for sourness)",
969
+ "Tomato Ketchup", "Tomatoes", "Turmeric Powder", "Vinegar", "Water", "Wheat Flour (for dough)",
970
+ "Whole Wheat Flour", "Yogurt (Curd)"
971
+ ];
972
+
973
+ const menuItemDetails = {
974
+ "Veg Manchurian": {
975
+ ingredients: "Cauliflower, Onion, Ginger, Garlic, Soy Sauce, Cornflour, Green Chilies, Capsicum, Spring Onion",
976
+ nutritionalInfo: { calories: 250, protein: 5, carbs: 35, fats: 12, fiber: 3, sugar: 2 },
977
+ allergens: "Soy, Gluten"
978
+ },
979
+ "Veg Biryani": {
980
+ ingredients: "Basmati Rice, Mixed Vegetables (Carrot, Peas, Potato, Cauliflower), Ginger, Garlic, Biryani Masala, Mint Leaves, Curd, Onion, Ghee",
981
+ nutritionalInfo: { calories: 300, protein: 6, carbs: 50, fats: 12, fiber: 5, sugar: 3 },
982
+ allergens: "Dairy"
983
+ },
984
+ "Sukka Gosht (Goat)": {
985
+ ingredients: "Goat Meat, Ginger-Garlic Paste, Green Chilies, Onion, Tomatoes, Garam Masala, Coriander Powder, Cumin Powder, Fresh Coriander",
986
+ nutritionalInfo: { calories: 450, protein: 35, carbs: 10, fats: 30, fiber: 2, sugar: 1 },
987
+ allergens: "None"
988
+ },
989
+ "Samosa": {
990
+ ingredients: "Potatoes, Peas, Onion, Ginger, Cumin Seeds, Garam Masala, Wheat Flour (for dough), Oil (for frying)",
991
+ nutritionalInfo: { calories: 150, protein: 3, carbs: 25, fats: 7, fiber: 2, sugar: 1 },
992
+ allergens: "Gluten"
993
+ },
994
+ "Roti": {
995
+ ingredients: "Whole Wheat Flour, Water, Salt",
996
+ nutritionalInfo: { calories: 150, protein: 4, carbs: 30, fats: 1, fiber: 3, sugar: 0 },
997
+ allergens: "Gluten"
998
+ },
999
+ "Prawn Fry": {
1000
+ ingredients: "Prawns, Garlic, Ginger, Chili Powder, Coriander Powder, Cumin Powder, Lemon Juice, Oil",
1001
+ nutritionalInfo: { calories: 350, protein: 25, carbs: 10, fats: 20, fiber: 1, sugar: 1 },
1002
+ allergens: "Shellfish"
1003
+ },
1004
+ "Paneer Butter Masala": {
1005
+ ingredients: "Paneer, Butter, Cream, Tomato Puree, Onion, Ginger, Garlic, Garam Masala",
1006
+ nutritionalInfo: { calories: 400, protein: 15, carbs: 20, fats: 25, fiber: 2, sugar: 3 },
1007
+ allergens: "Dairy"
1008
+ },
1009
+ "Paneer Biryani": {
1010
+ ingredients: "Paneer, Basmati Rice, Mixed Vegetables (Carrot, Peas, Potato), Onion, Tomatoes, Biryani Masala, Mint Leaves, Curd",
1011
+ nutritionalInfo: { calories: 350, protein: 12, carbs: 55, fats: 15, fiber: 4, sugar: 3 },
1012
+ allergens: "Dairy"
1013
+ },
1014
+ "Onion Pakoda": {
1015
+ ingredients: "Onion, Chickpea Flour (Besan), Rice Flour, Green Chilies, Cumin Seeds, Ginger, Turmeric Powder, Oil (for frying)",
1016
+ nutritionalInfo: { calories: 200, protein: 5, carbs: 30, fats: 8, fiber: 3, sugar: 2 },
1017
+ allergens: "Gluten (if cross-contamination)"
1018
+ },
1019
+ "Mutton Biryani": {
1020
+ ingredients: "Mutton, Basmati Rice, Onion, Tomatoes, Ginger-Garlic Paste, Biryani Masala, Mint Leaves, Yogurt, Ghee",
1021
+ nutritionalInfo: { calories: 500, protein: 30, carbs: 50, fats: 25, fiber: 4, sugar: 3 },
1022
+ allergens: "Dairy"
1023
+ },
1024
+ "Fish Curry": {
1025
+ ingredients: "Fish (any firm fish like Salmon or King Fish), Onion, Tomato, Ginger-Garlic Paste, Curry Leaves, Coconut Milk, Tamarind, Mustard Seeds",
1026
+ nutritionalInfo: { calories: 300, protein: 25, carbs: 10, fats: 20, fiber: 2, sugar: 1 },
1027
+ allergens: "Fish"
1028
+ },
1029
+ "Fiery Mango Glaze Chicken": {
1030
+ ingredients: "Chicken, Mango Puree, Chili Sauce, Soy Sauce, Honey, Garlic, Ginger, Lemon Juice",
1031
+ nutritionalInfo: { calories: 350, protein: 30, carbs: 15, fats: 18, fiber: 1, sugar: 5 },
1032
+ allergens: "Soy"
1033
+ },
1034
+ "Chilli Gobi": {
1035
+ ingredients: "Cauliflower, Onion, Green Chilies, Soy Sauce, Cornflour, Garlic, Ginger, Cumin Powder",
1036
+ nutritionalInfo: { calories: 250, protein: 6, carbs: 35, fats: 12, fiber: 3, sugar: 2 },
1037
+ allergens: "Soy, Gluten"
1038
+ },
1039
+ "Chilli Chicken": {
1040
+ ingredients: "Chicken, Bell Pepper, Onion, Green Chilies, Soy Sauce, Cornflour, Garlic, Ginger",
1041
+ nutritionalInfo: { calories: 400, protein: 35, carbs: 20, fats: 18, fiber: 2, sugar: 2 },
1042
+ allergens: "Soy, Gluten"
1043
+ },
1044
+ "Chicken Manchurian": {
1045
+ ingredients: "Chicken, Onion, Garlic, Ginger, Soy Sauce, Cornflour, Green Chilies, Capsicum",
1046
+ nutritionalInfo: { calories: 350, protein: 25, carbs: 20, fats: 18, fiber: 2, sugar: 2 },
1047
+ allergens: "Soy, Gluten"
1048
+ },
1049
+ "Chicken Curry": {
1050
+ ingredients: "Chicken, Onion, Tomatoes, Ginger-Garlic Paste, Garam Masala, Coconut Milk, Coriander Leaves",
1051
+ nutritionalInfo: { calories: 350, protein: 28, carbs: 15, fats: 12, fiber: 4, sugar: 2 },
1052
+ allergens: "None"
1053
+ },
1054
+ "Chicken Biryani": {
1055
+ ingredients: "Chicken, Basmati Rice, Onion, Tomatoes, Ginger-Garlic Paste, Biryani Masala, Mint Leaves, Curd",
1056
+ nutritionalInfo: { calories: 500, protein: 35, carbs: 60, fats: 20, fiber: 5, sugar: 3 },
1057
+ allergens: "Dairy"
1058
+ },
1059
+ "Channa Masala": {
1060
+ ingredients: "Chickpeas, Onion, Tomatoes, Ginger-Garlic Paste, Garam Masala, Coriander Powder, Cumin Seeds, Lemon Juice",
1061
+ nutritionalInfo: { calories: 250, protein: 10, carbs: 45, fats: 5, fiber: 6, sugar: 2 },
1062
+ allergens: "None"
1063
+ }
1064
+ };
1065
+
1066
+ function addToCartLocalStorage(payload) {
1067
+ let cart = JSON.parse(localStorage.getItem('cart')) || [];
1068
+ const existingItem = cart.find(item =>
1069
+ item.itemName === payload.itemName &&
1070
+ item.instructions === payload.instructions &&
1071
+ JSON.stringify(item.addons) === JSON.stringify(payload.addons)
1072
+ );
1073
+ if (existingItem) {
1074
+ existingItem.quantity += payload.quantity;
1075
+ } else {
1076
+ cart.push(payload);
1077
+ }
1078
+ localStorage.setItem('cart', JSON.stringify(cart));
1079
+ return cart;
1080
+ }
1081
+
1082
+ function removeFromCartLocalStorage(itemName, quantityToRemove, instructions, addons) {
1083
+ let cart = JSON.parse(localStorage.getItem('cart')) || [];
1084
+ const itemIndex = cart.findIndex(item =>
1085
+ item.itemName === itemName &&
1086
+ item.instructions === instructions &&
1087
+ JSON.stringify(item.addons) === JSON.stringify(addons)
1088
+ );
1089
+ if (itemIndex !== -1) {
1090
+ if (quantityToRemove >= cart[itemIndex].quantity) {
1091
+ cart.splice(itemIndex, 1);
1092
+ } else {
1093
+ cart[itemIndex].quantity -= quantityToRemove;
1094
+ }
1095
+ }
1096
+ localStorage.setItem('cart', JSON.stringify(cart));
1097
+ return cart;
1098
+ }
1099
+
1100
+ function getCartLocalStorage() {
1101
+ return JSON.parse(localStorage.getItem('cart')) || [];
1102
+ }
1103
+
1104
+ document.addEventListener('DOMContentLoaded', function () {
1105
  const videoContainers = document.querySelectorAll('.video-container');
1106
 
1107
  videoContainers.forEach(container => {
1108
  const video = container.querySelector('video');
1109
+ const playButton = container.querySelector('.play-button');
1110
 
 
1111
  const observer = new IntersectionObserver((entries) => {
1112
  entries.forEach(entry => {
1113
  if (entry.isIntersecting && video.dataset.src && !video.src) {
 
1122
 
1123
  observer.observe(container);
1124
 
 
1125
  container.addEventListener('mouseenter', () => {
1126
+ if (window.innerWidth > 768) {
1127
+ if (video.src || video.dataset.src) {
1128
+ if (!video.src) video.src = video.dataset.src;
1129
+ video.play().catch(e => console.log('Autoplay prevented:', e));
1130
+ }
1131
  }
1132
  });
1133
 
1134
  container.addEventListener('mouseleave', () => {
1135
+ if (window.innerWidth > 768) {
1136
+ if (!video.paused) {
1137
+ video.pause();
1138
+ if (playButton) {
1139
+ playButton.innerHTML = '<i class="bi bi-play-fill"></i>';
1140
+ }
1141
+ }
1142
  }
1143
  });
1144
+
 
1145
  container.addEventListener('touchstart', (e) => {
1146
+ e.preventDefault();
1147
+ if (window.innerWidth <= 768) {
1148
+ if (video.src || video.dataset.src) {
1149
+ if (!video.src) video.src = video.dataset.src;
1150
+ if (video.paused) {
1151
+ video.play()
1152
+ .then(() => {
1153
+ if (playButton) {
1154
+ playButton.innerHTML = '<i class="bi bi-pause-fill"></i>';
1155
+ }
1156
+ })
1157
+ .catch(e => console.log('Video play error:', e));
1158
+ } else {
1159
+ video.pause();
1160
+ if (playButton) {
1161
+ playButton.innerHTML = '<i class="bi bi-play-fill"></i>';
1162
+ }
1163
+ }
1164
+ }
1165
  }
1166
  }, { passive: false });
1167
+ });
1168
+
1169
+ const avatarContainer = document.querySelector('.avatar-dropdown-container');
1170
+ const dropdownMenu = document.querySelector('.dropdown-menu');
1171
+
1172
+ avatarContainer.addEventListener('click', function (event) {
1173
+ event.stopPropagation();
1174
+ dropdownMenu.style.display = dropdownMenu.style.display === 'block' ? 'none' : 'block';
1175
+ });
1176
+
1177
+ document.addEventListener('click', function (event) {
1178
+ if (!avatarContainer.contains(event.target)) {
1179
+ dropdownMenu.style.display = 'none';
1180
+ }
1181
+ });
1182
+
1183
+ const dropdownItems = document.querySelectorAll('.dropdown-item');
1184
+ dropdownItems.forEach(item => {
1185
+ item.addEventListener('click', function () {
1186
+ dropdownMenu.style.display = 'none';
1187
  });
1188
  });
1189
+
1190
+ const menuCards = document.querySelectorAll('.menu-card');
1191
+ menuCards.forEach(card => {
1192
+ const itemName = card.querySelector('.card-title').innerText;
1193
+ const detailsDiv = card.querySelector('.item-details');
1194
+ const detailsData = menuItemDetails[itemName];
1195
+
1196
+ if (detailsData) {
1197
+ detailsDiv.innerHTML = `
1198
+ <h6>Ingredients</h6>
1199
+ <p>${detailsData.ingredients}</p>
1200
+ <h6>Nutritional Info</h6>
1201
+ <div class="nutritional-info">
1202
+ <span>Calories: ${detailsData.nutritionalInfo.calories} kcal</span>
1203
+ <span>Carbs: ${detailsData.nutritionalInfo.carbs}g</span>
1204
+ <span>Protein: ${detailsData.nutritionalInfo.protein}g</span>
1205
+ <span>Fats: ${detailsData.nutritionalInfo.fats}g</span>
1206
+ </div>
1207
+ <h6>Allergens</h6>
1208
+ <p>${detailsData.allergens}</p>
1209
+ `;
1210
+ } else {
1211
+ detailsDiv.innerHTML = '<p>No details available for this item.</p>';
1212
+ }
1213
+ });
1214
+
1215
+ const cardObserver = new IntersectionObserver((entries, observer) => {
1216
+ entries.forEach(entry => {
1217
+ if (entry.isIntersecting) {
1218
+ entry.target.classList.add('visible');
1219
+ observer.unobserve(entry.target);
1220
  }
1221
  });
1222
+ }, {
1223
+ root: null,
1224
+ rootMargin: '0px',
1225
+ threshold: 0.1
1226
  });
 
1227
 
1228
+ menuCards.forEach(card => cardObserver.observe(card));
1229
+
 
 
 
1230
  const toggleLinks = document.querySelectorAll('.toggle-details');
1231
  toggleLinks.forEach(link => {
1232
+ link.addEventListener('click', function () {
1233
  const itemName = this.getAttribute('data-item-name').replace(/ /g, '-');
1234
  const detailsDiv = document.getElementById(`details-${itemName}`);
1235
  detailsDiv.classList.toggle('show');
 
1237
  });
1238
  });
1239
 
 
1240
  const categoryButtons = document.querySelectorAll('.category-button');
1241
+ const categoryForm = document.getElementById('categoryForm');
1242
+ const selectedCategoryInput = document.getElementById('selectedCategoryInput');
1243
+
1244
+ if (!selectedCategoryInput.value) {
1245
+ selectedCategoryInput.value = "All";
1246
+ document.querySelector('.category-button[data-category="All"]').classList.add('selected');
1247
+ }
1248
+
1249
  categoryButtons.forEach(button => {
1250
+ button.addEventListener('click', function () {
1251
  categoryButtons.forEach(btn => btn.classList.remove('selected'));
1252
  this.classList.add('selected');
1253
+ selectedCategoryInput.value = this.getAttribute('data-category');
1254
+ categoryForm.submit();
1255
+ });
1256
+ });
1257
+
1258
+ const searchBar = document.getElementById('searchBar');
1259
+ const suggestionsContainer = document.getElementById('autocompleteSuggestions');
1260
+
1261
+ searchBar.addEventListener('input', function () {
1262
+ const input = this.value.trim().toLowerCase();
1263
+ suggestionsContainer.innerHTML = '';
1264
+ suggestionsContainer.style.display = 'none';
1265
+
1266
+ if (input) {
1267
+ const filteredItems = menuItems.filter(item =>
1268
+ item.toLowerCase().includes(input)
1269
+ );
1270
+ if (filteredItems.length > 0) {
1271
+ filteredItems.forEach(item => {
1272
+ const suggestionDiv = document.createElement('div');
1273
+ suggestionDiv.classList.add('suggestion-item');
1274
+ suggestionDiv.innerText = item;
1275
+ suggestionDiv.addEventListener('click', function () {
1276
+ searchBar.value = item;
1277
+ suggestionsContainer.style.display = 'none';
1278
+ filterMenu();
1279
+ });
1280
+ suggestionsContainer.appendChild(suggestionDiv);
1281
+ });
1282
+ suggestionsContainer.style.display = 'block';
1283
+ }
1284
+ }
1285
+ filterMenu();
1286
+ });
1287
+
1288
+ document.addEventListener('click', function (event) {
1289
+ if (!searchBar.contains(event.target) && !suggestionsContainer.contains(event.target)) {
1290
+ suggestionsContainer.style.display = 'none';
1291
+ }
1292
+ });
1293
+
1294
+ const descriptionTextarea = document.getElementById('custom-dish-description');
1295
+ const descriptionSuggestions = document.getElementById('descriptionSuggestions');
1296
+
1297
+ if (descriptionTextarea && descriptionSuggestions) {
1298
+ let usedIngredients = new Set();
1299
+
1300
+ function updateUsedIngredients() {
1301
+ const inputText = descriptionTextarea.value.trim();
1302
+ usedIngredients.clear();
1303
+ if (inputText) {
1304
+ const words = inputText.split(/,\s*/).map(word => word.trim());
1305
+ words.forEach(word => {
1306
+ if (word && ingredientsList.includes(word)) {
1307
+ usedIngredients.add(word);
1308
+ }
1309
+ });
1310
+ }
1311
+ }
1312
+
1313
+ descriptionTextarea.addEventListener('input', function () {
1314
+ const inputText = this.value.trim();
1315
+ const words = inputText.split(/,\s*/);
1316
+ const lastWord = words[words.length - 1].trim().toLowerCase();
1317
+ descriptionSuggestions.innerHTML = '';
1318
+ descriptionSuggestions.style.display = 'none';
1319
+
1320
+ updateUsedIngredients();
1321
+
1322
+ if (lastWord) {
1323
+ const filteredIngredients = ingredientsList.filter(ingredient =>
1324
+ ingredient.toLowerCase().includes(lastWord) && !usedIngredients.has(ingredient)
1325
+ );
1326
+ if (filteredIngredients.length > 0) {
1327
+ filteredIngredients.forEach(ingredient => {
1328
+ const suggestionDiv = document.createElement('div');
1329
+ suggestionDiv.classList.add('suggestion-item');
1330
+ suggestionDiv.innerText = ingredient;
1331
+ suggestionDiv.addEventListener('click', function () {
1332
+ const currentValue = descriptionTextarea.value;
1333
+ const lastCommaIndex = currentValue.lastIndexOf(',');
1334
+ const baseText = lastCommaIndex !== -1 ? currentValue.substring(0, lastCommaIndex + 1) : '';
1335
+ descriptionTextarea.value = baseText + (baseText ? ' ' : '') + ingredient + ', ';
1336
+ descriptionSuggestions.style.display = 'none';
1337
+ descriptionTextarea.focus();
1338
+ updateUsedIngredients();
1339
+ });
1340
+ descriptionSuggestions.appendChild(suggestionDiv);
1341
+ });
1342
+ descriptionSuggestions.style.display = 'block';
1343
+ }
1344
+ }
1345
+ });
1346
+
1347
+ document.addEventListener('click', function (event) {
1348
+ if (!descriptionTextarea.contains(event.target) && !descriptionSuggestions.contains(event.target)) {
1349
+ descriptionSuggestions.style.display = 'none';
1350
+ }
1351
+ });
1352
+ }
1353
+
1354
+ fetch('/cart/get')
1355
+ .then(response => {
1356
+ if (!response.ok) {
1357
+ throw new Error(`HTTP error! Status: ${response.status}`);
1358
+ }
1359
+ return response.json();
1360
+ })
1361
+ .then(data => {
1362
+ if (data.success) {
1363
+ updateCartUI(data.cart);
1364
+ } else {
1365
+ console.error('Failed to fetch cart:', data.error);
1366
+ const cart = getCartLocalStorage();
1367
+ updateCartUI(cart);
1368
+ }
1369
+ })
1370
+ .catch(err => {
1371
+ console.error('Error fetching cart:', err);
1372
+ const cart = getCartLocalStorage();
1373
+ updateCartUI(cart);
1374
  });
1375
+
1376
+ const preloadedImages = document.querySelectorAll('link[rel="preload"]');
1377
+ preloadedImages.forEach(link => {
1378
+ const img = new Image();
1379
+ img.src = link.href;
1380
  });
1381
 
 
1382
  const decreaseBtn = document.getElementById('decreaseQuantity');
1383
  const increaseBtn = document.getElementById('increaseQuantity');
1384
  const quantityInput = document.getElementById('quantityInput');
1385
 
1386
+ decreaseBtn.addEventListener('click', function () {
1387
  let currentQuantity = parseInt(quantityInput.value);
1388
  if (currentQuantity > 1) {
1389
  currentQuantity--;
 
1391
  }
1392
  });
1393
 
1394
+ increaseBtn.addEventListener('click', function () {
1395
  let currentQuantity = parseInt(quantityInput.value);
1396
  currentQuantity++;
1397
  quantityInput.value = currentQuantity;
1398
  });
1399
  });
1400
 
1401
+ function debounce(func, wait) {
1402
+ let timeout;
1403
+ return function (...args) {
1404
+ clearTimeout(timeout);
1405
+ timeout = setTimeout(() => func.apply(this, args), wait);
1406
+ };
1407
+ }
1408
+
1409
+ function filterMenu() {
1410
+ const input = document.getElementById('searchBar').value.trim().toLowerCase();
1411
+ const sections = document.querySelectorAll('h3');
1412
+ const items = document.querySelectorAll('.menu-card');
1413
+ let matchedSections = new Set();
1414
+
1415
+ items.forEach(item => {
1416
+ const itemName = item.querySelector('.card-title').innerText.toLowerCase();
1417
+ const itemSection = item.closest('.row').previousElementSibling.innerText.toLowerCase();
1418
+
1419
+ if (itemName.includes(input) || (itemSection && itemSection.includes(input))) {
1420
+ item.style.display = 'block';
1421
+ item.classList.add('visible');
1422
+ matchedSections.add(item.closest('.row'));
1423
+ } else {
1424
+ item.style.display = 'none';
1425
+ }
1426
+ });
1427
+
1428
+ sections.forEach(section => {
1429
+ const sectionRow = section.nextElementSibling;
1430
+ if (matchedSections.has(sectionRow)) {
1431
+ section.style.display = 'block';
1432
+ sectionRow.style.display = 'flex';
1433
+ } else {
1434
+ section.style.display = 'none';
1435
+ sectionRow.style.display = 'none';
1436
+ }
1437
+ });
1438
+
1439
+ if (!input) {
1440
+ sections.forEach(section => {
1441
+ section.style.display = 'block';
1442
+ section.nextElementSibling.style.display = 'flex';
1443
+ });
1444
+ items.forEach(item => {
1445
+ item.style.display = 'block';
1446
+ item.classList.add('visible');
1447
+ });
1448
+ }
1449
+ }
1450
+
1451
  function showItemDetails(name, price, image, description, section, selectedCategory) {
1452
  document.getElementById('modal-name').innerText = name;
1453
  document.getElementById('modal-price').innerText = `$${price}`;
1454
+ const modalImg = document.getElementById('modal-img');
1455
+ if (section.toLowerCase() === 'soft drinks') {
1456
+ modalImg.style.display = 'none';
1457
+ } else {
1458
+ modalImg.style.display = 'block';
1459
+ modalImg.src = image || '/static/placeholder.jpg';
1460
+ }
1461
  document.getElementById('modal-description').innerText = description || 'No description available.';
1462
+ const nutritionalInfoEl = document.getElementById('modal-nutritional-info');
1463
+ const itemDetails = menuItemDetails[name];
1464
+ if (itemDetails && itemDetails.nutritionalInfo) {
1465
+ const { calories, protein, carbs, fats, fiber, sugar } = itemDetails.nutritionalInfo;
1466
+ nutritionalInfoEl.innerText = `[Energy: ${calories} kcal, Protein: ${protein}g, Carbohydrates: ${carbs}g, Fiber: ${fiber}g, Fat: ${fats}g, Sugar: ${sugar}g]`;
1467
+ } else {
1468
+ nutritionalInfoEl.innerText = '[No nutritional info available.]';
1469
+ }
1470
+
1471
+ document.getElementById('addons-list').innerHTML = 'Loading customization options...';
1472
+ document.getElementById('modal-instructions').value = '';
1473
  const modalSectionEl = document.getElementById('modal-section');
1474
  modalSectionEl.setAttribute('data-section', section);
1475
  modalSectionEl.setAttribute('data-category', selectedCategory);
 
 
1476
  document.getElementById('quantityInput').value = 1;
1477
+
1478
+ const prepStyleOptions = document.getElementById('prep-style-options');
1479
+ const typeOptions = document.getElementById('type-options');
1480
+ const spiceLevelOptions = document.getElementById('spice-level-options');
1481
+ const firstRow = document.getElementById('first-row');
1482
+ const firstRowTitle = document.getElementById('first-row-title');
1483
+ const addonsTitle = document.getElementById('addons-title');
1484
+
1485
+ prepStyleOptions.innerHTML = '';
1486
+ typeOptions.innerHTML = '';
1487
+ spiceLevelOptions.innerHTML = '';
1488
+
1489
+ if (section.toLowerCase() === 'starters') {
1490
+ firstRow.style.display = 'block';
1491
+ firstRowTitle.style.display = 'block';
1492
+ addonsTitle.style.display = 'none';
1493
+ } else {
1494
+ firstRow.style.display = 'none';
1495
+ firstRowTitle.style.display = 'none';
1496
+ addonsTitle.style.display = 'block';
1497
+ }
1498
+
1499
+ const addonsList = document.getElementById('addons-list');
1500
+ addonsList.innerHTML = '';
1501
+ const dummySections = [
1502
+ { name: "Beverages", options: ["Sprite ($3)", "Thums Up ($3)", "Virgin Mojito ($3)", "Lemonade ($3)", "Blue Lagoon Mocktail ($3)"] },
1503
+ { name: "Sauces", options: ["Mint Chutney", "Tomato Sauce"] },
1504
+ { name: "Extra Toppings", options: ["Cheese ($2)", "Olives ($1)", "Jalapenos ($1)", "Mushrooms ($2)", "Peppers ($1)"] },
1505
+ { name: "Sides", options: ["Fries ($3)", "Salad ($2)", "Garlic Bread ($3)", "Onion Rings ($2)", "Coleslaw ($2)"] },
1506
+ { name: "Desserts", options: ["Ice Cream ($3)", "Brownie ($3)", "Cheesecake ($4)", "Gulab Jamun ($3)", "Rasmalai ($4)"] }
1507
+ ];
1508
+
1509
+ dummySections.forEach(addon => {
1510
+ const sectionDiv = document.createElement('div');
1511
+ sectionDiv.classList.add('addon-section');
1512
+ sectionDiv.setAttribute('data-addon-name', addon.name);
1513
+
1514
+ const title = document.createElement('h6');
1515
+ title.innerText = addon.name;
1516
+ sectionDiv.appendChild(title);
1517
+
1518
+ const optionsContainer = document.createElement('div');
1519
+ addon.options.forEach((option, index) => {
1520
+ const optionId = `addon-${addon.name.replace(/\s+/g, '')}-${index}`;
1521
+ const listItem = document.createElement('div');
1522
+ listItem.classList.add('form-check');
1523
+
1524
+ listItem.innerHTML = `
1525
+ <input type="checkbox" class="form-check-input addon-option" id="${optionId}" value="${option}"
1526
+ data-name="${option}" data-group="${addon.name}" data-price="0">
1527
+ <label class="form-check-label" for="${optionId}">
1528
+ ${option}
1529
+ </label>
1530
+ `;
1531
+ optionsContainer.appendChild(listItem);
1532
+ });
1533
+ sectionDiv.appendChild(optionsContainer);
1534
+ addonsList.appendChild(sectionDiv);
1535
+ });
1536
+
1537
+ fetch(`/api/addons?item_name=${encodeURIComponent(name)}&item_section=${encodeURIComponent(section)}`)
1538
+ .then(response => response.json())
1539
+ .then(data => {
1540
+ const addonsList = document.getElementById('addons-list');
1541
+ addonsList.innerHTML = '';
1542
+
1543
+ if (!data.success || !data.addons || data.addons.length === 0) {
1544
+ addonsList.innerHTML = '<p>No customization options available.</p>';
1545
+ addonsTitle.style.display = 'none';
1546
+ return;
1547
+ }
1548
+
1549
+ if (section.toLowerCase() === 'starters') {
1550
+ data.addons.forEach(addon => {
1551
+ if (addon.name.toLowerCase() === "choose preparation style") {
1552
+ addon.options.forEach(option => {
1553
+ const optionId = `addon-prep-style-${option}`;
1554
+ const optionHTML = `
1555
+ <div class="form-check">
1556
+ <input type="checkbox" class="form-check-input" id="${optionId}" value="${option}" data-name="${option}" data-group="Choose Preparation Style">
1557
+ <label class="form-check-label" for="${optionId}">
1558
+ ${option}
1559
+ </label>
1560
+ </div>
1561
+ `;
1562
+ prepStyleOptions.innerHTML += optionHTML;
1563
+ });
1564
+ }
1565
+ if (addon.name.toLowerCase() === "type") {
1566
+ addon.options.forEach(option => {
1567
+ const optionId = `addon-type-${option}`;
1568
+ const optionHTML = `
1569
+ <div class="form-check">
1570
+ <input type="checkbox" class="form-check-input" id="${optionId}" value="${option}" data-name="${option}" data-group="Type">
1571
+ <label class="form-check-label" for="${optionId}">
1572
+ ${option}
1573
+ </label>
1574
+ </div>
1575
+ `;
1576
+ typeOptions.innerHTML += optionHTML;
1577
+ });
1578
+ }
1579
+ if (addon.name.toLowerCase() === "spice level") {
1580
+ addon.options.forEach(option => {
1581
+ const optionId = `addon-spice-level-${option}`;
1582
+ const optionHTML = `
1583
+ <div class="form-check">
1584
+ <input type="checkbox" class="form-check-input spice-level-option" id="${optionId}" value="${option}" data-name="${option}" data-group="Spice Level">
1585
+ <label class="form-check-label" for="${optionId}">
1586
+ ${option}
1587
+ </label>
1588
+ </div>
1589
+ `;
1590
+ spiceLevelOptions.innerHTML += optionHTML;
1591
+ });
1592
+ }
1593
+ });
1594
+ }
1595
+
1596
+ data.addons.forEach(addon => {
1597
+ if (section.toLowerCase() === 'starters' &&
1598
+ (addon.name.toLowerCase() === "type" ||
1599
+ addon.name.toLowerCase() === "spice level" ||
1600
+ addon.name.toLowerCase() === "choose preparation style")) {
1601
+ return;
1602
+ }
1603
+
1604
+ const sectionDiv = document.createElement('div');
1605
+ sectionDiv.classList.add('addon-section');
1606
+ sectionDiv.setAttribute('data-addon-name', addon.name);
1607
+
1608
+ const title = document.createElement('h6');
1609
+ title.innerText = addon.name;
1610
+ sectionDiv.appendChild(title);
1611
+
1612
+ const optionsContainer = document.createElement('div');
1613
+ addon.options.forEach((option, index) => {
1614
+ const optionId = `addon-${addon.name.replace(/\s+/g, '')}-${index}`;
1615
+ const listItem = document.createElement('div');
1616
+ listItem.classList.add('form-check');
1617
+
1618
+ listItem.innerHTML = `
1619
+ <input type="checkbox" class="form-check-input ${addon.name.toLowerCase() === 'spice level' ? 'spice-level-option' : 'addon-option'}" id="${optionId}" value="${option}"
1620
+ data-name="${option}" data-group="${addon.name}" data-price="${addon.extra_charge ? addon.extra_charge_amount : 0}">
1621
+ <label class="form-check-label" for="${optionId}">
1622
+ ${option} ${addon.extra_charge ? `($${addon.extra_charge_amount})` : ''}
1623
+ </label>
1624
+ `;
1625
+ optionsContainer.appendChild(listItem);
1626
+ });
1627
+ sectionDiv.appendChild(optionsContainer);
1628
+ addonsList.appendChild(sectionDiv);
1629
+ });
1630
+
1631
+ const startersOrder = [
1632
+ "Select Dip/Sauce",
1633
+ "Extra Add-ons",
1634
+ "Make it a Combo"
1635
+ ];
1636
+
1637
+ const desiredOrder = [
1638
+ "Spice Level",
1639
+ "Choose Preparation Style",
1640
+ "Select Dip/Sauce",
1641
+ "Extra Add-ons",
1642
+ "Make it a Combo",
1643
+ "Type"
1644
+ ];
1645
+
1646
+ const orderToUse = section.toLowerCase() === 'starters' ? startersOrder : desiredOrder;
1647
+
1648
+ const sections = Array.from(addonsList.children);
1649
+ addonsList.innerHTML = '';
1650
+
1651
+ orderToUse.forEach(sectionName => {
1652
+ const section = sections.find(s => s.getAttribute('data-addon-name') === sectionName);
1653
+ if (section) {
1654
+ addonsList.appendChild(section);
1655
+ }
1656
+ });
1657
+
1658
+ sections.forEach(section => {
1659
+ if (!orderToUse.includes(section.getAttribute('data-addon-name'))) {
1660
+ addonsList.appendChild(section);
1661
+ }
1662
+ });
1663
+ })
1664
+ .catch(err => {
1665
+ console.error('Error fetching add-ons:', err);
1666
+ document.getElementById('addons-list').innerHTML = '<p>Error loading customization options.</p>';
1667
+ addonsTitle.style.display = 'none';
1668
+ });
1669
+ }
1670
+
1671
+ document.addEventListener('click', function(event) {
1672
+ if (event.target.classList.contains('spice-level-option') || event.target.classList.contains('addon-option')) {
1673
+ handleAddonClick(event.target);
1674
+ }
1675
+ });
1676
+
1677
+ function handleAddonClick(checkbox) {
1678
+ const groupName = checkbox.getAttribute('data-group');
1679
+ const isMultiSelectGroup = ["Extra Toppings", "Choose Raita/Sides", "Select Dip/Sauce", "Extra Add-ons", "Make it a Combo", "Beverages", "Sauces"].includes(groupName);
1680
+
1681
+ if (groupName.toLowerCase() === "spice level") {
1682
+ const allSpiceLevelCheckboxes = document.querySelectorAll('.spice-level-option');
1683
+ allSpiceLevelCheckboxes.forEach(otherCheckbox => {
1684
+ if (otherCheckbox !== checkbox) {
1685
+ otherCheckbox.checked = false;
1686
+ }
1687
+ });
1688
+ }
1689
+ else if (!isMultiSelectGroup) {
1690
+ const checkboxes = document.querySelectorAll(`.addon-option[data-group="${groupName}"]`);
1691
+ checkboxes.forEach(otherCheckbox => {
1692
+ if (otherCheckbox !== checkbox) {
1693
+ otherCheckbox.checked = false;
1694
+ }
1695
+ });
1696
+ }
1697
  }
1698
 
1699
  function addToCartFromModal() {
1700
  const itemName = document.getElementById('modal-name').innerText;
1701
+ let itemPrice = parseFloat(document.getElementById('modal-price').innerText.replace('$', ''));
1702
+ if (isNaN(itemPrice)) {
1703
+ alert('Invalid price for the item. Please check the item details.');
1704
+ return;
1705
+ }
1706
  const itemImage = document.getElementById('modal-img').src;
1707
  const modalSectionEl = document.getElementById('modal-section');
1708
  const section = modalSectionEl.getAttribute('data-section');
1709
  const selectedCategory = modalSectionEl.getAttribute('data-category');
1710
+ if (!itemName || !itemPrice || !section || !itemImage) {
1711
+ console.error('Missing data for cart item:', { itemName, itemPrice, section, itemImage});
1712
+ return;
1713
+ }
1714
+
1715
  let selectedAddOns = [];
1716
+ const addonsListOptions = document.querySelectorAll('#addons-list .addon-option');
1717
+ addonsListOptions.forEach(option => {
1718
+ if (option.checked) {
1719
+ selectedAddOns.push({
1720
+ name: option.getAttribute('data-name') || 'Default Name',
1721
+ price: parseFloat(option.getAttribute('data-price') || 0)
1722
+ });
1723
+ }
1724
  });
1725
 
1726
+ if (section.toLowerCase() === 'starters') {
1727
+ const prepStyleOptions = Array.from(
1728
+ document.querySelectorAll('#prep-style-options input[type="checkbox"]:checked')
1729
+ ).map(option => ({
1730
+ name: option.getAttribute('data-name') || 'Default Prep Style',
1731
+ price: 0
1732
+ }));
1733
+ const typeOptions = Array.from(
1734
+ document.querySelectorAll('#type-options input[type="checkbox"]:checked')
1735
+ ).map(option => ({
1736
+ name: option.getAttribute('data-name') || 'Default Type',
1737
+ price: 0
1738
+ }));
1739
+ const spiceLevelOption = document.querySelector('#spice-level-options input[type="checkbox"].spice-level-option:checked');
1740
+ const spiceLevelOptions = spiceLevelOption ? [{
1741
+ name: spiceLevelOption.getAttribute('data-name') || 'Default Spice Level',
1742
+ price: 0
1743
+ }] : [];
1744
+ selectedAddOns = [...selectedAddOns, ...prepStyleOptions, ...typeOptions, ...spiceLevelOptions];
1745
+ }
1746
+ const quantity = parseInt(document.getElementById('quantityInput').value) || 1;
1747
+ const instructions = document.getElementById('modal-instructions').value;
1748
  const cartPayload = {
1749
  itemName: itemName,
1750
  itemPrice: itemPrice,
 
1755
  instructions: instructions,
1756
  quantity: quantity
1757
  };
1758
+ fetch('/cart/add', {
1759
+ method: 'POST',
1760
+ headers: {
1761
+ 'Content-Type': 'application/json',
1762
+ },
1763
+ body: JSON.stringify(cartPayload)
1764
+ })
1765
+ .then(response => {
1766
+ if (!response.ok) {
1767
+ throw new Error(`HTTP error! Status: ${response.status}`);
1768
+ }
1769
+ return response.json();
1770
+ })
1771
+ .then(data => {
1772
+ if (data.success) {
1773
+ alert('Item added to cart successfully!');
1774
+ updateCartUI(data.cart);
1775
+ const modal = document.getElementById('itemModal');
1776
+ const modalInstance = bootstrap.Modal.getInstance(modal);
1777
+ modalInstance.hide();
1778
+ } else {
1779
+ console.error('Failed to add item to cart:', data.error);
1780
+ alert(data.error || 'Failed to add item to cart.');
1781
+ }
1782
+ })
1783
+ .catch(err => {
1784
+ console.error('Error adding item to cart:', err);
1785
+ alert('An error occurred while adding the item to the cart: ' + err.message);
1786
+ const cart = addToCartLocalStorage(cartPayload);
1787
+ updateCartUI(cart);
1788
+ const modal = document.getElementById('itemModal');
1789
+ const modalInstance = bootstrap.Modal.getInstance(modal);
1790
+ modalInstance.hide();
1791
+ });
1792
  }
 
1793
  function handleSoftDrinkAdd(button) {
1794
  const buttonContainer = button.closest('.button-container');
1795
  const quantitySelector = buttonContainer.querySelector('.quantity-selector');
 
1797
  const quantityDisplay = quantitySelector.querySelector('.quantity-display');
1798
  const quantityToAddSelect = quantitySelector.querySelector('.quantity-to-add');
1799
  const quantityToAdd = parseInt(quantityToAddSelect.value);
 
 
 
 
 
 
 
 
 
1800
  const itemName = buttonContainer.getAttribute('data-item-name');
1801
  const itemPrice = parseFloat(buttonContainer.getAttribute('data-item-price'));
1802
  const itemImage = buttonContainer.getAttribute('data-item-image');
1803
  const section = buttonContainer.getAttribute('data-item-section');
1804
  const selectedCategory = buttonContainer.getAttribute('data-item-category');
1805
+ addButton.style.display = 'none';
1806
+ quantitySelector.style.display = 'flex';
1807
+ let currentQuantity = parseInt(quantityDisplay.innerText) || 0;
1808
+ currentQuantity += quantityToAdd;
1809
+ quantityDisplay.innerText = currentQuantity;
1810
  const cartPayload = {
1811
  itemName: itemName,
1812
  itemPrice: itemPrice,
 
1817
  instructions: '',
1818
  quantity: quantityToAdd
1819
  };
1820
+ button.disabled = true;
1821
+ fetch('/cart/add', {
1822
+ method: 'POST',
1823
+ headers: {
1824
+ 'Content-Type': 'application/json',
1825
+ },
1826
+ body: JSON.stringify(cartPayload)
1827
+ })
1828
+ .then(response => {
1829
+ if (!response.ok) {
1830
+ throw new Error(`HTTP error! Status: ${response.status}`);
1831
+ }
1832
+ return response.json();
1833
+ })
1834
+ .then(data => {
1835
+ if (data.success) {
1836
+ alert(`Added ${quantityToAdd} item(s) to cart successfully!`);
1837
+ updateCartUI(data.cart);
1838
+ } else {
1839
+ console.error('Failed to add item to cart:', data.error);
1840
+ alert(data.error || 'Failed to add item to cart.');
1841
+ currentQuantity -= quantityToAdd;
1842
+ quantityDisplay.innerText = currentQuantity;
1843
+ }
1844
+ })
1845
+ .catch(err => {
1846
+ console.error('Error adding item to cart:', err);
1847
+ alert('An error occurred while adding the item to the cart: ' + err.message);
1848
+ const cart = addToCartLocalStorage(cartPayload);
1849
+ updateCartUI(cart);
1850
+ })
1851
+ .finally(() => {
1852
+ button.disabled = false;
1853
+ });
1854
  }
 
1855
  function increaseQuantity(button) {
1856
  const buttonContainer = button.closest('.button-container');
1857
  const quantityDisplay = buttonContainer.querySelector('.quantity-display');
1858
  const quantityToAddSelect = buttonContainer.querySelector('.quantity-to-add');
1859
  const quantityToAdd = parseInt(quantityToAddSelect.value);
 
 
 
 
 
 
1860
  const itemName = buttonContainer.getAttribute('data-item-name');
1861
  const itemPrice = parseFloat(buttonContainer.getAttribute('data-item-price'));
1862
  const itemImage = buttonContainer.getAttribute('data-item-image');
1863
  const section = buttonContainer.getAttribute('data-item-section');
1864
  const selectedCategory = buttonContainer.getAttribute('data-item-category');
1865
+ let currentQuantity = parseInt(quantityDisplay.innerText) || 0;
1866
+ currentQuantity += quantityToAdd;
1867
+ quantityDisplay.innerText = currentQuantity;
1868
  const cartPayload = {
1869
  itemName: itemName,
1870
  itemPrice: itemPrice,
 
1875
  instructions: '',
1876
  quantity: quantityToAdd
1877
  };
1878
+ fetch('/cart/add', {
1879
+ method: 'POST',
1880
+ headers: {
1881
+ 'Content-Type': 'application/json',
1882
+ },
1883
+ body: JSON.stringify(cartPayload)
1884
+ })
1885
+ .then(response => {
1886
+ if (!response.ok) {
1887
+ throw new Error(`HTTP error! Status: ${response.status}`);
1888
+ }
1889
+ return response.json();
1890
+ })
1891
+ .then(data => {
1892
+ if (data.success) {
1893
+ alert(`Added ${quantityToAdd} item(s) to cart successfully!`);
1894
+ updateCartUI(data.cart);
1895
+ } else {
1896
+ console.error('Failed to add item to cart:', data.error);
1897
+ alert(data.error || 'Failed to add item to cart.');
1898
+ currentQuantity -= quantityToAdd;
1899
+ quantityDisplay.innerText = currentQuantity;
1900
+ }
1901
+ })
1902
+ .catch(err => {
1903
+ console.error('Error adding item to cart:', err);
1904
+ alert('An error occurred while adding the item to the cart: ' + err.message);
1905
+ const cart = addToCartLocalStorage(cartPayload);
1906
+ updateCartUI(cart);
1907
+ });
1908
  }
 
1909
  function decreaseQuantity(button) {
1910
  const buttonContainer = button.closest('.button-container');
1911
  const quantityDisplay = buttonContainer.querySelector('.quantity-display');
 
1914
  const addButton = buttonContainer.querySelector('.add-to-cart-btn');
1915
  const quantitySelector = buttonContainer.querySelector('.quantity-selector');
1916
  let currentQuantity = parseInt(quantityDisplay.innerText);
 
1917
  if (currentQuantity <= quantityToRemove) {
 
1918
  const itemName = buttonContainer.getAttribute('data-item-name');
1919
+ fetch(`/cart/remove?item_name=${encodeURIComponent(itemName)}&quantity=${currentQuantity}&instructions=&addons=[]`, {
1920
+ method: 'POST',
1921
+ headers: {
1922
+ 'Content-Type': 'application/json',
1923
+ }
1924
+ })
1925
+ .then(response => {
1926
+ if (!response.ok) {
1927
+ throw new Error(`HTTP error! Status: ${response.status}`);
1928
+ }
1929
+ return response.json();
1930
+ })
1931
+ .then(data => {
1932
+ if (data.success) {
1933
+ updateCartUI(data.cart);
1934
+ addButton.style.display = 'block';
1935
+ quantitySelector.style.display = 'none';
1936
+ quantityDisplay.innerText = 0;
1937
+ } else {
1938
+ console.error('Failed to remove item from cart:', data.error);
1939
+ alert(data.error || 'Failed to remove item from cart.');
1940
+ }
1941
+ })
1942
+ .catch(err => {
1943
+ console.error('Error removing item from cart:', err);
1944
+ alert('An error occurred while removing the item from the cart: ' + err.message);
1945
+ const cart = removeFromCartLocalStorage(itemName, currentQuantity, '', []);
1946
+ updateCartUI(cart);
1947
+ addButton.style.display = 'block';
1948
+ quantitySelector.style.display = 'none';
1949
+ quantityDisplay.innerText = 0;
1950
+ });
1951
  } else {
 
1952
  currentQuantity -= quantityToRemove;
1953
  quantityDisplay.innerText = currentQuantity;
 
1954
  const itemName = buttonContainer.getAttribute('data-item-name');
1955
+ fetch(`/cart/remove?item_name=${encodeURIComponent(itemName)}&quantity=${quantityToRemove}&instructions=&addons=[]`, {
1956
+ method: 'POST',
1957
+ headers: {
1958
+ 'Content-Type': 'application/json',
1959
+ }
1960
+ })
1961
+ .then(response => {
1962
+ if (!response.ok) {
1963
+ throw new Error(`HTTP error! Status: ${response.status}`);
1964
+ }
1965
+ return response.json();
1966
+ })
1967
+ .then(data => {
1968
+ if (data.success) {
1969
+ alert(`Removed ${quantityToRemove} item(s) from cart successfully!`);
1970
+ updateCartUI(data.cart);
1971
+ } else {
1972
+ console.error('Failed to remove item from cart:', data.error);
1973
+ alert(data.error || 'Failed to remove item from cart.');
1974
+ currentQuantity += quantityToRemove;
1975
+ quantityDisplay.innerText = currentQuantity;
1976
+ }
1977
+ })
1978
+ .catch(err => {
1979
+ console.error('Error removing item from cart:', err);
1980
+ alert('An error occurred while removing the item from the cart: ' + err.message);
1981
+ const cart = removeFromCartLocalStorage(itemName, quantityToRemove, '', []);
1982
+ updateCartUI(cart);
1983
+ });
1984
  }
1985
  }
1986
+ function updateCartUI(cart) {
1987
+ if (!Array.isArray(cart)) {
1988
+ console.error('Invalid cart data:', cart);
1989
+ return;
1990
+ }
1991
+
1992
+ // Calculate total quantity of items in cart
1993
+ let totalQuantity = 0;
1994
+ cart.forEach(item => {
1995
+ totalQuantity += item.quantity;
1996
+ });
1997
+
1998
+ // Update cart item count badge
1999
+ const cartItemCount = document.getElementById('cart-item-count');
2000
+ if (cartItemCount) {
2001
+ cartItemCount.innerText = totalQuantity;
2002
+ if (totalQuantity > 0) {
2003
+ cartItemCount.classList.add('active');
2004
+ } else {
2005
+ cartItemCount.classList.remove('active');
2006
+ }
2007
+ }
2008
+ // Update quantity displays for soft drinks
2009
+ const buttonContainers = document.querySelectorAll('.button-container');
2010
+ buttonContainers.forEach(container => {
2011
+ const itemName = container.getAttribute('data-item-name');
2012
+ const quantityDisplay = container.querySelector('.quantity-display');
2013
+ const addButton = container.querySelector('.add-to-cart-btn');
2014
+ const quantitySelector = container.querySelector('.quantity-selector');
2015
+ const cartItem = cart.find(item =>
2016
+ item.itemName === itemName &&
2017
+ item.instructions === '' &&
2018
+ JSON.stringify(item.addons) === JSON.stringify([])
2019
+ );
2020
+ if (cartItem && cartItem.quantity > 0) {
2021
+ quantityDisplay.innerText = cartItem.quantity;
2022
+ addButton.style.display = 'none';
2023
+ quantitySelector.style.display = 'flex';
2024
+ } else {
2025
+ quantityDisplay.innerText = 0;
2026
+ addButton.style.display = 'block';
2027
+ quantitySelector.style.display = 'none';
2028
+ }
2029
+ });
2030
+ }
2031
  </script>
2032
  </body>
2033
  </html>