DSatishchandra commited on
Commit
346957f
·
verified ·
1 Parent(s): c796d18

Update templates/menu.html

Browse files
Files changed (1) hide show
  1. templates/menu.html +559 -288
templates/menu.html CHANGED
@@ -9,162 +9,199 @@
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;
15
- padding: 0;
16
- display: flex;
17
- flex-direction: column;
18
- }
19
- .container {
20
- max-width: 900px;
21
- }
22
- .menu-card {
23
- max-width: 350px;
24
- border-radius: 15px;
25
- overflow: hidden;
26
- background-color: #fff;
27
- margin: auto;
28
- }
29
- .menu-image {
30
- height: 200px;
31
- width: 100%;
32
- object-fit: cover;
33
- border-radius: 15px 15px 0 0;
34
- }
35
- .card-title {
36
- font-size: 1.2rem;
37
- font-weight: bold;
38
- }
39
- .card-text {
40
- font-size: 1rem;
41
- color: #6c757d;
42
- }
43
- .btn-primary {
44
- font-size: 14px;
45
- font-weight: bold;
46
- border-radius: 5px;
47
- width: 100px;
48
- background-color: #0FAA39; /* Updated button background color */
49
- border-color: #28a745;
50
-
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;
71
- padding: 10px 20px;
72
- border-radius: 30px;
73
- font-size: 1rem;
74
- font-weight: bold;
75
- text-decoration: none;
76
- box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
77
- display: flex;
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;
91
- border-radius: 50%;
92
- background-color: #5bbfc1;
93
- cursor: pointer;
94
- display: flex;
95
- align-items: center;
96
- justify-content: center;
97
- color: white;
98
- font-size: 20px;
99
- font-weight: bold;
100
- }
101
- .dropdown-menu {
102
- position: absolute;
103
- right: 0;
104
- top: 100%;
105
- background-color: #fff;
106
- border-radius: 5px;
107
- width: 200px; /* Adjust width as needed */
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;
117
- color: #333;
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 */
130
- left: 50%;
131
- transform: translateX(-50%);
132
- width: 80%;
133
- max-width: 600px;
134
- z-index: 999; /* Keep it above content */
135
- background-color: white;
136
- padding: 10px;
137
- border-radius: 25px;
138
- box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2);
139
- }
140
- .container {
141
- margin-top: 180px; /* Adjust spacing based on navbar and search bar */
142
- }
143
- .fixed-top-bar {
144
  position: fixed;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  top: 0;
146
  left: 0;
147
  width: 100%;
148
- height: 54px; /* Adjust the height as needed */
149
- z-index: 1000;
150
  background-color: #FF6B35;
151
  color: white;
152
  padding: 15px;
153
  display: flex;
154
  justify-content: space-between;
155
  align-items: center; /* Vertically align items */
156
- z-index: 10000; /* Make sure it's at the top */
157
  }
 
 
158
  .avatar-dropdown-container {
159
  position: absolute;
160
  right: 20px; /* Adjust the value as needed to position it properly */
161
  top: 50%; /* Adjust top to place it within the header */
162
  transform: translateY(-50%); /* Correct the alignment to be perfectly centered */
163
  display: flex;
164
- align-items: center;
165
  justify-content: center;
166
  }
 
167
  .search-bar-container {
 
168
  position: absolute;
169
  left: 20px;
170
  top: 50%;
@@ -174,94 +211,165 @@
174
  align-items: center;
175
  width: 300px; /* Adjust width as needed */
176
  }
 
177
  .search-bar-container input {
178
- width: 100%;
179
  padding: 8px 10px 8px 30px; /* Add padding for the icon */
180
  font-size: 16px;
181
- border-radius: 20px;
182
  border: none;
183
  }
 
184
  .search-icon {
185
  position: absolute;
186
  left: 10px; /* Position the icon inside the input box */
187
  font-size: 20px;
188
  color: #888; /* Icon color */
189
  }
190
- /* Style for customization sections */
191
- .addon-section {
192
- background-color: #f8f9fa; /* Light gray background */
193
- border: 2px solid #ff6b35; /* Border color */
194
- border-radius: 8px;
195
- padding: 12px;
196
- margin-bottom: 15px; /* Spacing between sections */
197
- }
198
- /* Customization section title */
199
- .addon-section h6 {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
  margin-bottom: 10px;
201
- font-size: 1.1rem;
202
- font-weight: bold;
203
- color: #333;
204
  }
205
- /* Style for add-on checkboxes */
206
- .addon-section .form-check {
207
- margin-left: 10px;
208
- }
209
- /* Category Filter with Custom Radio Buttons */
210
- form.text-center.mb-4 {
211
  display: flex;
212
- flex-direction: column;
213
  align-items: center;
 
 
 
 
214
  }
215
- .form-check {
216
- display: inline-block;
217
- margin-right: 15px;
218
- margin-bottom: 10px; /* Add space between buttons */
219
- }
220
- .form-check-inline {
221
- margin-right: 10px;
222
  }
223
- .form-check-label {
 
 
 
 
224
  font-size: 16px;
225
- margin-left: 8px; /* Space between radio button and label */
226
  }
227
- .custom-radio {
228
- appearance: none;
229
- -webkit-appearance: none;
230
- -moz-appearance: none;
231
- width: 18px;
232
- height: 18px;
233
- border: 2px solid #333;
234
- border-radius: 50%;
235
- margin-right: 10px; /* Increased spacing between button and label */
236
- outline: none;
237
  cursor: pointer;
238
- position: relative;
239
- }
240
- .custom-radio:checked {
241
- background-color: #007bff;
242
- border-color: #007bff;
243
- }
244
- .custom-radio:checked::after {
245
- content: '';
246
- position: absolute;
247
- top: 4px;
248
- left: 4px;
249
- width: 8px;
250
- height: 8px;
251
- background-color: #fff;
252
- border-radius: 50%;
253
- }
254
- .custom-radio:hover {
255
- border-color: #007bff;
256
- }
257
- /* Optional: Style the labels */
258
- .form-check-label {
259
  font-size: 16px;
260
- margin-left: 8px; /* Space between the radio button and the label */
 
 
 
261
  }
262
  </style>
263
  </head>
264
  <body>
 
265
  <div class="fixed-top-bar">
266
  <!-- Avatar and Dropdown -->
267
  <div class="avatar-dropdown-container">
@@ -297,7 +405,6 @@
297
  </div>
298
  </form>
299
 
300
-
301
  <!-- Show menu items only when Customized Dish is not selected -->
302
  <div class="container mt-4">
303
  <h1 class="text-center">Menu</h1>
@@ -353,7 +460,9 @@
353
  </a>
354
  </div>
355
 
356
- <!-- Modal for Item Details -->
 
 
357
  <div class="modal fade" id="itemModal" tabindex="-1" aria-labelledby="itemModalLabel" aria-hidden="true">
358
  <div class="modal-dialog modal-dialog-centered">
359
  <div class="modal-content">
@@ -385,8 +494,16 @@
385
 
386
  </div>
387
  <div class="modal-footer">
388
- <button type="button" class="btn btn-primary" onclick="addToCartFromModal()">Add to Cart</button>
389
- <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
 
 
 
 
 
 
 
 
390
  </div>
391
  </div>
392
  </div>
@@ -394,6 +511,29 @@
394
 
395
  <!-- JavaScript -->
396
  <script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
397
  function showItemDetails(name, price, image, description, section, selectedCategory) {
398
  document.getElementById('modal-name').innerText = name;
399
  document.getElementById('modal-price').innerText = `$${price}`;
@@ -407,100 +547,231 @@
407
  modalSectionEl.setAttribute('data-category', selectedCategory);
408
  // Fetch customization options based on the section
409
  fetch(`/api/addons?item_name=${encodeURIComponent(name)}&item_section=${encodeURIComponent(section)}`)
410
- .then(response => response.json())
411
- .then(data => {
412
- const addonsList = document.getElementById('addons-list');
413
- addonsList.innerHTML = ''; // Clear previous content
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
414
 
415
- if (!data.success || !data.addons || data.addons.length === 0) {
416
- addonsList.innerHTML = '<p>No customization options available.</p>';
417
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
418
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
419
 
420
- data.addons.forEach(addon => {
421
- const sectionDiv = document.createElement('div');
422
- sectionDiv.classList.add('addon-section');
423
- const title = document.createElement('h6');
424
- title.innerText = addon.name;
425
- sectionDiv.appendChild(title);
426
-
427
- const optionsContainer = document.createElement('div');
428
- addon.options.forEach((option, index) => {
429
- const optionId = `addon-${addon.name.replace(/\s+/g, '')}-${index}`;
430
- const listItem = document.createElement('div');
431
- listItem.classList.add('form-check');
432
- listItem.innerHTML = `
433
- <input type="checkbox" class="form-check-input addon-option" id="${optionId}" value="${option}"
434
- data-name="${option}" data-price="${addon.extra_charge ? addon.extra_charge_amount : 0}">
435
- <label class="form-check-label" for="${optionId}">
436
- ${option} ${addon.extra_charge ? `($${addon.extra_charge_amount})` : ''}
437
- </label>
438
- `;
439
- optionsContainer.appendChild(listItem);
440
- });
441
- sectionDiv.appendChild(optionsContainer);
442
- addonsList.appendChild(sectionDiv);
443
- });
 
 
 
 
 
 
 
444
  })
445
  .catch(err => {
446
- console.error('Error fetching add-ons:', err);
447
- document.getElementById('addons-list').innerHTML = '<p>Error loading customization options.</p>';
448
  });
449
-
450
- function addToCartFromModal() {
451
- const itemName = document.getElementById('modal-name').innerText;
452
- let itemPrice = parseFloat(document.getElementById('modal-price').innerText.replace('$', ''));
453
- if (isNaN(itemPrice)) {
454
- alert('Invalid price for the item. Please check the item details.');
455
- return;
456
- }
457
- const itemImage = document.getElementById('modal-img').src;
458
- const modalSectionEl = document.getElementById('modal-section');
459
- const section = modalSectionEl.getAttribute('data-section');
460
- const selectedCategory = modalSectionEl.getAttribute('data-category');
461
- let selectedAddOns = Array.from(
462
- document.querySelectorAll('#addons-list input[type="checkbox"]:checked')
463
- ).map(addon => ({
464
- name: addon.getAttribute('data-name') || 'Default Name',
465
- price: parseFloat(addon.getAttribute('data-price') || 0)
466
- }));
467
- const instructions = document.getElementById('modal-instructions').value;
468
- const cartPayload = {
469
- itemName: itemName,
470
- itemPrice: itemPrice,
471
- itemImage: itemImage,
472
- section: section,
473
- category: selectedCategory,
474
- addons: selectedAddOns,
475
- instructions: instructions
476
- };
477
- fetch('/cart/add', {
478
- method: 'POST',
479
- headers: { 'Content-Type': 'application/json' },
480
- body: JSON.stringify(cartPayload)
481
- })
482
- .then(response => response.json())
483
- .then(data => {
484
- if (data.success) {
485
- alert('Item added to cart successfully!');
486
- updateCartUI(data.cart);
487
- const modal = document.getElementById('itemModal');
488
- const modalInstance = bootstrap.Modal.getInstance(modal);
489
- modalInstance.hide();
490
- } else {
491
- alert(data.error || 'Failed to add item to cart.');
492
- }
493
- })
494
- .catch(err => {
495
- console.error('Error adding item to cart:', err);
496
- alert('An error occurred while adding the item to the cart.');
497
- });
498
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
499
 
500
- function updateCartUI(cart) {
501
- const cartIcon = document.getElementById('cart-icon');
502
- cartIcon.innerText = cart.length;
 
 
503
  }
 
 
 
 
 
 
 
504
  </script>
 
 
 
505
  </body>
506
  </html>
 
 
 
 
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;
15
+ padding: 0;
16
+ display: flex;
17
+ flex-direction: column;
18
+ }
19
+
20
+ .container {
21
+ max-width: 900px;
22
+ }
23
+
24
+ .menu-card {
25
+ max-width: 350px;
26
+ border-radius: 15px;
27
+ overflow: hidden;
28
+ background-color: #fff;
29
+ margin: auto;
30
+ }
31
+
32
+ .menu-image {
33
+ height: 200px;
34
+ width: 100%;
35
+ object-fit: cover;
36
+ border-radius: 15px 15px 0 0;
37
+ }
38
+
39
+ .card-title {
40
+ font-size: 1.2rem;
41
+ font-weight: bold;
42
+ }
43
+
44
+ .card-text {
45
+ font-size: 1rem;
46
+ color: #6c757d;
47
+ }
48
+
49
+ .btn-primary {
50
+ font-size: 14px;
51
+ font-weight: bold;
52
+ border-radius: 5px;
53
+ width: 100px;
54
+ background-color: #0FAA39; /* Updated button background color */
55
+ border-color: #28a745;
56
+ }
57
+
58
+ .btn-primary:hover {
59
+ background-color: #0FAA39;
60
+ border-color: #ffffff;
61
+ }
62
+
63
+ .btn-primary:active,
64
+ .btn-primary:focus {
65
+ background-color: #4a5d68;
66
+ border-color: #ffffff;
67
+ box-shadow: none;
68
+ }
69
+
70
+ .view-cart-container {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  position: fixed;
72
+ bottom: 20px;
73
+ right: 20px;
74
+ z-index: 999;
75
+ }
76
+
77
+ .view-cart-button {
78
+ background-color: #0FAA39; /* Updated View Cart button background color */
79
+ color: #fff;
80
+ padding: 10px 20px;
81
+ border-radius: 30px;
82
+ font-size: 1rem;
83
+ font-weight: bold;
84
+ text-decoration: none;
85
+ box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
86
+ display: flex;
87
+ align-items: center;
88
+ justify-content: center;
89
+ }
90
+
91
+ .view-cart-button:hover {
92
+ background-color: #109835; /* Slightly darker shade for hover effect */
93
+ text-decoration: none;
94
+ }
95
+
96
+ .avatar-dropdown-container {
97
+ position: relative;
98
+ }
99
+
100
+ .avatar-icon {
101
+ width: 40px;
102
+ height: 40px;
103
+ border-radius: 50%;
104
+ background-color: #5bbfc1;
105
+ cursor: pointer;
106
+ display: flex;
107
+ align-items: center;
108
+ justify-content: center;
109
+ color: white;
110
+ font-size: 20px;
111
+ font-weight: bold;
112
+ }
113
+
114
+ .dropdown-menu {
115
+ position: absolute;
116
+ right: 0;
117
+ top: 100%;
118
+ background-color: #fff;
119
+ border-radius: 5px;
120
+ width: 200px; /* Adjust width as needed */
121
+ box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
122
+ display: none;
123
+ }
124
+
125
+ .avatar-dropdown-container:hover .dropdown-menu {
126
+ display: block;
127
+ }
128
+
129
+ .dropdown-menu .dropdown-item {
130
+ padding: 10px 15px;
131
+ text-decoration: none;
132
+ color: #333;
133
+ border-bottom: 1px solid #ddd;
134
+ display: block; /* Make each item stack vertically */
135
+ }
136
+
137
+ .dropdown-menu .dropdown-item:last-child {
138
+ border-bottom: none; /* Remove the bottom border from the last item */
139
+ }
140
+
141
+ .dropdown-menu .dropdown-item:hover {
142
+ background-color: #f1f1f1;
143
+ }
144
+
145
+ .fixed-search-container {
146
+ position: absolute;
147
+ top: 90px; /* Move it slightly lower */
148
+ left: 50%;
149
+ transform: translateX(-50%);
150
+ width: 80%;
151
+ max-width: 600px;
152
+ z-index: 999; /* Keep it above content */
153
+ background-color: white;
154
+ padding: 10px;
155
+ border-radius: 25px;
156
+ box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2);
157
+ }
158
+
159
+ /* Ensure the category filter dropdown does not overlap */
160
+ form.text-center.mb-4 {
161
+ margin-top: 50px; /* No margin at the top */
162
+ margin-bottom: 10px; /* Small space at the bottom */
163
+ }
164
+
165
+ /* Ensure the container has enough margin so nothing is overlapped */
166
+ .container {
167
+ margin-top: 10px; /* Adjust spacing based on navbar and search bar */
168
+ padding-top: 0 !important; /* Ensure no padding is added by default */
169
+ }
170
+
171
+ h1.text-center {
172
+ margin-top: 10px; /* Reduced space above */
173
+ padding-top: 0 !important; /* Removed padding */
174
+ }
175
+
176
+ .fixed-top-bar {
177
+ /* Remove the fixed positioning */
178
+ position: relative; /* Change from fixed to relative */
179
  top: 0;
180
  left: 0;
181
  width: 100%;
182
+ height: 54px;
 
183
  background-color: #FF6B35;
184
  color: white;
185
  padding: 15px;
186
  display: flex;
187
  justify-content: space-between;
188
  align-items: center; /* Vertically align items */
189
+ z-index: 1000; /* Make sure it's still above other content */
190
  }
191
+
192
+
193
  .avatar-dropdown-container {
194
  position: absolute;
195
  right: 20px; /* Adjust the value as needed to position it properly */
196
  top: 50%; /* Adjust top to place it within the header */
197
  transform: translateY(-50%); /* Correct the alignment to be perfectly centered */
198
  display: flex;
199
+ align-items: right;
200
  justify-content: center;
201
  }
202
+
203
  .search-bar-container {
204
+ padding: 10px;
205
  position: absolute;
206
  left: 20px;
207
  top: 50%;
 
211
  align-items: center;
212
  width: 300px; /* Adjust width as needed */
213
  }
214
+
215
  .search-bar-container input {
216
+ width: 85%;
217
  padding: 8px 10px 8px 30px; /* Add padding for the icon */
218
  font-size: 16px;
219
+ border-radius: 10px;
220
  border: none;
221
  }
222
+
223
  .search-icon {
224
  position: absolute;
225
  left: 10px; /* Position the icon inside the input box */
226
  font-size: 20px;
227
  color: #888; /* Icon color */
228
  }
229
+
230
+ /* Style for customization sections */
231
+ .addon-section {
232
+ background-color: #f8f9fa; /* Light gray background */
233
+ border: 2px solid #ff6b35; /* Border color */
234
+ border-radius: 8px;
235
+ padding: 12px;
236
+ margin-bottom: 15px; /* Spacing between sections */
237
+ }
238
+
239
+ /* Customization section title */
240
+ .addon-section h6 {
241
+ margin-bottom: 10px;
242
+ font-size: 1.1rem;
243
+ font-weight: bold;
244
+ color: #333;
245
+ }
246
+
247
+ /* Style for add-on checkboxes */
248
+ .addon-section .form-check {
249
+ margin-left: 10px;
250
+ }
251
+
252
+ /* Category Filter with Custom Radio Buttons */
253
+ form.text-center.mb-4 {
254
+ display: flex;
255
+ flex-direction: column;
256
+ align-items: center;
257
+ justify-content: center;
258
+ }
259
+
260
+ .form-check {
261
+ display: inline-block;
262
+ margin-right: 5px; /* Reduced space between radio button and label */
263
+ margin-bottom: 0; /* Remove bottom margin */
264
+ vertical-align: middle; /* Align radio buttons vertically */
265
+ }
266
+
267
+ .form-check-inline {
268
+ display: inline-block;
269
+ margin-right: 5px; !important; /* Decrease space between each radio button */
270
+ }
271
+
272
+ .form-check-label {
273
+ font-size: 16px;
274
+ margin-left: 8px; /* Spacing between radio button and label */
275
+ vertical-align: middle; /* Align label vertically */
276
+ }
277
+
278
+ .custom-radio {
279
+ appearance: none;
280
+ -webkit-appearance: none;
281
+ -moz-appearance: none;
282
+ width: 20px;
283
+ height: 20px;
284
+ border: 3px solid #4CAF50; /* Green border */
285
+ border-radius: 50%;
286
+ margin-right: 5px; /* Reduced spacing between button and label */
287
+ outline: none;
288
+ cursor: pointer;
289
+ position: relative;
290
+ display: inline-block;
291
+ }
292
+
293
+ .custom-radio:checked {
294
+ background-color: #4CAF50; /* Green color when checked */
295
+ border-color: #4CAF50; /* Matching border color */
296
+ }
297
+
298
+ .custom-radio:checked::after {
299
+ content: '';
300
+ position: absolute;
301
+ top: 5px;
302
+ left: 5px;
303
+ border-radius: 50%;
304
+ }
305
+
306
+ .custom-radio:hover {
307
+ border-color: #388E3C;
308
+ }
309
+
310
+ /* Optional: Style the labels */
311
+ .form-check-label {
312
+ font-size: 16px;
313
+ margin-left: 8px; /* Space between the radio button and the label */
314
+ }
315
+ .modal-footer .d-flex {
316
+ justify-content: flex-start; /* Align content to the left */
317
+ width: 100%; /* Make sure the container spans the full width */
318
+ padding-left: 0; /* Remove padding if any */
319
+ }
320
+
321
+ .modal-footer .form-control {
322
+ margin-right: 10px; /* Add a little space between the quantity input and the buttons */
323
+ }
324
+ .cart-container {
325
+ display: flex;
326
+ align-items: center;
327
+ gap: 10px;
328
  margin-bottom: 10px;
 
 
 
329
  }
330
+
331
+ .quantity-box {
 
 
 
 
332
  display: flex;
 
333
  align-items: center;
334
+ border: 1px solid #ccc;
335
+ border-radius: 5px;
336
+ overflow: hidden;
337
+ height: 40px;
338
  }
339
+
340
+ .quantity-box button {
341
+ background: #f0f0f0;
342
+ border: none;
343
+ padding: 5px 10px;
344
+ cursor: pointer;
345
+ height: 100%;
346
  }
347
+
348
+ .quantity-box input {
349
+ width: 40px;
350
+ text-align: center;
351
+ border: none;
352
  font-size: 16px;
353
+ height: 100%;
354
  }
355
+
356
+ .add-to-cart-btn {
357
+ background: green;
358
+ color: white;
359
+ padding: 10px 15px;
360
+ border: none;
361
+ border-radius: 5px;
 
 
 
362
  cursor: pointer;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
363
  font-size: 16px;
364
+ height: 40px;
365
+ display: flex;
366
+ align-items: center;
367
+ justify-content: center;
368
  }
369
  </style>
370
  </head>
371
  <body>
372
+
373
  <div class="fixed-top-bar">
374
  <!-- Avatar and Dropdown -->
375
  <div class="avatar-dropdown-container">
 
405
  </div>
406
  </form>
407
 
 
408
  <!-- Show menu items only when Customized Dish is not selected -->
409
  <div class="container mt-4">
410
  <h1 class="text-center">Menu</h1>
 
460
  </a>
461
  </div>
462
 
463
+
464
+
465
+ <!-- Modal for Item Details -->
466
  <div class="modal fade" id="itemModal" tabindex="-1" aria-labelledby="itemModalLabel" aria-hidden="true">
467
  <div class="modal-dialog modal-dialog-centered">
468
  <div class="modal-content">
 
494
 
495
  </div>
496
  <div class="modal-footer">
497
+ <div class="d-flex align-items-center">
498
+ <button type="button" class="btn btn-outline-secondary" id="decreaseQuantity">-</button>
499
+ <input type="text" class="form-control text-center" id="quantityInput" value="1" readonly style="width: 50px;"/>
500
+ <button type="button" class="btn btn-outline-secondary" id="increaseQuantity">+</button>
501
+ </div>
502
+
503
+ <div>
504
+ <button class="add-to-cart-btn" onclick="addToCartFromModal()">Add items to Cart $<span id="totalAmountDisplay">0.00</span></button>
505
+ </div>
506
+
507
  </div>
508
  </div>
509
  </div>
 
511
 
512
  <!-- JavaScript -->
513
  <script>
514
+ function changeQuantity(amount, itemId) {
515
+ let quantityInput = document.getElementById("quantity-" + itemId);
516
+ let currentQuantity = parseInt(quantityInput.value);
517
+ let newQuantity = currentQuantity + amount;
518
+
519
+ if (newQuantity >= 1) {
520
+ quantityInput.value = newQuantity;
521
+ updateTotalAmount(itemId);
522
+ }
523
+ }
524
+
525
+ function updateTotalAmount(itemId) {
526
+ let quantity = parseInt(document.getElementById("quantity-" + itemId).value);
527
+ let price = parseFloat(document.getElementById("price-" + itemId).innerText); // Get price dynamically
528
+ let totalAmount = price * quantity;
529
+ document.getElementById("totalAmountDisplay-" + itemId).innerText = totalAmount.toFixed(2);
530
+ }
531
+
532
+ function addToCartFromModal(itemId) {
533
+ let quantity = document.getElementById("quantity-" + itemId).value;
534
+ let itemName = document.getElementById("name-" + itemId).innerText; // Get item name dynamically
535
+ alert(`Added ${quantity} x ${itemName} to cart!`);
536
+ }
537
  function showItemDetails(name, price, image, description, section, selectedCategory) {
538
  document.getElementById('modal-name').innerText = name;
539
  document.getElementById('modal-price').innerText = `$${price}`;
 
547
  modalSectionEl.setAttribute('data-category', selectedCategory);
548
  // Fetch customization options based on the section
549
  fetch(`/api/addons?item_name=${encodeURIComponent(name)}&item_section=${encodeURIComponent(section)}`)
550
+ .then(response => response.json())
551
+ .then(data => {
552
+ const addonsList = document.getElementById('addons-list');
553
+ addonsList.innerHTML = ''; // Clear previous content
554
+
555
+ if (!data.success || !data.addons || data.addons.length === 0) {
556
+ addonsList.innerHTML = '<p>No customization options available.</p>';
557
+ return;
558
+ }
559
+ // Display customization options inside styled divs
560
+ data.addons.forEach(addon => {
561
+ const sectionDiv = document.createElement('div');
562
+ sectionDiv.classList.add('addon-section'); // Add styling class
563
+ // Add section title
564
+ const title = document.createElement('h6');
565
+ title.innerText = addon.name;
566
+ sectionDiv.appendChild(title);
567
+ // Create options list
568
+ const optionsContainer = document.createElement('div');
569
+ addon.options.forEach((option, index) => {
570
+ const optionId = `addon-${addon.name.replace(/\s+/g, '')}-${index}`;
571
+ const listItem = document.createElement('div');
572
+ listItem.classList.add('form-check');
573
+ listItem.innerHTML = `
574
+ <input type="checkbox" class="form-check-input addon-option" id="${optionId}" value="${option}"
575
+ data-name="${option}" data-price="${addon.extra_charge ? addon.extra_charge_amount : 0}">
576
+ <label class="form-check-label" for="${optionId}">
577
+ ${option} ${addon.extra_charge ? `($${addon.extra_charge_amount})` : ''}
578
+ </label>
579
+ `;
580
+ optionsContainer.appendChild(listItem);
581
+ });
582
+ sectionDiv.appendChild(optionsContainer);
583
+ addonsList.appendChild(sectionDiv);
584
+ });
585
+ })
586
+ .catch(err => {
587
+ console.error('Error fetching add-ons:', err);
588
+ document.getElementById('addons-list').innerHTML = '<p>Error loading customization options.</p>';
589
+ });
590
+ }
591
 
592
+ function filterMenu() {
593
+ let input = document.getElementById('searchBar').value.toLowerCase(); // Get the value from search bar
594
+ let sections = document.querySelectorAll('h3'); // Select section headers
595
+ let items = document.querySelectorAll('.menu-card'); // Select all items
596
+ let matchedSections = new Set(); // Store matched sections
597
+
598
+ // Hide all items initially
599
+ items.forEach(item => {
600
+ let itemName = item.querySelector('.card-title').innerText.toLowerCase(); // Get item name
601
+ let itemSection = item.closest('.row').previousElementSibling.innerText.toLowerCase(); // Get section name
602
+
603
+ // If the search matches item name or section, show the item
604
+ if (itemName.includes(input) || (itemSection && itemSection.includes(input))) {
605
+ item.style.display = 'block'; // Show item if it matches search
606
+ matchedSections.add(item.closest('.row')); // Add section to matched list
607
+ } else {
608
+ item.style.display = 'none'; // Hide item if not matched
609
  }
610
+ });
611
+
612
+ // Show or hide sections based on matched items
613
+ sections.forEach(section => {
614
+ let sectionRow = section.nextElementSibling; // The row containing items
615
+ if (matchedSections.has(sectionRow)) {
616
+ section.style.display = 'block'; // Show section header
617
+ sectionRow.style.display = 'flex'; // Show section items
618
+ } else {
619
+ section.style.display = 'none'; // Hide section header
620
+ sectionRow.style.display = 'none'; // Hide section items
621
+ }
622
+ });
623
+ }
624
+
625
+ function addToCartFromModal() {
626
+ const itemName = document.getElementById('modal-name').innerText;
627
+ let itemPrice = parseFloat(document.getElementById('modal-price').innerText.replace('$', ''));
628
+
629
+ // Validate item price
630
+ if (isNaN(itemPrice)) {
631
+ alert('Invalid price for the item. Please check the item details.');
632
+ return;
633
+ }
634
+
635
+ const itemImage = document.getElementById('modal-img').src;
636
+ console.log(itemName, itemPrice, itemImage); // Log values for debugging
637
+ const modalSectionEl = document.getElementById('modal-section');
638
+ const section = modalSectionEl.getAttribute('data-section');
639
+ const selectedCategory = modalSectionEl.getAttribute('data-category');
640
+ if (!itemName || !itemPrice || !section) {
641
+ console.error('Missing data for cart item:', { itemName, itemPrice, section });
642
+ return;
643
+ }
644
+
645
+ // Collect selected add-ons
646
+ let selectedAddOns = Array.from(
647
+ document.querySelectorAll('#addons-list input[type="checkbox"]:checked')
648
+ ).map(addon => ({
649
+ name: addon.getAttribute('data-name') || 'Default Name', // Fallback Name
650
+ price: parseFloat(addon.getAttribute('data-price') || 0)
651
+ }));
652
+
653
+ // Get the selected quantity
654
+ const quantity = parseInt(document.getElementById('quantityInput').value) || 1; // Default to 1 if invalid
655
+
656
+ const instructions = document.getElementById('modal-instructions').value;
657
 
658
+ // Prepare data for the cart
659
+ const cartPayload = {
660
+ itemName: itemName,
661
+ itemPrice: itemPrice,
662
+ itemImage: itemImage,
663
+ section: section,
664
+ category: selectedCategory,
665
+ addons: selectedAddOns,
666
+ instructions: instructions,
667
+ quantity: quantity // Include the quantity
668
+ };
669
+
670
+ // Send the cart data to the server
671
+ fetch('/cart/add', {
672
+ method: 'POST',
673
+ headers: {
674
+ 'Content-Type': 'application/json',
675
+ },
676
+ body: JSON.stringify(cartPayload)
677
+ })
678
+ .then(response => response.json())
679
+ .then(data => {
680
+ if (data.success) {
681
+ alert('Item added to cart successfully!');
682
+ updateCartUI(data.cart); // Update cart UI after adding an item
683
+ const modal = document.getElementById('itemModal');
684
+ const modalInstance = bootstrap.Modal.getInstance(modal);
685
+ modalInstance.hide();
686
+ } else {
687
+ alert(data.error || 'Failed to add item to cart.');
688
+ }
689
  })
690
  .catch(err => {
691
+ console.error('Error adding item to cart:', err);
692
+ alert('An error occurred while adding the item to the cart.');
693
  });
694
+ }
695
+
696
+ function updateCartUI(cart) {
697
+ if (!Array.isArray(cart)) {
698
+ console.error('Invalid cart data:', cart);
699
+ return;
700
+ }
701
+ const cartIcon = document.getElementById('cart-icon');
702
+ cartIcon.innerText = cart.length; // Assuming cart is an array of items
703
+ }
704
+
705
+ function updateCartDisplay(cart) {
706
+ if (!Array.isArray(cart)) {
707
+ console.error('Invalid cart data:', cart);
708
+ return;
709
+ }
710
+ const cartCountElement = document.getElementById('cart-count');
711
+ cartCountElement.innerText = cart.length; // Update cart item count
712
+ // Optionally, show a small success notification that the item was added
713
+ const successNotification = document.createElement('div');
714
+ successNotification.classList.add('success-notification');
715
+ successNotification.innerText = 'Item added to cart!';
716
+ document.body.appendChild(successNotification);
717
+ setTimeout(() => {
718
+ successNotification.remove(); // Remove success notification after a few seconds
719
+ }, 2000);
720
+ }
721
+ document.addEventListener('DOMContentLoaded', function () {
722
+ // Get references to the quantity buttons and the input field
723
+ const decreaseBtn = document.getElementById('decreaseQuantity');
724
+ const increaseBtn = document.getElementById('increaseQuantity');
725
+ const quantityInput = document.getElementById('quantityInput');
726
+
727
+ // Add event listener to decrease button
728
+ decreaseBtn.addEventListener('click', function () {
729
+ let currentQuantity = parseInt(quantityInput.value);
730
+ if (currentQuantity > 1) {
731
+ currentQuantity--;
732
+ quantityInput.value = currentQuantity;
 
 
 
 
 
 
 
 
 
 
733
  }
734
+ });
735
+
736
+ // Add event listener to increase button
737
+ increaseBtn.addEventListener('click', function () {
738
+ let currentQuantity = parseInt(quantityInput.value);
739
+ currentQuantity++;
740
+ quantityInput.value = currentQuantity;
741
+ });
742
+ });
743
+
744
+ // Function to round reward points to a single digit
745
+ function roundRewardPoints() {
746
+ // Get the reward points element
747
+ let rewardPointsElement = document.getElementById('reward-points');
748
+
749
+ // Check if the element exists in the DOM
750
+ if (rewardPointsElement) {
751
+ let rewardPointsText = rewardPointsElement.innerText.trim(); // Get and trim the value to remove any extra spaces
752
+
753
+ // Check if the innerText is a valid number
754
+ let rewardPoints = parseFloat(rewardPointsText);
755
 
756
+ // If it's a valid number, round it to 1 decimal place
757
+ if (!isNaN(rewardPoints)) {
758
+ rewardPointsElement.innerText = rewardPoints.toFixed(1); // Round to 1 decimal place
759
+ } else {
760
+ console.error("Reward points value is not a valid number:", rewardPointsText);
761
  }
762
+ } else {
763
+ console.error("Reward points element is missing.");
764
+ }
765
+ }
766
+ // Run the function when the page loads
767
+ window.onload = roundRewardPoints;
768
+
769
  </script>
770
+
771
+ <!-- Bootstrap JS -->
772
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
773
  </body>
774
  </html>
775
+ </script>
776
+ </body>
777
+ </html>