DSatishchandra commited on
Commit
2bfc0ad
·
verified ·
1 Parent(s): 2c62acb

Update templates/menu.html

Browse files
Files changed (1) hide show
  1. templates/menu.html +243 -179
templates/menu.html CHANGED
@@ -8,8 +8,7 @@
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
  <style>
11
- /* General Body Styling */
12
- body {
13
  font-family: Arial, sans-serif;
14
  background-color: #fdf4e3; /* Updated background color */
15
  margin: 0;
@@ -17,14 +16,10 @@ body {
17
  display: flex;
18
  flex-direction: column;
19
  }
20
-
21
- /* Container */
22
  .container {
23
  max-width: 900px;
24
- margin-top: 10px;
25
  }
26
-
27
- /* Menu Card */
28
  .menu-card {
29
  max-width: 350px;
30
  border-radius: 15px;
@@ -32,27 +27,20 @@ body {
32
  background-color: #fff;
33
  margin: auto;
34
  }
35
-
36
- /* Menu Image */
37
  .menu-image {
38
  height: 200px;
39
  width: 100%;
40
  object-fit: cover;
41
  border-radius: 15px 15px 0 0;
42
  }
43
-
44
- /* Card Title and Text */
45
  .card-title {
46
  font-size: 1.2rem;
47
  font-weight: bold;
48
  }
49
-
50
  .card-text {
51
  font-size: 1rem;
52
  color: #6c757d;
53
  }
54
-
55
- /* Button Primary */
56
  .btn-primary {
57
  font-size: 13px;
58
  font-weight: bold;
@@ -61,27 +49,22 @@ body {
61
  background-color: #0FAA39; /* Updated button background color */
62
  border-color: #0FAA39;
63
  }
64
-
65
  .btn-primary:hover {
66
  background-color: #0FAA39;
67
  border-color: #ffffff;
68
  }
69
-
70
  .btn-primary:active,
71
  .btn-primary:focus {
72
  background-color: #4a5d68;
73
  border-color: #ffffff;
74
  box-shadow: none;
75
  }
76
-
77
- /* View Cart Button */
78
  .view-cart-container {
79
  position: fixed;
80
  bottom: 20px;
81
  right: 20px;
82
  z-index: 999;
83
  }
84
-
85
  .view-cart-button {
86
  background-color: #0FAA39; /* Updated View Cart button background color */
87
  color: #fff;
@@ -95,17 +78,13 @@ body {
95
  align-items: center;
96
  justify-content: center;
97
  }
98
-
99
  .view-cart-button:hover {
100
  background-color: #109835; /* Slightly darker shade for hover effect */
101
  text-decoration: none;
102
  }
103
-
104
- /* Avatar Dropdown */
105
  .avatar-dropdown-container {
106
  position: relative;
107
  }
108
-
109
  .avatar-icon {
110
  width: 40px;
111
  height: 40px;
@@ -119,7 +98,6 @@ body {
119
  font-size: 20px;
120
  font-weight: bold;
121
  }
122
-
123
  .dropdown-menu {
124
  position: absolute;
125
  right: 0;
@@ -130,11 +108,9 @@ body {
130
  box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
131
  display: none;
132
  }
133
-
134
  .avatar-dropdown-container:hover .dropdown-menu {
135
  display: block;
136
  }
137
-
138
  .dropdown-menu .dropdown-item {
139
  padding: 10px 15px;
140
  text-decoration: none;
@@ -142,16 +118,12 @@ body {
142
  border-bottom: 1px solid #ddd;
143
  display: block; /* Make each item stack vertically */
144
  }
145
-
146
  .dropdown-menu .dropdown-item:last-child {
147
  border-bottom: none; /* Remove the bottom border from the last item */
148
  }
149
-
150
  .dropdown-menu .dropdown-item:hover {
151
  background-color: #f1f1f1;
152
  }
153
-
154
- /* Fixed Search Container */
155
  .fixed-search-container {
156
  position: absolute;
157
  top: 90px; /* Move it slightly lower */
@@ -165,17 +137,96 @@ body {
165
  border-radius: 25px;
166
  box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2);
167
  }
168
-
169
- /* Form Category Filter */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  form.text-center.mb-4 {
171
  display: flex;
172
  flex-direction: column;
173
  align-items: center;
174
  justify-content: center;
175
- margin-bottom: 5px; /* Reduced bottom margin */
176
  }
177
-
178
- /* Adjust Category Filter Radio Buttons */
179
  .form-check {
180
  display: inline-block;
181
  margin-right: 5px; /* Reduced space between radio button and label */
@@ -183,20 +234,16 @@ form.text-center.mb-4 {
183
  margin-top: 10px; /* Adds space between categories and Customized Dish */
184
  vertical-align: middle; /* Align radio buttons vertically */
185
  }
186
-
187
  .form-check-inline {
188
  display: inline-block;
189
  margin-right: 5px; /* Decrease space between each radio button */
190
  }
191
-
192
  .form-check-label {
193
  display: inline-block;
194
  font-size: 16px;
195
  margin-left: 0px; /* Spacing between radio button and label */
196
  vertical-align: middle; /* Align label vertically */
197
  }
198
-
199
- /* Custom Radio Button */
200
  .custom-radio {
201
  appearance: none;
202
  -webkit-appearance: none;
@@ -209,14 +256,12 @@ form.text-center.mb-4 {
209
  cursor: pointer;
210
  position: relative;
211
  display: inline-block;
212
- vertical-align: middle; /* Align vertically with text */
213
  }
214
-
215
  .custom-radio:checked {
216
  background-color: #4CAF50; /* Green color when checked */
217
  border-color: #4CAF50; /* Matching border color */
218
  }
219
-
220
  .custom-radio:checked::after {
221
  content: '';
222
  position: relative;
@@ -224,56 +269,39 @@ form.text-center.mb-4 {
224
  left: 5px;
225
  border-radius: 50%;
226
  }
227
-
228
  .custom-radio:hover {
229
  border-color: #388E3C;
230
  }
231
-
232
- /* Add-ons and Customization Sections */
233
- .addon-section {
234
- background-color: #f8f9fa; /* Light gray background */
235
- border: 2px solid #ff6b35; /* Border color */
236
- border-radius: 8px;
237
- padding: 12px;
238
- margin-bottom: 10px; /* Spacing between sections */
239
- }
240
-
241
- .addon-section h6 {
242
- margin-bottom: 10px;
243
- font-size: 1.1rem;
244
- font-weight: bold;
245
- color: #444;
246
  }
247
-
248
- .addon-section .form-check {
249
- margin-left: 10px;
 
250
  }
251
-
252
- /* Modal Footer Styling */
253
  .modal-footer {
254
  display: flex;
255
  align-items: center;
256
  justify-content: space-between; /* Space between quantity and Add to Cart button */
257
  padding: 10px;
258
  }
259
-
260
  .modal-footer .d-flex {
261
  display: flex;
262
  align-items: center;
263
  gap: 10px; /* Space between quantity buttons */
264
  }
265
-
266
  .modal-footer .btn {
267
  height: 40px; /* Set consistent button height */
268
  padding: 0 15px; /* Adjust padding to fit inside the buttons */
269
  }
270
-
271
  .modal-footer .form-control {
272
  width: 50px; /* Fixed width for quantity input */
273
  height: 40px; /* Match the height of buttons */
274
  text-align: center; /* Center the value inside the input */
275
  }
276
-
277
  .modal-footer .btn-primary {
278
  background-color: #0FAA39; /* Green background for Add to Cart button */
279
  border-color: #0FAA39; /* Border color to match button background */
@@ -285,29 +313,23 @@ form.text-center.mb-4 {
285
  align-items: center;
286
  width: auto; /* Auto width to adjust to button text */
287
  }
288
-
289
  .modal-footer .btn-outline-secondary {
290
  height: 40px; /* Ensure quantity buttons are the same size */
291
  width: 40px; /* Make sure the buttons are square */
292
  }
293
-
294
- /* Responsive Adjustments */
295
  @media (max-width: 576px) {
296
  /* Responsive adjustments for smaller screens */
297
  .modal-dialog {
298
  max-width: 98%; /* Adjust modal width for smaller screens */
299
  }
300
-
301
  .modal-footer .btn {
302
  height: 35px; /* Smaller buttons for small screens */
303
  }
304
-
305
  .modal-footer .form-control {
306
  width: 40px; /* Adjust input size for smaller screens */
307
  height: 35px;
308
  }
309
  }
310
-
311
  </style>
312
  </head>
313
  <body>
@@ -341,6 +363,9 @@ form.text-center.mb-4 {
341
  {% if selected_category == category %}checked{% endif %} onchange="this.form.submit()">
342
  <label class="form-check-label" for="category-{{ category }}">{{ category }}</label>
343
  {% endfor %}
 
 
 
344
  <input type="radio" id="category-CustomizedDish" name="category" value="Customized Dish" class="custom-radio"
345
  {% if selected_category == "Customized Dish" %}checked{% endif %} onchange="this.form.submit()">
346
  <label class="form-check-label" for="category-CustomizedDish">Customized Dish</label>
@@ -402,105 +427,131 @@ form.text-center.mb-4 {
402
  </a>
403
  </div>
404
 
405
- <!-- Bootstrap JS -->
406
- <script src="https://cdn.jsdelivr.net/npm/[email protected]-alpha1/dist/js/bootstrap.bundle.min.js"></script>
407
-
408
- <!-- Modal for Item Details -->
409
- <div class="modal fade" id="itemModal" tabindex="-1" aria-labelledby="itemModalLabel" aria-hidden="true">
410
- <div class="modal-dialog modal-dialog-centered">
411
- <div class="modal-content">
412
- <div class="modal-header">
413
- <h5 class="modal-title" id="itemModalLabel">Item Details</h5>
414
- <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
 
 
 
 
 
 
 
 
 
 
 
415
  </div>
416
- <div class="modal-body">
417
- <!-- Item Image -->
418
- <img id="modal-img" class="img-fluid rounded mb-3 d-block mx-auto" alt="Item Image" style="max-height: 200px; object-fit: cover;">
419
- <!-- Item Name -->
420
- <h5 id="modal-name" class="fw-bold text-center"></h5>
421
- <!-- Item Price -->
422
- <p id="modal-price" class="text-muted text-center"></p>
423
- <!-- Item Description -->
424
- <p id="modal-description" class="text-secondary"></p>
425
- <!-- Add-ons -->
426
- <div id="modal-addons" class="modal-addons mt-4">
427
- <h6>Customization Options</h6>
428
- <div id="addons-list" class="addons-container">Loading customization options...</div>
429
- </div>
430
-
431
-
432
- <div class="mt-4">
433
- <h6>Custom Request</h6>
434
- <textarea id="modal-instructions" class="form-control" placeholder="Enter any special instructions here..."></textarea>
435
- </div>
436
- <span id="modal-section" data-section="" data-category="" style="display: none;"></span>
437
-
438
  </div>
439
- <div class="modal-footer">
440
- <button type="button" class="btn btn-primary" onclick="addToCartFromModal()">Add to Cart</button>
441
- <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
 
 
 
 
 
 
442
  </div>
 
 
443
  </div>
444
  </div>
445
  </div>
 
446
 
447
- <!-- JavaScript -->
448
- <script>
449
- function showItemDetails(name, price, image, description, section, selectedCategory) {
450
- document.getElementById('modal-name').innerText = name;
451
- document.getElementById('modal-price').innerText = `$${price}`;
452
- document.getElementById('modal-img').src = image || '/static/placeholder.jpg';
453
- document.getElementById('modal-description').innerText = description || 'No description available.';
454
- document.getElementById('addons-list').innerHTML = 'Loading customization options...';
455
- document.getElementById('modal-instructions').value = '';
456
- // Set section and category for reference
457
- const modalSectionEl = document.getElementById('modal-section');
458
- modalSectionEl.setAttribute('data-section', section);
459
- modalSectionEl.setAttribute('data-category', selectedCategory);
460
- // Fetch customization options based on the section
461
- fetch(`/api/addons?item_name=${encodeURIComponent(name)}&item_section=${encodeURIComponent(section)}`)
462
- .then(response => response.json())
463
- .then(data => {
464
- const addonsList = document.getElementById('addons-list');
465
- addonsList.innerHTML = ''; // Clear previous content
466
 
467
- if (!data.success || !data.addons || data.addons.length === 0) {
468
- addonsList.innerHTML = '<p>No customization options available.</p>';
469
- return;
470
- }
471
- // Display customization options inside styled divs
472
- data.addons.forEach(addon => {
473
- const sectionDiv = document.createElement('div');
474
- sectionDiv.classList.add('addon-section'); // Add styling class
475
- // Add section title
476
- const title = document.createElement('h6');
477
- title.innerText = addon.name;
478
- sectionDiv.appendChild(title);
479
- // Create options list
480
- const optionsContainer = document.createElement('div');
481
- addon.options.forEach((option, index) => {
482
- const optionId = `addon-${addon.name.replace(/\s+/g, '')}-${index}`;
483
- const listItem = document.createElement('div');
484
- listItem.classList.add('form-check');
485
- listItem.innerHTML = `
486
- <input type="checkbox" class="form-check-input addon-option" id="${optionId}" value="${option}"
487
- data-name="${option}" data-price="${addon.extra_charge ? addon.extra_charge_amount : 0}">
488
- <label class="form-check-label" for="${optionId}">
489
- ${option} ${addon.extra_charge ? `($${addon.extra_charge_amount})` : ''}
490
- </label>
491
- `;
492
- optionsContainer.appendChild(listItem);
493
- });
494
- sectionDiv.appendChild(optionsContainer);
495
- addonsList.appendChild(sectionDiv);
 
 
 
 
 
 
496
  });
497
- })
498
- .catch(err => {
499
- console.error('Error fetching add-ons:', err);
500
- document.getElementById('addons-list').innerHTML = '<p>Error loading customization options.</p>';
501
  });
 
 
 
 
 
 
 
 
 
 
502
  }
503
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
504
  function filterMenu() {
505
  let input = document.getElementById('searchBar').value.toLowerCase(); // Get the value from search bar
506
  let sections = document.querySelectorAll('h3'); // Select section headers
@@ -533,24 +584,21 @@ form.text-center.mb-4 {
533
  }
534
  });
535
  }
536
-
537
  function addToCartFromModal() {
538
  const itemName = document.getElementById('modal-name').innerText;
539
  let itemPrice = parseFloat(document.getElementById('modal-price').innerText.replace('$', ''));
540
-
541
  // Validate item price
542
  if (isNaN(itemPrice)) {
543
  alert('Invalid price for the item. Please check the item details.');
544
  return;
545
  }
546
-
547
  const itemImage = document.getElementById('modal-img').src;
548
  console.log(itemName, itemPrice, itemImage); // Log values for debugging
549
  const modalSectionEl = document.getElementById('modal-section');
550
  const section = modalSectionEl.getAttribute('data-section');
551
  const selectedCategory = modalSectionEl.getAttribute('data-category');
552
- if (!itemName || !itemPrice || !section) {
553
- console.error('Missing data for cart item:', { itemName, itemPrice, section });
554
  return;
555
  }
556
 
@@ -558,11 +606,12 @@ function addToCartFromModal() {
558
  let selectedAddOns = Array.from(
559
  document.querySelectorAll('#addons-list input[type="checkbox"]:checked')
560
  ).map(addon => ({
561
- name: addon.getAttribute('data-name') || 'Default Name', //Fallback Name
562
  price: parseFloat(addon.getAttribute('data-price') || 0)
563
  }));
 
 
564
  const instructions = document.getElementById('modal-instructions').value;
565
-
566
  // Prepare data for the cart
567
  const cartPayload = {
568
  itemName: itemName,
@@ -571,9 +620,9 @@ function addToCartFromModal() {
571
  section: section,
572
  category: selectedCategory,
573
  addons: selectedAddOns,
574
- instructions: instructions
 
575
  };
576
-
577
  // Send the cart data to the server
578
  fetch('/cart/add', {
579
  method: 'POST',
@@ -607,14 +656,15 @@ function updateCartUI(cart) {
607
  const cartIcon = document.getElementById('cart-icon');
608
  cartIcon.innerText = cart.length; // Assuming cart is an array of items
609
  }
610
-
611
  function updateCartDisplay(cart) {
612
  if (!Array.isArray(cart)) {
613
  console.error('Invalid cart data:', cart);
614
  return;
615
  }
 
616
  const cartCountElement = document.getElementById('cart-count');
617
- cartCountElement.innerText = cart.length; // Update cart item count
 
618
  // Optionally, show a small success notification that the item was added
619
  const successNotification = document.createElement('div');
620
  successNotification.classList.add('success-notification');
@@ -624,19 +674,36 @@ function updateCartDisplay(cart) {
624
  successNotification.remove(); // Remove success notification after a few seconds
625
  }, 2000);
626
  }
627
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
628
  // Function to round reward points to a single digit
629
  function roundRewardPoints() {
630
  // Get the reward points element
631
  let rewardPointsElement = document.getElementById('reward-points');
632
-
633
  // Check if the element exists in the DOM
634
  if (rewardPointsElement) {
635
  let rewardPointsText = rewardPointsElement.innerText.trim(); // Get and trim the value to remove any extra spaces
636
-
637
  // Check if the innerText is a valid number
638
  let rewardPoints = parseFloat(rewardPointsText);
639
-
640
  // If it's a valid number, round it to 1 decimal place
641
  if (!isNaN(rewardPoints)) {
642
  rewardPointsElement.innerText = rewardPoints.toFixed(1); // Round to 1 decimal place
@@ -655,7 +722,4 @@ function roundRewardPoints() {
655
  <!-- Bootstrap JS -->
656
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
657
  </body>
658
- </html>
659
- </script>
660
- </body>
661
  </html>
 
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
  <style>
11
+ body {
 
12
  font-family: Arial, sans-serif;
13
  background-color: #fdf4e3; /* Updated background color */
14
  margin: 0;
 
16
  display: flex;
17
  flex-direction: column;
18
  }
 
 
19
  .container {
20
  max-width: 900px;
21
+ /*margin-top: 10px; /* Adjust spacing to control space between filter and menu */
22
  }
 
 
23
  .menu-card {
24
  max-width: 350px;
25
  border-radius: 15px;
 
27
  background-color: #fff;
28
  margin: auto;
29
  }
 
 
30
  .menu-image {
31
  height: 200px;
32
  width: 100%;
33
  object-fit: cover;
34
  border-radius: 15px 15px 0 0;
35
  }
 
 
36
  .card-title {
37
  font-size: 1.2rem;
38
  font-weight: bold;
39
  }
 
40
  .card-text {
41
  font-size: 1rem;
42
  color: #6c757d;
43
  }
 
 
44
  .btn-primary {
45
  font-size: 13px;
46
  font-weight: bold;
 
49
  background-color: #0FAA39; /* Updated button background color */
50
  border-color: #0FAA39;
51
  }
 
52
  .btn-primary:hover {
53
  background-color: #0FAA39;
54
  border-color: #ffffff;
55
  }
 
56
  .btn-primary:active,
57
  .btn-primary:focus {
58
  background-color: #4a5d68;
59
  border-color: #ffffff;
60
  box-shadow: none;
61
  }
 
 
62
  .view-cart-container {
63
  position: fixed;
64
  bottom: 20px;
65
  right: 20px;
66
  z-index: 999;
67
  }
 
68
  .view-cart-button {
69
  background-color: #0FAA39; /* Updated View Cart button background color */
70
  color: #fff;
 
78
  align-items: center;
79
  justify-content: center;
80
  }
 
81
  .view-cart-button:hover {
82
  background-color: #109835; /* Slightly darker shade for hover effect */
83
  text-decoration: none;
84
  }
 
 
85
  .avatar-dropdown-container {
86
  position: relative;
87
  }
 
88
  .avatar-icon {
89
  width: 40px;
90
  height: 40px;
 
98
  font-size: 20px;
99
  font-weight: bold;
100
  }
 
101
  .dropdown-menu {
102
  position: absolute;
103
  right: 0;
 
108
  box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
109
  display: none;
110
  }
 
111
  .avatar-dropdown-container:hover .dropdown-menu {
112
  display: block;
113
  }
 
114
  .dropdown-menu .dropdown-item {
115
  padding: 10px 15px;
116
  text-decoration: none;
 
118
  border-bottom: 1px solid #ddd;
119
  display: block; /* Make each item stack vertically */
120
  }
 
121
  .dropdown-menu .dropdown-item:last-child {
122
  border-bottom: none; /* Remove the bottom border from the last item */
123
  }
 
124
  .dropdown-menu .dropdown-item:hover {
125
  background-color: #f1f1f1;
126
  }
 
 
127
  .fixed-search-container {
128
  position: absolute;
129
  top: 90px; /* Move it slightly lower */
 
137
  border-radius: 25px;
138
  box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2);
139
  }
140
+ /* Ensure the category filter dropdown does not overlap */
141
+ form.text-center.mb-4 {
142
+ margin-top: 10px; /* No margin at the top */
143
+ margin-bottom: 0px; /* Small space at the bottom */
144
+ }
145
+ /* Ensure the container has enough margin so nothing is overlapped */
146
+ .container {
147
+ margin-top: 10px; /* Adjust spacing based on navbar and search bar */
148
+ padding-top: 0 !important; /* Ensure no padding is added by default */
149
+ }
150
+ h1.text-center {
151
+ margin-top: 10px; /* Reduced space above */
152
+ padding-top: 0 !important; /* Removed padding */
153
+ font-weight: semi-bold; /* Make the "Menu" text bold */
154
+ }
155
+ .fixed-top-bar {
156
+ /* Remove the fixed positioning */
157
+ position: relative; /* Change from fixed to relative */
158
+ top: 0;
159
+ left: 0;
160
+ width: 100%;
161
+ height: 54px;
162
+ background-color: #FF6B35;
163
+ color: white;
164
+ padding: 15px;
165
+ display: flex;
166
+ justify-content: space-between;
167
+ align-items: center; /* Vertically align items */
168
+ z-index: 1000; /* Make sure it's still above other content */
169
+ }
170
+ .avatar-dropdown-container {
171
+ position: absolute;
172
+ right: 20px; /* Adjust the value as needed to position it properly */
173
+ top: 50%; /* Adjust top to place it within the header */
174
+ transform: translateY(-50%); /* Correct the alignment to be perfectly centered */
175
+ display: flex;
176
+ align-items: right;
177
+ justify-content: center;
178
+ }
179
+ .search-bar-container {
180
+ padding: 10px;
181
+ position: absolute;
182
+ left: 20px;
183
+ top: 50%;
184
+ transform: translateY(-50%);
185
+ display: flex;
186
+ justify-content: flex-start;
187
+ align-items: center;
188
+ width: 300px; /* Adjust width as needed */
189
+ }
190
+ .search-bar-container input {
191
+ width: 85%;
192
+ padding: 8px 10px 8px 30px; /* Add padding for the icon */
193
+ font-size: 16px;
194
+ border-radius: 10px;
195
+ border: none;
196
+ }
197
+ .search-icon {
198
+ position: absolute;
199
+ left: 15px; /* Position the icon inside the input box */
200
+ font-size: 20px;
201
+ color: #888; /* Icon color */
202
+ }
203
+ /* Style for customization sections */
204
+ .addon-section {
205
+ background-color: #f8f9fa; /* Light gray background */
206
+ border: 2px solid #ff6b35; /* Border color */
207
+ border-radius: 8px;
208
+ padding: 12px;
209
+ margin-bottom: 10px; /* Spacing between sections */
210
+ }
211
+ /* Customization section title */
212
+ .addon-section h6 {
213
+ margin-bottom: 10px;
214
+ font-size: 1.1rem;
215
+ font-weight: bold;
216
+ color: #444;
217
+ }
218
+ /* Style for add-on checkboxes */
219
+ .addon-section .form-check {
220
+ margin-left: 10px;
221
+ }
222
+ /* Category Filter with Custom Radio Buttons */
223
  form.text-center.mb-4 {
224
  display: flex;
225
  flex-direction: column;
226
  align-items: center;
227
  justify-content: center;
228
+ margin-bottom: 5px; /* Reduce bottom margin */
229
  }
 
 
230
  .form-check {
231
  display: inline-block;
232
  margin-right: 5px; /* Reduced space between radio button and label */
 
234
  margin-top: 10px; /* Adds space between categories and Customized Dish */
235
  vertical-align: middle; /* Align radio buttons vertically */
236
  }
 
237
  .form-check-inline {
238
  display: inline-block;
239
  margin-right: 5px; /* Decrease space between each radio button */
240
  }
 
241
  .form-check-label {
242
  display: inline-block;
243
  font-size: 16px;
244
  margin-left: 0px; /* Spacing between radio button and label */
245
  vertical-align: middle; /* Align label vertically */
246
  }
 
 
247
  .custom-radio {
248
  appearance: none;
249
  -webkit-appearance: none;
 
256
  cursor: pointer;
257
  position: relative;
258
  display: inline-block;
259
+ vertical-align: middle; /* Align vertically with text */
260
  }
 
261
  .custom-radio:checked {
262
  background-color: #4CAF50; /* Green color when checked */
263
  border-color: #4CAF50; /* Matching border color */
264
  }
 
265
  .custom-radio:checked::after {
266
  content: '';
267
  position: relative;
 
269
  left: 5px;
270
  border-radius: 50%;
271
  }
 
272
  .custom-radio:hover {
273
  border-color: #388E3C;
274
  }
275
+ /* Optional: Style the labels */
276
+ .form-check-label {
277
+ font-size: 16px;
278
+ margin-left: 5px; /* Space between the radio button and the label */
 
 
 
 
 
 
 
 
 
 
 
279
  }
280
+ .cart-container {
281
+ display: flex;
282
+ align-items: center;
283
+ gap: 10px;
284
  }
 
 
285
  .modal-footer {
286
  display: flex;
287
  align-items: center;
288
  justify-content: space-between; /* Space between quantity and Add to Cart button */
289
  padding: 10px;
290
  }
 
291
  .modal-footer .d-flex {
292
  display: flex;
293
  align-items: center;
294
  gap: 10px; /* Space between quantity buttons */
295
  }
 
296
  .modal-footer .btn {
297
  height: 40px; /* Set consistent button height */
298
  padding: 0 15px; /* Adjust padding to fit inside the buttons */
299
  }
 
300
  .modal-footer .form-control {
301
  width: 50px; /* Fixed width for quantity input */
302
  height: 40px; /* Match the height of buttons */
303
  text-align: center; /* Center the value inside the input */
304
  }
 
305
  .modal-footer .btn-primary {
306
  background-color: #0FAA39; /* Green background for Add to Cart button */
307
  border-color: #0FAA39; /* Border color to match button background */
 
313
  align-items: center;
314
  width: auto; /* Auto width to adjust to button text */
315
  }
 
316
  .modal-footer .btn-outline-secondary {
317
  height: 40px; /* Ensure quantity buttons are the same size */
318
  width: 40px; /* Make sure the buttons are square */
319
  }
 
 
320
  @media (max-width: 576px) {
321
  /* Responsive adjustments for smaller screens */
322
  .modal-dialog {
323
  max-width: 98%; /* Adjust modal width for smaller screens */
324
  }
 
325
  .modal-footer .btn {
326
  height: 35px; /* Smaller buttons for small screens */
327
  }
 
328
  .modal-footer .form-control {
329
  width: 40px; /* Adjust input size for smaller screens */
330
  height: 35px;
331
  }
332
  }
 
333
  </style>
334
  </head>
335
  <body>
 
363
  {% if selected_category == category %}checked{% endif %} onchange="this.form.submit()">
364
  <label class="form-check-label" for="category-{{ category }}">{{ category }}</label>
365
  {% endfor %}
366
+ </div>
367
+ <!-- Separate Customized Dish radio button in a new div to align it properly -->
368
+ <div class="form-check">
369
  <input type="radio" id="category-CustomizedDish" name="category" value="Customized Dish" class="custom-radio"
370
  {% if selected_category == "Customized Dish" %}checked{% endif %} onchange="this.form.submit()">
371
  <label class="form-check-label" for="category-CustomizedDish">Customized Dish</label>
 
427
  </a>
428
  </div>
429
 
430
+ <!-- Modal for Item Details -->
431
+ <div class="modal fade" id="itemModal" tabindex="-1" aria-labelledby="itemModalLabel" aria-hidden="true">
432
+ <div class="modal-dialog modal-dialog-centered">
433
+ <div class="modal-content">
434
+ <div class="modal-header">
435
+ <h5 class="modal-title" id="itemModalLabel">Item Details</h5>
436
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
437
+ </div>
438
+ <div class="modal-body">
439
+ <!-- Item Image -->
440
+ <img id="modal-img" class="img-fluid rounded mb-3 d-block mx-auto" alt="Item Image" style="max-height: 200px; object-fit: cover;">
441
+ <!-- Item Name -->
442
+ <h5 id="modal-name" class="fw-bold text-center"></h5>
443
+ <!-- Item Price -->
444
+ <p id="modal-price" class="text-muted text-center"></p>
445
+ <!-- Item Description -->
446
+ <p id="modal-description" class="text-secondary"></p>
447
+ <!-- Add-ons -->
448
+ <div id="modal-addons" class="modal-addons mt-4">
449
+ <h6>Customization Options</h6>
450
+ <div id="addons-list" class="addons-container">Loading customization options...</div>
451
  </div>
452
+ <div class="mt-4">
453
+ <h6>Custom Request</h6>
454
+ <textarea id="modal-instructions" class="form-control" placeholder="Enter any special instructions here..."></textarea>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
455
  </div>
456
+ <span id="modal-section" data-section="" data-category="" style="display: none;"></span>
457
+ </div>
458
+ <!-- Quantity Controls and Add to Cart Button -->
459
+ <div class="modal-footer d-flex align-items-center justify-content-between">
460
+ <!-- Quantity Controls -->
461
+ <div class="d-flex align-items-center gap-2">
462
+ <button type="button" class="btn btn-outline-secondary" id="decreaseQuantity">-</button>
463
+ <input type="text" class="form-control text-center" id="quantityInput" value="1" readonly style="width: 50px;"/>
464
+ <button type="button" class="btn btn-outline-secondary" id="increaseQuantity">+</button>
465
  </div>
466
+ <!-- Add to Cart Button -->
467
+ <button type="button" class="btn btn-primary" onclick="addToCartFromModal()">Add to Cart</button>
468
  </div>
469
  </div>
470
  </div>
471
+ </div>
472
 
473
+ <!-- JavaScript -->
474
+ <script>
475
+ // Show item details and fetch customization options
476
+ function showItemDetails(name, price, image, description, section, selectedCategory) {
477
+ document.getElementById('modal-name').innerText = name;
478
+ document.getElementById('modal-price').innerText = `$${price}`;
479
+ document.getElementById('modal-img').src = image || '/static/placeholder.jpg';
480
+ document.getElementById('modal-description').innerText = description || 'No description available.';
481
+ document.getElementById('addons-list').innerHTML = 'Loading customization options...';
482
+ document.getElementById('modal-instructions').value = '';
483
+ const modalSectionEl = document.getElementById('modal-section');
484
+ modalSectionEl.setAttribute('data-section', section);
485
+ modalSectionEl.setAttribute('data-category', selectedCategory);
486
+ // Set the default quantity to 1
487
+ document.getElementById('quantityInput').value = 1;
 
 
 
 
488
 
489
+ // Fetch customization options based on the section
490
+ fetch(`/api/addons?item_name=${encodeURIComponent(name)}&item_section=${encodeURIComponent(section)}`)
491
+ .then(response => response.json())
492
+ .then(data => {
493
+ const addonsList = document.getElementById('addons-list');
494
+ addonsList.innerHTML = ''; // Clear previous content
495
+ if (!data.success || !data.addons || data.addons.length === 0) {
496
+ addonsList.innerHTML = '<p>No customization options available.</p>';
497
+ return;
498
+ }
499
+
500
+ // Display customization options inside styled divs
501
+ data.addons.forEach(addon => {
502
+ const sectionDiv = document.createElement('div');
503
+ sectionDiv.classList.add('addon-section'); // Add styling class
504
+
505
+ // Add section title
506
+ const title = document.createElement('h6');
507
+ title.innerText = addon.name;
508
+ sectionDiv.appendChild(title);
509
+
510
+ // Create options list
511
+ const optionsContainer = document.createElement('div');
512
+ addon.options.forEach((option, index) => {
513
+ const optionId = `addon-${addon.name.replace(/\s+/g, '')}-${index}`;
514
+ const listItem = document.createElement('div');
515
+ listItem.classList.add('form-check');
516
+ listItem.innerHTML = `
517
+ <input type="checkbox" class="form-check-input addon-option" id="${optionId}" value="${option}"
518
+ data-name="${option}" data-group="${addon.name}" data-price="${addon.extra_charge ? addon.extra_charge_amount : 0}">
519
+ <label class="form-check-label" for="${optionId}">
520
+ ${option} ${addon.extra_charge ? `($${addon.extra_charge_amount})` : ''}
521
+ </label>
522
+ `;
523
+ optionsContainer.appendChild(listItem);
524
  });
525
+ sectionDiv.appendChild(optionsContainer);
526
+ addonsList.appendChild(sectionDiv);
 
 
527
  });
528
+ })
529
+ .catch(err => {
530
+ console.error('Error fetching add-ons:', err);
531
+ document.getElementById('addons-list').innerHTML = '<p>Error loading customization options.</p>';
532
+ });
533
+ }
534
+ // Handle single-select/deselect logic for checkbox groups in all modals
535
+ document.addEventListener('click', function(event) {
536
+ if (event.target.classList.contains('addon-option')) {
537
+ handleAddonClick(event.target);
538
  }
539
+ });
540
+ // Handle checkbox selection logic
541
+ function handleAddonClick(checkbox) {
542
+ const groupName = checkbox.getAttribute('data-group');
543
+ const isMultiSelectGroup = ["Extra Toppings", "Choose Raita/Sides","Select Dip/Sauce","Extra Add-ons","Make it a Combo"].includes(groupName);
544
+
545
+ // If it's not multi-select, uncheck all other checkboxes in the same group
546
+ if (!isMultiSelectGroup) {
547
+ const checkboxes = document.querySelectorAll(`.addon-option[data-group="${groupName}"]`);
548
+ checkboxes.forEach(otherCheckbox => {
549
+ if (otherCheckbox !== checkbox) {
550
+ otherCheckbox.checked = false;
551
+ }
552
+ });
553
+ }
554
+ }
555
  function filterMenu() {
556
  let input = document.getElementById('searchBar').value.toLowerCase(); // Get the value from search bar
557
  let sections = document.querySelectorAll('h3'); // Select section headers
 
584
  }
585
  });
586
  }
 
587
  function addToCartFromModal() {
588
  const itemName = document.getElementById('modal-name').innerText;
589
  let itemPrice = parseFloat(document.getElementById('modal-price').innerText.replace('$', ''));
 
590
  // Validate item price
591
  if (isNaN(itemPrice)) {
592
  alert('Invalid price for the item. Please check the item details.');
593
  return;
594
  }
 
595
  const itemImage = document.getElementById('modal-img').src;
596
  console.log(itemName, itemPrice, itemImage); // Log values for debugging
597
  const modalSectionEl = document.getElementById('modal-section');
598
  const section = modalSectionEl.getAttribute('data-section');
599
  const selectedCategory = modalSectionEl.getAttribute('data-category');
600
+ if (!itemName || !itemPrice || !section || !itemImage) {
601
+ console.error('Missing data for cart item:', { itemName, itemPrice, section, itemImage});
602
  return;
603
  }
604
 
 
606
  let selectedAddOns = Array.from(
607
  document.querySelectorAll('#addons-list input[type="checkbox"]:checked')
608
  ).map(addon => ({
609
+ name: addon.getAttribute('data-name') || 'Default Name', // Fallback Name
610
  price: parseFloat(addon.getAttribute('data-price') || 0)
611
  }));
612
+ // Get the selected quantity
613
+ const quantity = parseInt(document.getElementById('quantityInput').value) || 1; // Default to 1 if invalid
614
  const instructions = document.getElementById('modal-instructions').value;
 
615
  // Prepare data for the cart
616
  const cartPayload = {
617
  itemName: itemName,
 
620
  section: section,
621
  category: selectedCategory,
622
  addons: selectedAddOns,
623
+ instructions: instructions,
624
+ quantity: quantity // Include the quantity
625
  };
 
626
  // Send the cart data to the server
627
  fetch('/cart/add', {
628
  method: 'POST',
 
656
  const cartIcon = document.getElementById('cart-icon');
657
  cartIcon.innerText = cart.length; // Assuming cart is an array of items
658
  }
 
659
  function updateCartDisplay(cart) {
660
  if (!Array.isArray(cart)) {
661
  console.error('Invalid cart data:', cart);
662
  return;
663
  }
664
+ // Optional: Update quantity on the cart page
665
  const cartCountElement = document.getElementById('cart-count');
666
+ cartCountElement.innerText = cart.reduce((total, item)=> total+item.quantity,0); // Update cart item count //Sum of all quantities
667
+
668
  // Optionally, show a small success notification that the item was added
669
  const successNotification = document.createElement('div');
670
  successNotification.classList.add('success-notification');
 
674
  successNotification.remove(); // Remove success notification after a few seconds
675
  }, 2000);
676
  }
677
+
678
+ document.addEventListener('DOMContentLoaded', function () {
679
+ // Get references to the quantity buttons and the input field
680
+ const decreaseBtn = document.getElementById('decreaseQuantity');
681
+ const increaseBtn = document.getElementById('increaseQuantity');
682
+ const quantityInput = document.getElementById('quantityInput');
683
+ // Add event listener to decrease button
684
+ decreaseBtn.addEventListener('click', function () {
685
+ let currentQuantity = parseInt(quantityInput.value);
686
+ if (currentQuantity > 1) {
687
+ currentQuantity--;
688
+ quantityInput.value = currentQuantity;
689
+ }
690
+ });
691
+ // Add event listener to increase button
692
+ increaseBtn.addEventListener('click', function () {
693
+ let currentQuantity = parseInt(quantityInput.value);
694
+ currentQuantity++;
695
+ quantityInput.value = currentQuantity;
696
+ });
697
+ });
698
  // Function to round reward points to a single digit
699
  function roundRewardPoints() {
700
  // Get the reward points element
701
  let rewardPointsElement = document.getElementById('reward-points');
 
702
  // Check if the element exists in the DOM
703
  if (rewardPointsElement) {
704
  let rewardPointsText = rewardPointsElement.innerText.trim(); // Get and trim the value to remove any extra spaces
 
705
  // Check if the innerText is a valid number
706
  let rewardPoints = parseFloat(rewardPointsText);
 
707
  // If it's a valid number, round it to 1 decimal place
708
  if (!isNaN(rewardPoints)) {
709
  rewardPointsElement.innerText = rewardPoints.toFixed(1); // Round to 1 decimal place
 
722
  <!-- Bootstrap JS -->
723
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
724
  </body>
 
 
 
725
  </html>