geethareddy commited on
Commit
5e81e51
·
verified ·
1 Parent(s): b53057b

Update templates/menu.html

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