Swathi6 commited on
Commit
c3f7e56
·
verified ·
1 Parent(s): 8ec26d2

Create templates/menu.html

Browse files
Files changed (1) hide show
  1. templates/menu.html +786 -0
templates/menu.html ADDED
@@ -0,0 +1,786 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Menu</title>
7
+ <!-- Bootstrap CSS -->
8
+ <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
9
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">
10
+ <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
+ const modalSectionEl = document.getElementById('modal-section');
545
+ modalSectionEl.setAttribute('data-section', section);
546
+ modalSectionEl.setAttribute('data-category', selectedCategory);
547
+ // Set the default quantity to 1
548
+ document.getElementById('quantityInput').value = 1;
549
+
550
+ // Fetch customization options based on the section
551
+ fetch(`/api/addons?item_name=${encodeURIComponent(name)}&item_section=${encodeURIComponent(section)}`)
552
+ .then(response => response.json())
553
+ .then(data => {
554
+ const addonsList = document.getElementById('addons-list');
555
+ addonsList.innerHTML = ''; // Clear previous content
556
+ if (!data.success || !data.addons || data.addons.length === 0) {
557
+ addonsList.innerHTML = '<p>No customization options available.</p>';
558
+ return;
559
+ }
560
+
561
+ // Display customization options inside styled divs
562
+ data.addons.forEach(addon => {
563
+ const sectionDiv = document.createElement('div');
564
+ sectionDiv.classList.add('addon-section'); // Add styling class
565
+
566
+ // Add section title
567
+ const title = document.createElement('h6');
568
+ title.innerText = addon.name;
569
+ sectionDiv.appendChild(title);
570
+
571
+ // Create options list
572
+ const optionsContainer = document.createElement('div');
573
+ addon.options.forEach((option, index) => {
574
+ const optionId = `addon-${addon.name.replace(/\s+/g, '')}-${index}`;
575
+ const listItem = document.createElement('div');
576
+ listItem.classList.add('form-check');
577
+ listItem.innerHTML = `
578
+ <input type="checkbox" class="form-check-input addon-option" id="${optionId}" value="${option}"
579
+ data-name="${option}" data-group="${addon.name}" data-price="${addon.extra_charge ? addon.extra_charge_amount : 0}">
580
+ <label class="form-check-label" for="${optionId}">
581
+ ${option} ${addon.extra_charge ? `($${addon.extra_charge_amount})` : ''}
582
+ </label>
583
+ `;
584
+ optionsContainer.appendChild(listItem);
585
+ });
586
+ sectionDiv.appendChild(optionsContainer);
587
+ addonsList.appendChild(sectionDiv);
588
+ });
589
+ })
590
+ .catch(err => {
591
+ console.error('Error fetching add-ons:', err);
592
+ document.getElementById('addons-list').innerHTML = '<p>Error loading customization options.</p>';
593
+ });
594
+ }
595
+ // Handle single-select/deselect logic for checkbox groups in all modals
596
+ document.addEventListener('click', function(event) {
597
+ if (event.target.classList.contains('addon-option')) {
598
+ handleAddonClick(event.target);
599
+ }
600
+ });
601
+ // Handle checkbox selection logic
602
+ function handleAddonClick(checkbox) {
603
+ const groupName = checkbox.getAttribute('data-group');
604
+ const isMultiSelectGroup = ["Extra Toppings", "Choose Raita/Sides","Select Dip/Sauce","Extra Add-ons","Make it a Combo"].includes(groupName);
605
+
606
+ // If it's not multi-select, uncheck all other checkboxes in the same group
607
+ if (!isMultiSelectGroup) {
608
+ const checkboxes = document.querySelectorAll(`.addon-option[data-group="${groupName}"]`);
609
+ checkboxes.forEach(otherCheckbox => {
610
+ if (otherCheckbox !== checkbox) {
611
+ otherCheckbox.checked = false;
612
+ }
613
+ });
614
+ }
615
+ }
616
+ function filterMenu() {
617
+ let input = document.getElementById('searchBar').value.toLowerCase(); // Get the value from search bar
618
+ let sections = document.querySelectorAll('h3'); // Select section headers
619
+ let items = document.querySelectorAll('.menu-card'); // Select all items
620
+ let matchedSections = new Set(); // Store matched sections
621
+
622
+ // Hide all items initially
623
+ items.forEach(item => {
624
+ let itemName = item.querySelector('.card-title').innerText.toLowerCase(); // Get item name
625
+ let itemSection = item.closest('.row').previousElementSibling.innerText.toLowerCase(); // Get section name
626
+
627
+ // If the search matches item name or section, show the item
628
+ if (itemName.includes(input) || (itemSection && itemSection.includes(input))) {
629
+ item.style.display = 'block'; // Show item if it matches search
630
+ matchedSections.add(item.closest('.row')); // Add section to matched list
631
+ } else {
632
+ item.style.display = 'none'; // Hide item if not matched
633
+ }
634
+ });
635
+
636
+ // Show or hide sections based on matched items
637
+ sections.forEach(section => {
638
+ let sectionRow = section.nextElementSibling; // The row containing items
639
+ if (matchedSections.has(sectionRow)) {
640
+ section.style.display = 'block'; // Show section header
641
+ sectionRow.style.display = 'flex'; // Show section items
642
+ } else {
643
+ section.style.display = 'none'; // Hide section header
644
+ sectionRow.style.display = 'none'; // Hide section items
645
+ }
646
+ });
647
+ }
648
+ function addToCartFromModal() {
649
+ const itemName = document.getElementById('modal-name').innerText;
650
+ let itemPrice = parseFloat(document.getElementById('modal-price').innerText.replace('$', ''));
651
+ // Validate item price
652
+ if (isNaN(itemPrice)) {
653
+ alert('Invalid price for the item. Please check the item details.');
654
+ return;
655
+ }
656
+ const itemImage = document.getElementById('modal-img').src;
657
+ console.log(itemName, itemPrice, itemImage); // Log values for debugging
658
+ const modalSectionEl = document.getElementById('modal-section');
659
+ const section = modalSectionEl.getAttribute('data-section');
660
+ const selectedCategory = modalSectionEl.getAttribute('data-category');
661
+ if (!itemName || !itemPrice || !section || !itemImage) {
662
+ console.error('Missing data for cart item:', { itemName, itemPrice, section, itemImage});
663
+ return;
664
+ }
665
+
666
+ // Collect selected add-ons
667
+ let selectedAddOns = Array.from(
668
+ document.querySelectorAll('#addons-list input[type="checkbox"]:checked')
669
+ ).map(addon => ({
670
+ name: addon.getAttribute('data-name') || 'Default Name', // Fallback Name
671
+ price: parseFloat(addon.getAttribute('data-price') || 0)
672
+ }));
673
+ // Get the selected quantity
674
+ const quantity = parseInt(document.getElementById('quantityInput').value) || 1; // Default to 1 if invalid
675
+ const instructions = document.getElementById('modal-instructions').value;
676
+ // Prepare data for the cart
677
+ const cartPayload = {
678
+ itemName: itemName,
679
+ itemPrice: itemPrice,
680
+ itemImage: itemImage,
681
+ section: section,
682
+ category: selectedCategory,
683
+ addons: selectedAddOns,
684
+ instructions: instructions,
685
+ quantity: quantity // Include the quantity
686
+ };
687
+ // Send the cart data to the server
688
+ fetch('/cart/add', {
689
+ method: 'POST',
690
+ headers: {
691
+ 'Content-Type': 'application/json',
692
+ },
693
+ body: JSON.stringify(cartPayload)
694
+ })
695
+ .then(response => response.json())
696
+ .then(data => {
697
+ if (data.success) {
698
+ alert('Item added to cart successfully!');
699
+ updateCartUI(data.cart); // Update cart UI after adding an item
700
+ const modal = document.getElementById('itemModal');
701
+ const modalInstance = bootstrap.Modal.getInstance(modal);
702
+ modalInstance.hide();
703
+ } else {
704
+ alert(data.error || 'Failed to add item to cart.');
705
+ }
706
+ })
707
+ .catch(err => {
708
+ console.error('Error adding item to cart:', err);
709
+ alert('An error occurred while adding the item to the cart.');
710
+ });
711
+ }
712
+ function updateCartUI(cart) {
713
+ if (!Array.isArray(cart)) {
714
+ console.error('Invalid cart data:', cart);
715
+ return;
716
+ }
717
+ const cartIcon = document.getElementById('cart-icon');
718
+ cartIcon.innerText = cart.length; // Assuming cart is an array of items
719
+ }
720
+ function updateCartDisplay(cart) {
721
+ if (!Array.isArray(cart)) {
722
+ console.error('Invalid cart data:', cart);
723
+ return;
724
+ }
725
+ // Optional: Update quantity on the cart page
726
+ const cartCountElement = document.getElementById('cart-count');
727
+ cartCountElement.innerText = cart.reduce((total, item)=> total+item.quantity,0); // Update cart item count //Sum of all quantities
728
+
729
+ // Optionally, show a small success notification that the item was added
730
+ const successNotification = document.createElement('div');
731
+ successNotification.classList.add('success-notification');
732
+ successNotification.innerText = 'Item added to cart!';
733
+ document.body.appendChild(successNotification);
734
+ setTimeout(() => {
735
+ successNotification.remove(); // Remove success notification after a few seconds
736
+ }, 2000);
737
+ }
738
+
739
+ document.addEventListener('DOMContentLoaded', function () {
740
+ // Get references to the quantity buttons and the input field
741
+ const decreaseBtn = document.getElementById('decreaseQuantity');
742
+ const increaseBtn = document.getElementById('increaseQuantity');
743
+ const quantityInput = document.getElementById('quantityInput');
744
+ // Add event listener to decrease button
745
+ decreaseBtn.addEventListener('click', function () {
746
+ let currentQuantity = parseInt(quantityInput.value);
747
+ if (currentQuantity > 1) {
748
+ currentQuantity--;
749
+ quantityInput.value = currentQuantity;
750
+ }
751
+ });
752
+ // Add event listener to increase button
753
+ increaseBtn.addEventListener('click', function () {
754
+ let currentQuantity = parseInt(quantityInput.value);
755
+ currentQuantity++;
756
+ quantityInput.value = currentQuantity;
757
+ });
758
+ });
759
+ // Function to round reward points to a single digit
760
+ function roundRewardPoints() {
761
+ // Get the reward points element
762
+ let rewardPointsElement = document.getElementById('reward-points');
763
+ // Check if the element exists in the DOM
764
+ if (rewardPointsElement) {
765
+ let rewardPointsText = rewardPointsElement.innerText.trim(); // Get and trim the value to remove any extra spaces
766
+ // Check if the innerText is a valid number
767
+ let rewardPoints = parseFloat(rewardPointsText);
768
+ // If it's a valid number, round it to 1 decimal place
769
+ if (!isNaN(rewardPoints)) {
770
+ rewardPointsElement.innerText = rewardPoints.toFixed(1); // Round to 1 decimal place
771
+ } else {
772
+ console.error("Reward points value is not a valid number:", rewardPointsText);
773
+ }
774
+ } else {
775
+ console.error("Reward points element is missing.");
776
+ }
777
+ }
778
+ // Run the function when the page loads
779
+ window.onload = roundRewardPoints;
780
+
781
+ </script>
782
+
783
+ <!-- Bootstrap JS -->
784
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
785
+ </body>
786
+ </html>