lokesh341 commited on
Commit
8d0fd70
·
verified ·
1 Parent(s): 46562a1

Update templates/menu.html

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