DSatishchandra commited on
Commit
c6c5fff
·
verified ·
1 Parent(s): 793139a

Update templates/menu.html

Browse files
Files changed (1) hide show
  1. templates/menu.html +126 -361
templates/menu.html CHANGED
@@ -10,7 +10,7 @@
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;
@@ -45,9 +45,8 @@
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;
@@ -66,7 +65,7 @@
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;
@@ -79,7 +78,7 @@
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 {
@@ -104,7 +103,7 @@
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
  }
@@ -116,148 +115,60 @@
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
- /* Ensure the category filter dropdown does not overlap */
141
- form.text-center.mb-4 {
142
- margin-top: 120px !important; /* Increase spacing below search bar */
143
- }
144
- /* Ensure the container has enough margin so nothing is overlapped */
145
  .container {
146
- margin-top: 180px; /* Adjust spacing based on navbar and search bar */
147
  }
148
- .fixed-top-bar {
149
- position: fixed;
150
- top: 0;
151
- left: 0;
152
- width: 100%;
153
- height: 54px; /* Adjust the height as needed */
154
- z-index: 1000;
155
- background-color: #FF6B35;
156
- color: white;
157
- padding: 15px;
158
- display: flex;
159
- justify-content: space-between;
160
- align-items: center; /* Vertically align items */
161
- z-index: 10000; /* Make sure it's at the top */
162
- }
163
-
164
- .avatar-dropdown-container {
165
- position: absolute;
166
- right: 20px; /* Adjust the value as needed to position it properly */
167
- top: 50%; /* Adjust top to place it within the header */
168
- transform: translateY(-50%); /* Correct the alignment to be perfectly centered */
169
- display: flex;
170
- align-items: center;
171
- justify-content: center;
172
- }
173
-
174
- .search-bar-container {
175
- position: absolute;
176
- left: 20px;
177
- top: 50%;
178
- transform: translateY(-50%);
179
- display: flex;
180
- justify-content: flex-start;
181
- align-items: center;
182
- width: 300px; /* Adjust width as needed */
183
- }
184
-
185
- .search-bar-container input {
186
- width: 100%;
187
- padding: 8px 10px 8px 30px; /* Add padding for the icon */
188
- font-size: 16px;
189
- border-radius: 20px;
190
- border: none;
191
- }
192
-
193
- .search-icon {
194
- position: absolute;
195
- left: 10px; /* Position the icon inside the input box */
196
- font-size: 20px;
197
- color: #888; /* Icon color */
198
- }
199
-
200
- /* Style for customization sections */
201
  .addon-section {
202
- background-color: #f8f9fa; /* Light gray background */
203
- border: 2px solid #ff6b35; /* Border color */
204
  border-radius: 8px;
205
  padding: 12px;
206
- margin-bottom: 15px; /* Spacing between sections */
207
  }
208
- /* Customization section title */
209
  .addon-section h6 {
210
  margin-bottom: 10px;
211
  font-size: 1.1rem;
212
  font-weight: bold;
213
  color: #333;
214
  }
215
- /* Style for add-on checkboxes */
216
- .addon-section .form-check {
217
- margin-left: 10px;
218
- }
219
-
220
- /* Category Filter with Custom Radio Buttons */
221
- form.text-center.mb-4 {
222
- display: flex;
223
- flex-direction: column;
224
- align-items: center;
225
- }
226
-
227
- .form-check {
228
- display: inline-block;
229
- margin-right: 15px;
230
- margin-bottom: 10px; /* Add space between buttons */
231
- }
232
-
233
- .form-check-inline {
234
- margin-right: 10px;
235
- }
236
-
237
  .form-check-label {
238
  font-size: 16px;
239
- margin-left: 8px; /* Space between radio button and label */
240
  }
241
-
242
  .custom-radio {
243
- appearance: none;
244
- -webkit-appearance: none;
245
- -moz-appearance: none;
246
  width: 18px;
247
  height: 18px;
248
  border: 2px solid #333;
249
  border-radius: 50%;
250
- margin-right: 10px; /* Increased spacing between button and label */
251
  outline: none;
252
  cursor: pointer;
253
- position: relative;
254
  }
255
-
256
  .custom-radio:checked {
257
  background-color: #007bff;
258
  border-color: #007bff;
259
  }
260
-
261
  .custom-radio:checked::after {
262
  content: '';
263
  position: absolute;
@@ -268,114 +179,82 @@
268
  background-color: #fff;
269
  border-radius: 50%;
270
  }
271
-
272
- .custom-radio:hover {
273
- border-color: #007bff;
274
- }
275
-
276
- /* Optional: Style the labels */
277
- .form-check-label {
278
- font-size: 16px;
279
- margin-left: 8px; /* Space between the radio button and the label */
280
  }
281
- </style>
282
  </head>
283
  <body>
284
-
285
- <div class="fixed-top-bar">
286
- <!-- Avatar and Dropdown -->
287
- <div class="avatar-dropdown-container">
288
- <div class="avatar-icon">
289
- <span>{{ first_letter }}</span> <!-- Display the first letter of the customer's name -->
290
- </div>
291
- <div class="dropdown-menu">
292
- <a href="{{ url_for('customer_details') }}" class="dropdown-item">View Profile</a>
293
- <a href="{{ url_for('order_history') }}" class="dropdown-item">Order History</a>
294
- <a href="{{ url_for('logout') }}" class="dropdown-item">Logout</a>
295
  </div>
296
  </div>
297
 
298
- <!-- Search Bar Section -->
299
- <div class="search-bar-container">
300
- <input type="text" id="searchBar" class="form-control" placeholder="Search items or sections..." onkeyup="filterMenu()">
301
- <i class="bi bi-search search-icon"></i> <!-- Search icon inside the input -->
302
- </div>
303
- </div>
304
-
305
- <!-- Category Filter with Custom Radio Buttons -->
306
- <form method="get" action="/menu" class="text-center mb-4">
307
- <label class="form-label fw-bold">Select a Category:</label>
308
- <div class="form-check form-check-inline">
309
- {% for category in categories %}
310
- <input type="radio" id="category-{{ category }}" name="category" value="{{ category }}" class="custom-radio"
311
- {% if selected_category == category %}checked{% endif %} onchange="this.form.submit()">
312
- <label class="form-check-label" for="category-{{ category }}">{{ category }}</label>
313
- {% endfor %}
314
- <input type="radio" id="category-CustomizedDish" name="category" value="Customized Dish" class="custom-radio"
315
- {% if selected_category == "Customized Dish" %}checked{% endif %} onchange="this.form.submit()">
316
- <label class="form-check-label" for="category-CustomizedDish">Customized Dish</label>
317
- </div>
318
- </form>
319
 
320
- <!-- Show menu items only when Customized Dish is not selected -->
321
  <div class="container mt-4">
322
  <h1 class="text-center">Menu</h1>
323
-
324
- <!-- Display text boxes for Customized Dish -->
325
- {% if selected_category == "Customized Dish" %}
326
- <div id="custom-dish-form" class="mt-4">
327
- <h3>Create Your Custom Dish</h3>
328
- <form method="POST" action="/generate_custom_dish">
329
- <div class="mb-3">
330
- <label for="custom-dish-name" class="form-label">Dish Name</label>
331
- <input type="text" class="form-control" id="custom-dish-name" name="name" required>
332
- </div>
333
- <div class="mb-3">
334
- <label for="custom-dish-description" class="form-label">Dish Description</label>
335
- <textarea class="form-control" id="custom-dish-description" name="description" required></textarea>
 
336
  </div>
337
- <button type="submit" class="btn btn-primary">Submit</button>
338
- </form>
339
- </div>
340
- {% else %}
341
-
342
- <!-- Menu Sections -->
343
- {% for section, items in ordered_menu.items() %}
344
- <h3>{{ section }}</h3>
345
- <div class="row">
346
- {% for item in items %}
347
- <div class="col-md-6 mb-4">
348
- <div class="card menu-card">
349
- <img src="{{ item.Image1__c }}" class="card-img-top menu-image" alt="{{ item.Name }}" onerror="this.src='/static/placeholder.jpg';">
350
- <div class="card-body">
351
- <h5 class="card-title">{{ item.Name }}</h5>
352
- <p class="card-text">${{ item.Price__c }}</p>
353
- <button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#itemModal"
354
- onclick="showItemDetails('{{ item.Name }}', '{{ item.Price__c }}', '{{ item.Image2__c }}', '{{ item.Description__c }}', '{{ item.Section__c }}','{{ selected_category }}')">
355
- Add
356
- </button>
357
  </div>
358
  </div>
359
- </div>
360
- {% endfor %}
361
- </div>
362
- {% endfor %}
363
- </div>
364
- {% endif %}
365
-
366
  </div>
367
 
368
- <!-- View Cart Button -->
369
  <div class="view-cart-container">
370
- <a href="/cart" class="view-cart-button">
371
- View Cart
372
- </a>
373
  </div>
374
 
375
- <!-- Bootstrap JS -->
376
- <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
377
-
378
- <!-- Modal for Item Details -->
379
  <div class="modal fade" id="itemModal" tabindex="-1" aria-labelledby="itemModalLabel" aria-hidden="true">
380
  <div class="modal-dialog modal-dialog-centered">
381
  <div class="modal-content">
@@ -384,27 +263,18 @@
384
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
385
  </div>
386
  <div class="modal-body">
387
- <!-- Item Image -->
388
  <img id="modal-img" class="img-fluid rounded mb-3 d-block mx-auto" alt="Item Image" style="max-height: 200px; object-fit: cover;">
389
- <!-- Item Name -->
390
  <h5 id="modal-name" class="fw-bold text-center"></h5>
391
- <!-- Item Price -->
392
  <p id="modal-price" class="text-muted text-center"></p>
393
- <!-- Item Description -->
394
  <p id="modal-description" class="text-secondary"></p>
395
- <!-- Add-ons -->
396
  <div id="modal-addons" class="modal-addons mt-4">
397
  <h6>Customization Options</h6>
398
  <div id="addons-list" class="addons-container">Loading customization options...</div>
399
  </div>
400
-
401
-
402
  <div class="mt-4">
403
  <h6>Custom Request</h6>
404
  <textarea id="modal-instructions" class="form-control" placeholder="Enter any special instructions here..."></textarea>
405
  </div>
406
- <span id="modal-section" data-section="" data-category="" style="display: none;"></span>
407
-
408
  </div>
409
  <div class="modal-footer">
410
  <button type="button" class="btn btn-primary" onclick="addToCartFromModal()">Add to Cart</button>
@@ -423,30 +293,24 @@
423
  document.getElementById('modal-description').innerText = description || 'No description available.';
424
  document.getElementById('addons-list').innerHTML = 'Loading customization options...';
425
  document.getElementById('modal-instructions').value = '';
426
- // Set section and category for reference
427
  const modalSectionEl = document.getElementById('modal-section');
428
  modalSectionEl.setAttribute('data-section', section);
429
  modalSectionEl.setAttribute('data-category', selectedCategory);
430
- // Fetch customization options based on the section
431
  fetch(`/api/addons?item_name=${encodeURIComponent(name)}&item_section=${encodeURIComponent(section)}`)
432
  .then(response => response.json())
433
  .then(data => {
434
  const addonsList = document.getElementById('addons-list');
435
  addonsList.innerHTML = ''; // Clear previous content
436
-
437
  if (!data.success || !data.addons || data.addons.length === 0) {
438
  addonsList.innerHTML = '<p>No customization options available.</p>';
439
  return;
440
  }
441
- // Display customization options inside styled divs
442
  data.addons.forEach(addon => {
443
  const sectionDiv = document.createElement('div');
444
- sectionDiv.classList.add('addon-section'); // Add styling class
445
- // Add section title
446
  const title = document.createElement('h6');
447
  title.innerText = addon.name;
448
  sectionDiv.appendChild(title);
449
- // Create options list
450
  const optionsContainer = document.createElement('div');
451
  addon.options.forEach((option, index) => {
452
  const optionId = `addon-${addon.name.replace(/\s+/g, '')}-${index}`;
@@ -471,161 +335,62 @@
471
  });
472
  }
473
 
474
- function filterMenu() {
475
- let input = document.getElementById('searchBar').value.toLowerCase(); // Get the value from search bar
476
- let sections = document.querySelectorAll('h3'); // Select section headers
477
- let items = document.querySelectorAll('.menu-card'); // Select all items
478
- let matchedSections = new Set(); // Store matched sections
479
-
480
- // Hide all items initially
481
- items.forEach(item => {
482
- let itemName = item.querySelector('.card-title').innerText.toLowerCase(); // Get item name
483
- let itemSection = item.closest('.row').previousElementSibling.innerText.toLowerCase(); // Get section name
484
-
485
- // If the search matches item name or section, show the item
486
- if (itemName.includes(input) || (itemSection && itemSection.includes(input))) {
487
- item.style.display = 'block'; // Show item if it matches search
488
- matchedSections.add(item.closest('.row')); // Add section to matched list
489
- } else {
490
- item.style.display = 'none'; // Hide item if not matched
491
- }
492
- });
493
-
494
- // Show or hide sections based on matched items
495
- sections.forEach(section => {
496
- let sectionRow = section.nextElementSibling; // The row containing items
497
- if (matchedSections.has(sectionRow)) {
498
- section.style.display = 'block'; // Show section header
499
- sectionRow.style.display = 'flex'; // Show section items
500
- } else {
501
- section.style.display = 'none'; // Hide section header
502
- sectionRow.style.display = 'none'; // Hide section items
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
503
  }
504
- });
505
- }
506
-
507
- function addToCartFromModal() {
508
- const itemName = document.getElementById('modal-name').innerText;
509
- let itemPrice = parseFloat(document.getElementById('modal-price').innerText.replace('$', ''));
510
-
511
- // Validate item price
512
- if (isNaN(itemPrice)) {
513
- alert('Invalid price for the item. Please check the item details.');
514
- return;
515
- }
516
 
517
- const itemImage = document.getElementById('modal-img').src;
518
- console.log(itemName, itemPrice, itemImage); // Log values for debugging
519
- const modalSectionEl = document.getElementById('modal-section');
520
- const section = modalSectionEl.getAttribute('data-section');
521
- const selectedCategory = modalSectionEl.getAttribute('data-category');
522
- if (!itemName || !itemPrice || !section) {
523
- console.error('Missing data for cart item:', { itemName, itemPrice, section });
524
- return;
525
- }
526
-
527
- // Collect selected add-ons
528
- let selectedAddOns = Array.from(
529
- document.querySelectorAll('#addons-list input[type="checkbox"]:checked')
530
- ).map(addon => ({
531
- name: addon.getAttribute('data-name') || 'Default Name', //Fallback Name
532
- price: parseFloat(addon.getAttribute('data-price') || 0)
533
- }));
534
- const instructions = document.getElementById('modal-instructions').value;
535
-
536
- // Prepare data for the cart
537
- const cartPayload = {
538
- itemName: itemName,
539
- itemPrice: itemPrice,
540
- itemImage: itemImage,
541
- section: section,
542
- category: selectedCategory,
543
- addons: selectedAddOns,
544
- instructions: instructions
545
- };
546
-
547
- // Send the cart data to the server
548
- fetch('/cart/add', {
549
- method: 'POST',
550
- headers: {
551
- 'Content-Type': 'application/json',
552
- },
553
- body: JSON.stringify(cartPayload)
554
- })
555
- .then(response => response.json())
556
- .then(data => {
557
- if (data.success) {
558
- alert('Item added to cart successfully!');
559
- updateCartUI(data.cart); // Update cart UI after adding an item
560
- const modal = document.getElementById('itemModal');
561
- const modalInstance = bootstrap.Modal.getInstance(modal);
562
- modalInstance.hide();
563
- } else {
564
- alert(data.error || 'Failed to add item to cart.');
565
  }
566
- })
567
- .catch(err => {
568
- console.error('Error adding item to cart:', err);
569
- alert('An error occurred while adding the item to the cart.');
570
- });
571
- }
572
- function updateCartUI(cart) {
573
- if (!Array.isArray(cart)) {
574
- console.error('Invalid cart data:', cart);
575
- return;
576
- }
577
- const cartIcon = document.getElementById('cart-icon');
578
- cartIcon.innerText = cart.length; // Assuming cart is an array of items
579
- }
580
-
581
- function updateCartDisplay(cart) {
582
- if (!Array.isArray(cart)) {
583
- console.error('Invalid cart data:', cart);
584
- return;
585
- }
586
- const cartCountElement = document.getElementById('cart-count');
587
- cartCountElement.innerText = cart.length; // Update cart item count
588
- // Optionally, show a small success notification that the item was added
589
- const successNotification = document.createElement('div');
590
- successNotification.classList.add('success-notification');
591
- successNotification.innerText = 'Item added to cart!';
592
- document.body.appendChild(successNotification);
593
- setTimeout(() => {
594
- successNotification.remove(); // Remove success notification after a few seconds
595
- }, 2000);
596
- }
597
-
598
- // Function to round reward points to a single digit
599
- function roundRewardPoints() {
600
- // Get the reward points element
601
- let rewardPointsElement = document.getElementById('reward-points');
602
-
603
- // Check if the element exists in the DOM
604
- if (rewardPointsElement) {
605
- let rewardPointsText = rewardPointsElement.innerText.trim(); // Get and trim the value to remove any extra spaces
606
-
607
- // Check if the innerText is a valid number
608
- let rewardPoints = parseFloat(rewardPointsText);
609
-
610
- // If it's a valid number, round it to 1 decimal place
611
- if (!isNaN(rewardPoints)) {
612
- rewardPointsElement.innerText = rewardPoints.toFixed(1); // Round to 1 decimal place
613
- } else {
614
- console.error("Reward points value is not a valid number:", rewardPointsText);
615
- }
616
- } else {
617
- console.error("Reward points element is missing.");
618
- }
619
- }
620
- // Run the function when the page loads
621
- window.onload = roundRewardPoints;
622
-
623
  </script>
624
 
625
- <!-- Bootstrap JS -->
626
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
627
  </body>
628
  </html>
629
- </script>
630
- </body>
631
- </html>
 
10
  <style>
11
  body {
12
  font-family: Arial, sans-serif;
13
+ background-color: #fdf4e3;
14
  margin: 0;
15
  padding: 0;
16
  display: flex;
 
45
  font-weight: bold;
46
  border-radius: 5px;
47
  width: 100px;
48
+ background-color: #0FAA39;
49
  border-color: #28a745;
 
50
  }
51
  .btn-primary:hover {
52
  background-color: #0FAA39;
 
65
  z-index: 999;
66
  }
67
  .view-cart-button {
68
+ background-color: #0FAA39;
69
  color: #fff;
70
  padding: 10px 20px;
71
  border-radius: 30px;
 
78
  justify-content: center;
79
  }
80
  .view-cart-button:hover {
81
+ background-color: #109835;
82
  text-decoration: none;
83
  }
84
  .avatar-dropdown-container {
 
103
  top: 100%;
104
  background-color: #fff;
105
  border-radius: 5px;
106
+ width: 200px;
107
  box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
108
  display: none;
109
  }
 
115
  text-decoration: none;
116
  color: #333;
117
  border-bottom: 1px solid #ddd;
118
+ display: block;
119
  }
120
  .dropdown-menu .dropdown-item:last-child {
121
+ border-bottom: none;
122
  }
123
  .dropdown-menu .dropdown-item:hover {
124
  background-color: #f1f1f1;
125
  }
126
  .fixed-search-container {
127
  position: absolute;
128
+ top: 90px;
129
  left: 50%;
130
  transform: translateX(-50%);
131
  width: 80%;
132
  max-width: 600px;
133
+ z-index: 999;
134
  background-color: white;
135
  padding: 10px;
136
  border-radius: 25px;
137
  box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2);
138
  }
 
 
 
 
 
139
  .container {
140
+ margin-top: 180px;
141
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  .addon-section {
143
+ background-color: #f8f9fa;
144
+ border: 2px solid #ff6b35;
145
  border-radius: 8px;
146
  padding: 12px;
147
+ margin-bottom: 15px;
148
  }
 
149
  .addon-section h6 {
150
  margin-bottom: 10px;
151
  font-size: 1.1rem;
152
  font-weight: bold;
153
  color: #333;
154
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  .form-check-label {
156
  font-size: 16px;
157
+ margin-left: 8px;
158
  }
 
159
  .custom-radio {
 
 
 
160
  width: 18px;
161
  height: 18px;
162
  border: 2px solid #333;
163
  border-radius: 50%;
164
+ margin-right: 10px;
165
  outline: none;
166
  cursor: pointer;
 
167
  }
 
168
  .custom-radio:checked {
169
  background-color: #007bff;
170
  border-color: #007bff;
171
  }
 
172
  .custom-radio:checked::after {
173
  content: '';
174
  position: absolute;
 
179
  background-color: #fff;
180
  border-radius: 50%;
181
  }
182
+ .form-check-inline {
183
+ margin-right: 10px;
 
 
 
 
 
 
 
184
  }
185
+ </style>
186
  </head>
187
  <body>
188
+ <div class="fixed-top-bar">
189
+ <div class="avatar-dropdown-container">
190
+ <div class="avatar-icon">
191
+ <span>{{ first_letter }}</span> <!-- First letter of user's name -->
192
+ </div>
193
+ <div class="dropdown-menu">
194
+ <a href="{{ url_for('customer_details') }}" class="dropdown-item">View Profile</a>
195
+ <a href="{{ url_for('order_history') }}" class="dropdown-item">Order History</a>
196
+ <a href="{{ url_for('logout') }}" class="dropdown-item">Logout</a>
197
+ </div>
 
198
  </div>
199
  </div>
200
 
201
+ <form method="get" action="/menu" class="text-center mb-4">
202
+ <label class="form-label fw-bold">Select a Category:</label>
203
+ <div class="form-check form-check-inline">
204
+ {% for category in categories %}
205
+ <input type="radio" id="category-{{ category }}" name="category" value="{{ category }}" class="custom-radio"
206
+ {% if selected_category == category %}checked{% endif %} onchange="this.form.submit()">
207
+ <label class="form-check-label" for="category-{{ category }}">{{ category }}</label>
208
+ {% endfor %}
209
+ </div>
210
+ </form>
 
 
 
 
 
 
 
 
 
 
 
211
 
 
212
  <div class="container mt-4">
213
  <h1 class="text-center">Menu</h1>
214
+ {% if selected_category == "Customized Dish" %}
215
+ <div id="custom-dish-form" class="mt-4">
216
+ <h3>Create Your Custom Dish</h3>
217
+ <form method="POST" action="/generate_custom_dish">
218
+ <div class="mb-3">
219
+ <label for="custom-dish-name" class="form-label">Dish Name</label>
220
+ <input type="text" class="form-control" id="custom-dish-name" name="name" required>
221
+ </div>
222
+ <div class="mb-3">
223
+ <label for="custom-dish-description" class="form-label">Dish Description</label>
224
+ <textarea class="form-control" id="custom-dish-description" name="description" required></textarea>
225
+ </div>
226
+ <button type="submit" class="btn btn-primary">Submit</button>
227
+ </form>
228
  </div>
229
+ {% else %}
230
+ {% for section, items in ordered_menu.items() %}
231
+ <h3>{{ section }}</h3>
232
+ <div class="row">
233
+ {% for item in items %}
234
+ <div class="col-md-6 mb-4">
235
+ <div class="card menu-card">
236
+ <img src="{{ item.Image1__c }}" class="card-img-top menu-image" alt="{{ item.Name }}" onerror="this.src='/static/placeholder.jpg';">
237
+ <div class="card-body">
238
+ <h5 class="card-title">{{ item.Name }}</h5>
239
+ <p class="card-text">${{ item.Price__c }}</p>
240
+ <button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#itemModal"
241
+ onclick="showItemDetails('{{ item.Name }}', '{{ item.Price__c }}', '{{ item.Image2__c }}', '{{ item.Description__c }}', '{{ item.Section__c }}','{{ selected_category }}')">
242
+ Add
243
+ </button>
244
+ </div>
 
 
 
 
245
  </div>
246
  </div>
247
+ {% endfor %}
248
+ </div>
249
+ {% endfor %}
250
+ {% endif %}
 
 
 
251
  </div>
252
 
 
253
  <div class="view-cart-container">
254
+ <a href="/cart" class="view-cart-button">View Cart</a>
 
 
255
  </div>
256
 
257
+ <!-- Modal for Item Details -->
 
 
 
258
  <div class="modal fade" id="itemModal" tabindex="-1" aria-labelledby="itemModalLabel" aria-hidden="true">
259
  <div class="modal-dialog modal-dialog-centered">
260
  <div class="modal-content">
 
263
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
264
  </div>
265
  <div class="modal-body">
 
266
  <img id="modal-img" class="img-fluid rounded mb-3 d-block mx-auto" alt="Item Image" style="max-height: 200px; object-fit: cover;">
 
267
  <h5 id="modal-name" class="fw-bold text-center"></h5>
 
268
  <p id="modal-price" class="text-muted text-center"></p>
 
269
  <p id="modal-description" class="text-secondary"></p>
 
270
  <div id="modal-addons" class="modal-addons mt-4">
271
  <h6>Customization Options</h6>
272
  <div id="addons-list" class="addons-container">Loading customization options...</div>
273
  </div>
 
 
274
  <div class="mt-4">
275
  <h6>Custom Request</h6>
276
  <textarea id="modal-instructions" class="form-control" placeholder="Enter any special instructions here..."></textarea>
277
  </div>
 
 
278
  </div>
279
  <div class="modal-footer">
280
  <button type="button" class="btn btn-primary" onclick="addToCartFromModal()">Add to Cart</button>
 
293
  document.getElementById('modal-description').innerText = description || 'No description available.';
294
  document.getElementById('addons-list').innerHTML = 'Loading customization options...';
295
  document.getElementById('modal-instructions').value = '';
 
296
  const modalSectionEl = document.getElementById('modal-section');
297
  modalSectionEl.setAttribute('data-section', section);
298
  modalSectionEl.setAttribute('data-category', selectedCategory);
 
299
  fetch(`/api/addons?item_name=${encodeURIComponent(name)}&item_section=${encodeURIComponent(section)}`)
300
  .then(response => response.json())
301
  .then(data => {
302
  const addonsList = document.getElementById('addons-list');
303
  addonsList.innerHTML = ''; // Clear previous content
 
304
  if (!data.success || !data.addons || data.addons.length === 0) {
305
  addonsList.innerHTML = '<p>No customization options available.</p>';
306
  return;
307
  }
 
308
  data.addons.forEach(addon => {
309
  const sectionDiv = document.createElement('div');
310
+ sectionDiv.classList.add('addon-section');
 
311
  const title = document.createElement('h6');
312
  title.innerText = addon.name;
313
  sectionDiv.appendChild(title);
 
314
  const optionsContainer = document.createElement('div');
315
  addon.options.forEach((option, index) => {
316
  const optionId = `addon-${addon.name.replace(/\s+/g, '')}-${index}`;
 
335
  });
336
  }
337
 
338
+ function addToCartFromModal() {
339
+ const itemName = document.getElementById('modal-name').innerText;
340
+ let itemPrice = parseFloat(document.getElementById('modal-price').innerText.replace('$', ''));
341
+ if (isNaN(itemPrice)) {
342
+ alert('Invalid price for the item. Please check the item details.');
343
+ return;
344
+ }
345
+ const itemImage = document.getElementById('modal-img').src;
346
+ const modalSectionEl = document.getElementById('modal-section');
347
+ const section = modalSectionEl.getAttribute('data-section');
348
+ const selectedCategory = modalSectionEl.getAttribute('data-category');
349
+ let selectedAddOns = Array.from(
350
+ document.querySelectorAll('#addons-list input[type="checkbox"]:checked')
351
+ ).map(addon => ({
352
+ name: addon.getAttribute('data-name') || 'Default Name',
353
+ price: parseFloat(addon.getAttribute('data-price') || 0)
354
+ }));
355
+ const instructions = document.getElementById('modal-instructions').value;
356
+ const cartPayload = {
357
+ itemName: itemName,
358
+ itemPrice: itemPrice,
359
+ itemImage: itemImage,
360
+ section: section,
361
+ category: selectedCategory,
362
+ addons: selectedAddOns,
363
+ instructions: instructions
364
+ };
365
+ fetch('/cart/add', {
366
+ method: 'POST',
367
+ headers: { 'Content-Type': 'application/json' },
368
+ body: JSON.stringify(cartPayload)
369
+ })
370
+ .then(response => response.json())
371
+ .then(data => {
372
+ if (data.success) {
373
+ alert('Item added to cart successfully!');
374
+ updateCartUI(data.cart);
375
+ const modal = document.getElementById('itemModal');
376
+ const modalInstance = bootstrap.Modal.getInstance(modal);
377
+ modalInstance.hide();
378
+ } else {
379
+ alert(data.error || 'Failed to add item to cart.');
380
+ }
381
+ })
382
+ .catch(err => {
383
+ console.error('Error adding item to cart:', err);
384
+ alert('An error occurred while adding the item to the cart.');
385
+ });
386
  }
 
 
 
 
 
 
 
 
 
 
 
 
387
 
388
+ function updateCartUI(cart) {
389
+ const cartIcon = document.getElementById('cart-icon');
390
+ cartIcon.innerText = cart.length;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
391
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
392
  </script>
393
 
 
394
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
395
  </body>
396
  </html>