lokeshloki143 commited on
Commit
0270e24
·
verified ·
1 Parent(s): f9e382e

Update templates/menu.html

Browse files
Files changed (1) hide show
  1. templates/menu.html +448 -570
templates/menu.html CHANGED
@@ -1,13 +1,11 @@
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
- <!-- Preload Critical Resources -->
11
  <link rel="preload" href="/static/placeholder.mp4" as="video">
12
  {% for section, items in ordered_menu.items() %}
13
  {% for item in items[:1] %}
@@ -39,7 +37,6 @@
39
  transition: opacity 0.3s ease-in-out;
40
  box-shadow: 0 4px 8px rgba(0,0,0,0.1);
41
  }
42
-
43
  .menu-card.visible {
44
  opacity: 1;
45
  }
@@ -237,7 +234,6 @@
237
  .mic-icon.active {
238
  color: #007bff;
239
  }
240
- /* Addon Section */
241
  .addon-section {
242
  background-color: #fff;
243
  border-radius: 10px;
@@ -288,7 +284,7 @@
288
  background-color: #fff;
289
  position: relative;
290
  margin-left: 10px;
291
- cursor: pointer;
292
  transition: all 0.2s ease;
293
  }
294
  .addon-section .form-check-input:checked {
@@ -355,7 +351,6 @@
355
  border-radius: 50%;
356
  animation: spin 1s linear infinite;
357
  }
358
- /* Soft Drinks Modal Styling */
359
  #softDrinkModal .modal-dialog {
360
  max-width: 400px;
361
  margin: 1.75rem auto;
@@ -495,12 +490,11 @@
495
  #softDrinkModal .modal-footer .quantity-controls-footer .btn:active {
496
  transform: scale(0.95);
497
  }
498
- /* Filter Form Styling */
499
  #filter-form {
500
  display: flex;
501
  flex-direction: column;
502
- align-items: flex-start; /* Align to the left */
503
- justify-content: flex-start; /* Align to the top */
504
  margin-bottom: 20px;
505
  }
506
  .form-label {
@@ -548,6 +542,108 @@
548
  color: #333;
549
  cursor: pointer;
550
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
551
  @keyframes checkmark {
552
  from { transform: scale(0); }
553
  to { transform: scale(1); }
@@ -564,6 +660,11 @@
564
  from { opacity: 0; transform: translateY(-20px); }
565
  to { opacity: 1; transform: translateY(0); }
566
  }
 
 
 
 
 
567
  .modal-header {
568
  padding: 10px 15px;
569
  }
@@ -774,7 +875,7 @@
774
  border-radius: 8px;
775
  font-weight: bold;
776
  font-size: 16px;
777
- color: #000000; /* Black text color for buttons */
778
  display: flex;
779
  align-items: center;
780
  justify-content: center;
@@ -783,11 +884,12 @@
783
  white-space: nowrap;
784
  }
785
  .bottom-action-bar .btn-order-history {
786
- background: linear-gradient(45deg, #FFA07A, #0FAA39);
787
- border: none;
788
  }
789
  .bottom-action-bar .btn-order-history:hover {
790
- background: linear-gradient(45deg, #FF8C61, #0D9232);
 
791
  }
792
  .bottom-action-bar .btn-view-cart {
793
  background-color: #0FAA39;
@@ -809,7 +911,6 @@
809
  font-size: 12px;
810
  margin-left: 8px;
811
  }
812
- /* Mobile-Specific Styles */
813
  @media (max-width: 576px) {
814
  .fixed-top-bar {
815
  height: 60px;
@@ -963,7 +1064,6 @@
963
  font-size: 10px;
964
  margin-left: 5px;
965
  }
966
- /* Mobile-Specific Addon Styles */
967
  .addon-section {
968
  margin-bottom: 10px;
969
  }
@@ -992,7 +1092,6 @@
992
  margin-left: 6px;
993
  font-size: 0.8rem;
994
  }
995
- /* Mobile-Specific Soft Drinks Modal Styles */
996
  #softDrinkModal .modal-dialog {
997
  max-width: 90%;
998
  }
@@ -1035,7 +1134,7 @@
1035
  padding: 10px;
1036
  }
1037
  #softDrinkModal .modal-footer .btn-primary {
1038
- NEL padding: 10px 25px;
1039
  font-size: 1rem;
1040
  }
1041
  #softDrinkModal .modal-footer .quantity-controls-footer .btn {
@@ -1044,7 +1143,6 @@
1044
  font-size: 1rem;
1045
  line-height: 28px;
1046
  }
1047
- /* Mobile-Specific Filter Form Styles */
1048
  #filter-form {
1049
  margin-bottom: 15px;
1050
  }
@@ -1070,319 +1168,26 @@
1070
  .toggle-container label {
1071
  font-size: 0.9rem;
1072
  }
1073
- }
1074
- .chat-container {
1075
- box-sizing: border-box;
1076
- margin: 0;
1077
- padding: 0;
1078
- }
1079
- body {
1080
- font-family: 'Segoe UI', Arial, sans-serif;
1081
- background-color: #f4f7fa;
1082
- overflow-x: hidden;
1083
- line-height: 1.5;
1084
- }
1085
- .chat-container {
1086
- width: 100%;
1087
- max-width: 800px;
1088
- height: 100vh;
1089
- margin: 0 auto;
1090
- background-color: #ffffff;
1091
- border-radius: 12px;
1092
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
1093
- display: flex;
1094
- flex-direction: column;
1095
- overflow: hidden;
1096
- }
1097
- .chat-header {
1098
- background-color: #0078d4;
1099
- color: #ffffff;
1100
- padding: 12px;
1101
- text-align: center;
1102
- font-size: 18px;
1103
- font-weight: 600;
1104
- flex-shrink: 0;
1105
- }
1106
- .chat-messages {
1107
- flex: 1;
1108
- overflow-y: auto;
1109
- padding: 15px;
1110
- scroll-behavior: smooth;
1111
- }
1112
- .bot-message, .user-message {
1113
- padding: 10px 15px;
1114
- margin: 8px 0;
1115
- border-radius: 12px;
1116
- max-width: 80%;
1117
- font-size: 14px;
1118
- line-height: 1.4;
1119
- }
1120
- .bot-message {
1121
- background-color: #e8f0fe;
1122
- color: #333;
1123
- }
1124
- .user-message {
1125
- background-color: #0078d4;
1126
- color: #ffffff;
1127
- margin-left: auto;
1128
- }
1129
- .chat-input {
1130
- display: flex;
1131
- padding: 10px;
1132
- border-top: 1px solid #e0e0e0;
1133
- background-color: #f9f9f9;
1134
- flex-shrink: 0;
1135
- }
1136
- .chat-input input {
1137
- flex: 1;
1138
- padding: 10px;
1139
- border: 1px solid #ccc;
1140
- border-radius: 8px;
1141
- font-size: 14px;
1142
- outline: none;
1143
- }
1144
- .chat-input button {
1145
- padding: 10px 20px;
1146
- margin-left: 10px;
1147
- background-color: #0078d4;
1148
- color: #ffffff;
1149
- border: none;
1150
- border-radius: 8px;
1151
- cursor: pointer;
1152
- font-size: 14px;
1153
- transition: background-color 0.2s;
1154
- }
1155
- .chat-input button:hover {
1156
- background-color: #005ea2;
1157
- }
1158
- .ingredients-list, .menu-items-list, .customization-ingredients-list {
1159
- display: flex;
1160
- flex-wrap: nowrap; /* Ensure items stay in a single row */
1161
- overflow-x: auto; /* Allow horizontal scrolling */
1162
- padding: 10px;
1163
- margin: 10px 0;
1164
- background-color: #f5f7fa;
1165
- border-radius: 10px;
1166
- gap: 15px;
1167
- scroll-behavior: smooth;
1168
- }
1169
- .ingredient-item, .menu-item {
1170
- flex: 0 0 auto; /* Ensure items don't stretch */
1171
- width: 200px; /* Set a fixed width for each item */
1172
- background-color: #ffffff;
1173
- border: 1px solid #e0e0e0;
1174
- border-radius: 10px;
1175
- padding: 10px;
1176
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
1177
- transition: transform 0.2s;
1178
- text-align: center;
1179
- }
1180
- .ingredient-item:hover, .menu-item:hover {
1181
- transform: translateY(-2px);
1182
- }
1183
- .ingredient-item img, .menu-item img {
1184
- width: 100%;
1185
- height: 120px;
1186
- object-fit: cover;
1187
- border-radius: 8px;
1188
- margin-bottom: 8px;
1189
- }
1190
- .ingredient-item div, .menu-item div {
1191
- font-size: 14px;
1192
- font-weight: 600;
1193
- color: #333;
1194
- margin-bottom: 5px;
1195
- }
1196
- .ingredient-item button, .menu-item button {
1197
- padding: 8px;
1198
- background-color: #28a745;
1199
- color: #ffffff;
1200
- border: none;
1201
- border-radius: 6px;
1202
- cursor: pointer;
1203
- font-size: 12px;
1204
- width: 100%;
1205
- }
1206
- .ingredient-item button:hover, .menu-item button:hover {
1207
- background-color: #218838;
1208
- }
1209
- .selected-ingredients, .selected-customization-ingredients {
1210
- background-color: #f1f8ff;
1211
- padding: 15px;
1212
- border: 1px solid #b3d7ff;
1213
- border-radius: 10px;
1214
- margin: 10px 0;
1215
- font-size: 14px;
1216
- display: flex;
1217
- flex-wrap: wrap;
1218
- gap: 10px;
1219
- }
1220
- .selected-ingredients div, .selected-customization-ingredients div {
1221
- background-color: #d6e9ff;
1222
- padding: 5px 10px;
1223
- border-radius: 6px;
1224
- font-size: 13px;
1225
- }
1226
- .customization-input {
1227
- margin: 10px 0;
1228
- }
1229
- .customization-input textarea, .selected-customization-ingredients textarea {
1230
- width: 100%;
1231
- padding: 8px;
1232
- border: 1px solid #b3d7ff;
1233
- border-radius: 6px;
1234
- font-size: 14px;
1235
- outline: none;
1236
- margin-bottom: 10px;
1237
- }
1238
- .customization-input button, .submit-button, .submit-customization-button, .submit-cart-button {
1239
- padding: 10px 20px;
1240
- background-color: #0078d4;
1241
- color: #ffffff;
1242
- border: none;
1243
- border-radius: 8px;
1244
- cursor: pointer;
1245
- font-size: 14px;
1246
- transition: background-color 0.2s;
1247
- }
1248
- .customization-input button:hover, .submit-button:hover, .submit-customization-button:hover, .submit-cart-button:hover {
1249
- background-color: #005ea2;
1250
- }
1251
- .option-button {
1252
- padding: 10px 20px;
1253
- color: #ffffff;
1254
- border: none;
1255
- border-radius: 8px;
1256
- cursor: pointer;
1257
- font-size: 14px;
1258
- margin: 5px;
1259
- transition: background-color 0.2s;
1260
- }
1261
- .option-button.green {
1262
- background-color: #28a745;
1263
- }
1264
- .option-button.green:hover {
1265
- background-color: #218838;
1266
- }
1267
- .option-button.red {
1268
- background-color: #dc3545;
1269
- }
1270
- .option-button.red:hover {
1271
- background-color: #c82333;
1272
- }
1273
- .cart-items {
1274
- background-color: #f1f8ff;
1275
- padding: 15px;
1276
- border: 1px solid #b3d7ff;
1277
- border-radius: 10px;
1278
- margin: 10px 0;
1279
- font-size: 14px;
1280
- }
1281
- .cart-item {
1282
- display: flex;
1283
- align-items: center;
1284
- background-color: #d6e9ff;
1285
- padding: 5px 10px;
1286
- border-radius: 6px;
1287
- font-size: 13px;
1288
- margin: 5px 0;
1289
- }
1290
- .cart-item img {
1291
- width: 30px;
1292
- height: 30px;
1293
- object-fit: cover;
1294
- border-radius: 6px;
1295
- margin-right: 8px;
1296
- }
1297
- .cart-item .remove-button {
1298
- padding: 5px 10px;
1299
- margin-left: 8px;
1300
- background-color: #dc3545;
1301
- color: #ffffff;
1302
- border: none;
1303
- border-radius: 6px;
1304
- cursor: pointer;
1305
- font-size: 12px;
1306
- }
1307
- .cart-item .remove-button:hover {
1308
- background-color: #c82333;
1309
- }
1310
- /* Responsive Design */
1311
- @media (max-width: 480px) {
1312
- .chat-container {
1313
- border-radius: 0;
1314
- box-shadow: none;
1315
- }
1316
- .chat-header {
1317
- font-size: 16px;
1318
- padding: 10px;
1319
- }
1320
- .chat-messages {
1321
- padding: 10px;
1322
- }
1323
- .bot-message, .user-message {
1324
- font-size: 13px;
1325
- padding: 8px 12px;
1326
- margin: 5px 0;
1327
- }
1328
- .chat-input input {
1329
- font-size: 13px;
1330
- padding: 8px;
1331
- }
1332
- .chat-input button {
1333
- font-size: 13px;
1334
- padding: 8px 15px;
1335
- }
1336
- .ingredients-list, .menu-items-list, .customization-ingredients-list {
1337
- flex-direction: row; /* Keep the items in a row on mobile */
1338
- gap: 10px;
1339
  }
1340
- .ingredient-item, .menu-item {
1341
- flex: 0 0 150px; /* Adjust the item width to fit smaller screens */
1342
  }
1343
- .ingredient-item img, .menu-item img {
1344
- height: 100px;
1345
  }
1346
- .ingredient-item div, .menu-item div {
1347
- font-size: 13px;
 
1348
  }
1349
- .ingredient-item button, .menu-item button {
1350
- font-size: 11px;
1351
- padding: 6px;
1352
  }
1353
- .option-button {
1354
- font-size: 13px;
1355
  padding: 8px 15px;
1356
- }
1357
- .selected-ingredients, .selected-customization-ingredients, .cart-items {
1358
- padding: 10px;
1359
- gap: 8px;
1360
- }
1361
- .cart-item {
1362
- font-size: 12px;
1363
- padding: 4px 8px;
1364
- }
1365
- .cart-item img {
1366
- width: 25px;
1367
- height: 25px;
1368
- }
1369
- }
1370
- @media (min-width: 481px) and (max-width: 768px) {
1371
- .chat-container {
1372
- max-width: 600px;
1373
- }
1374
- .chat-header {
1375
- font-size: 17px;
1376
- padding: 11px;
1377
- }
1378
- .chat-messages {
1379
- padding: 12px;
1380
- }
1381
- .ingredient-item, .menu-item {
1382
- flex: 0 0 180px;
1383
- }
1384
- .ingredient-item img, .menu-item img {
1385
- height: 110px;
1386
  }
1387
  }
1388
  </style>
@@ -1406,40 +1211,33 @@
1406
  <i class="bi bi-mic mic-icon" id="micIcon"></i>
1407
  </div>
1408
  </div>
1409
-
1410
  <form method="get" action="/menu" class="text-center mb-4" id="filter-form">
1411
  <label class="form-label fw-bold">Filters:</label>
1412
  <div class="toggle-container">
1413
- <!-- Veg Only Toggle -->
1414
- <input type="checkbox" id="veg-toggle" name="veg"
1415
- {% if selected_category == "Veg" %}checked{% endif %}
1416
- class="custom-toggle" onchange="handleToggle('veg')"
1417
- aria-label="Toggle Vegetarian filter">
1418
  <label for="veg-toggle">Veg</label>
1419
  </div>
1420
  <div class="toggle-container">
1421
- <!-- Customized Dish Toggle -->
1422
- <input type="radio" id="category-CustomizedDish" name="category" value="Customized Dish"
1423
- {% if selected_category == "Customized Dish" %}checked{% endif %}
1424
- class="custom-toggle" onchange="handleToggle('custom')"
1425
- aria-label="Toggle Customized Dish filter">
1426
  <label for="category-CustomizedDish">Customized Dish</label>
1427
  </div>
1428
  </form>
1429
-
1430
  <div class="container mt-4">
1431
  {% if selected_category == "Customized Dish" %}
1432
  <div id="custom-dish-form" class="mt-4">
1433
- <div class="chat-container">
1434
- <div class="chat-header">🍳 Chef Bot</div>
1435
- <div class="chat-messages" id="chatMessages">
1436
- <!-- Initial message will be set by JavaScript based on session -->
1437
- </div>
1438
- <div class="chat-input">
1439
- <input type="text" id="userInput" placeholder="Type your name or message...">
1440
- <button onclick="sendMessage()">Send</button>
1441
- </div>
1442
- </div>
 
 
 
1443
  </div>
1444
  {% else %}
1445
  {% if ordered_menu.items()|length == 0 %}
@@ -1451,18 +1249,7 @@
1451
  {% for item in items %}
1452
  <div class="col-md-6 mb-4">
1453
  <div class="card menu-card" data-item-name="{{ item.Name | default('Unnamed Item') }}" data-item-section="{{ item.Section__c | default(section) }}">
1454
- <video
1455
- class="card-img-top menu-video"
1456
- muted
1457
- loop
1458
- preload="auto"
1459
- data-src="{{ item.Video1__c | default('/static/placeholder.mp4') }}"
1460
- poster="{{ item.Image1__c | default('/static/placeholder.jpg') }}"
1461
- width="350"
1462
- height="200"
1463
- onmouseover="this.play()"
1464
- onmouseout="this.pause(); this.currentTime = 0;"
1465
- onerror="this.poster='/static/placeholder.jpg';">
1466
  <source src="{{ item.Video1__c | default('/static/placeholder.mp4') }}" type="video/mp4">
1467
  Your browser does not support the video tag.
1468
  </video>
@@ -1473,23 +1260,11 @@
1473
  <p class="card-text price">${{ item.Price__c | default('0.00') }}</p>
1474
  </div>
1475
  <div class="d-flex flex-column align-items-center justify-content-center">
1476
- <div class="button-container"
1477
- data-item-name="{{ item.Name | default('Unnamed Item') }}"
1478
- data-item-price="{{ item.Price__c | default('0.00') }}"
1479
- data-item-image="{{ item.Image1__c | default('/static/placeholder.jpg') }}"
1480
- data-item-section="{{ item.Section__c | default(section) }}"
1481
- data-item-category="{{ selected_category }}"
1482
- data-item-description="{{ item.Description__c | default('No description') }}"
1483
- data-item-image2="{{ item.Image2__c | default(item.Image1__c) }}">
1484
  {% if item.Section__c == 'Soft Drinks' %}
1485
  <button class="btn btn-primary add-to-cart-btn" onclick="showSoftDrinkModal(this)">ADD</button>
1486
  {% else %}
1487
- <button class="btn btn-primary"
1488
- data-bs-toggle="modal"
1489
- data-bs-target="#itemModal"
1490
- onclick="showItemDetails('{{ item.Name | default('Unnamed Item') }}', '{{ item.Price__c | default('0.00') }}', '{{ item.Image2__c | default(item.Image1__c) }}', '{{ item.Description__c | default('No description') }}', '{{ item.Section__c | default(section) }}', '{{ selected_category }}')">
1491
- ADD
1492
- </button>
1493
  {% if item.Section__c != 'Apetizer' and item.Section__c != 'Customized dish' %}
1494
  <span class="customisable-text">Customisable</span>
1495
  {% endif %}
@@ -1519,7 +1294,6 @@
1519
  {% endif %}
1520
  {% endif %}
1521
  </div>
1522
-
1523
  <div class="bottom-action-bar">
1524
  <a href="{{ url_for('orderhistory.order_history') }}" class="btn btn-order-history">
1525
  <i class="bi bi-clock-history"></i> Order History
@@ -1529,12 +1303,10 @@
1529
  <span id="cart-item-count" class="cart-icon-badge" style="display: none;">0</span>
1530
  </a>
1531
  </div>
1532
-
1533
- <!-- Modal for Item Details -->
1534
  <div class="modal fade" id="itemModal" tabindex="-1" aria-labelledby="itemModalLabel" aria-hidden="true">
1535
  <div class="modal-dialog modal-dialog-centered">
1536
  <div class="modal-content">
1537
- <div class="modal-header názov">
1538
  <h5 class="modal-title" id="itemModalLabel">Item Details</h5>
1539
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
1540
  </div>
@@ -1564,8 +1336,6 @@
1564
  </div>
1565
  </div>
1566
  </div>
1567
-
1568
- <!-- Modal for Soft Drinks Quantity Selection -->
1569
  <div class="modal fade" id="softDrinkModal" tabindex="-1" aria-labelledby="softDrinkModalLabel" aria-hidden="true">
1570
  <div class="modal-dialog modal-dialog-centered">
1571
  <div class="modal-content">
@@ -1595,18 +1365,39 @@
1595
  </div>
1596
  </div>
1597
  </div>
1598
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1599
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
1600
  <script>
1601
  let isProcessingRequest = false;
1602
  let currentSoftDrinkButton = null;
1603
  let baseItemPrice = 0;
 
1604
  const menuItems = [
1605
  {% for section, items in ordered_menu.items() %}
1606
  {% for item in items %}
1607
  {
1608
  name: "{{ item.Name | default('Unnamed Item') }}",
1609
- section: "{{ item.Section__c | default(section) }}"
 
1610
  },
1611
  {% endfor %}
1612
  {% endfor %}
@@ -1634,7 +1425,7 @@
1634
  JSON.stringify(item.addons) === JSON.stringify(payload.addons)
1635
  );
1636
  if (existingItem) {
1637
- existingItem.quantity = payload.quantity;
1638
  } else {
1639
  cart.push(payload);
1640
  }
@@ -1661,13 +1452,6 @@
1661
  function getCartLocalStorage() {
1662
  return JSON.parse(localStorage.getItem('cart')) || [];
1663
  }
1664
- function debounce(func, wait) {
1665
- let timeout;
1666
- return function (...args) {
1667
- clearTimeout(timeout);
1668
- timeout = setTimeout(() => func.apply(this, args), wait);
1669
- };
1670
- }
1671
  function updateModalPrice() {
1672
  const selectedAddOns = Array.from(
1673
  document.querySelectorAll('#addons-list input[type="checkbox"]:checked')
@@ -1688,27 +1472,22 @@
1688
  const itemName = buttonContainer.getAttribute('data-item-name');
1689
  const itemPrice = buttonContainer.getAttribute('data-item-price');
1690
  const itemImage = buttonContainer.getAttribute('data-item-image');
1691
-
1692
  document.getElementById('soft-drink-name').textContent = itemName;
1693
- document.getElementById('soft-drink-price').textContent = `${itemPrice}`;
1694
  document.getElementById('soft-drink-quantity').value = '1';
1695
  document.getElementById('soft-drink-image').src = itemImage || '/static/placeholder.jpg';
1696
-
1697
  const modal = new bootstrap.Modal(document.getElementById('softDrinkModal'));
1698
  modal.show();
1699
  }
1700
  function addSoftDrinkToCart() {
1701
  if (!currentSoftDrinkButton) return;
1702
-
1703
  const buttonContainer = currentSoftDrinkButton.closest('.button-container');
1704
  const quantity = parseInt(document.getElementById('soft-drink-quantity').value) || 1;
1705
-
1706
  const itemName = buttonContainer.getAttribute('data-item-name');
1707
  const itemPrice = parseFloat(buttonContainer.getAttribute('data-item-price'));
1708
  const itemImage = buttonContainer.getAttribute('data-item-image');
1709
  const section = buttonContainer.getAttribute('data-item-section');
1710
  const selectedCategory = buttonContainer.getAttribute('data-item-category');
1711
-
1712
  const cartPayload = {
1713
  itemName: itemName,
1714
  itemPrice: itemPrice,
@@ -1719,7 +1498,6 @@
1719
  instructions: '',
1720
  quantity: quantity
1721
  };
1722
-
1723
  fetch('/cart/add', {
1724
  method: 'POST',
1725
  headers: {
@@ -1764,9 +1542,6 @@
1764
  cartItemCount.style.display = totalQuantity > 0 ? 'inline-flex' : 'none';
1765
  }
1766
  }
1767
-
1768
- window.most_common_addons = {{ most_common_addons | tojson }};
1769
- console.log("Most common add-ons: ", window.most_common_addons);
1770
  function showItemDetails(name, price, image, description, section, selectedCategory) {
1771
  document.getElementById('modal-name').innerText = name;
1772
  baseItemPrice = parseFloat(price) || 0;
@@ -1841,42 +1616,6 @@
1841
  }
1842
  });
1843
  });
1844
- // Pre-select the highest-count spice level
1845
- if (window.most_common_addons && window.most_common_addons.length > 0) {
1846
- const checkboxes = document.querySelectorAll('.addon-option');
1847
- const categorySelection = {
1848
- "Select Spice Level": null,
1849
- "Choose Spice Level": null,
1850
- "Raita/Sides": [],
1851
- };
1852
- // First pass: Find and select the highest-count spice level
1853
- for (let spice of window.most_common_addons) {
1854
- const isSpiceLevel = ["Mild", "Medium", "Spicy", "Extra Spicy"].includes(spice); // Define valid spice levels
1855
- if (isSpiceLevel) {
1856
- checkboxes.forEach(checkbox => {
1857
- const checkboxName = checkbox.getAttribute('data-name').trim();
1858
- const checkboxGroup = checkbox.getAttribute('data-group');
1859
- if ((checkboxGroup === "Select Spice Level" || checkboxGroup === "Choose Spice Level") &&
1860
- checkboxName === spice && categorySelection[checkboxGroup] === null) {
1861
- console.log(`Pre-selecting highest-count spice level: ${checkboxName}`);
1862
- checkbox.checked = true;
1863
- categorySelection[checkboxGroup] = checkboxName;
1864
- }
1865
- });
1866
- if (categorySelection["Select Spice Level"] || categorySelection["Choose Spice Level"]) break; // Stop after selecting the first spice
1867
- }
1868
- }
1869
- // Second pass: Select other non-spice add-ons (e.g., Raita/Sides)
1870
- checkboxes.forEach(checkbox => {
1871
- const checkboxName = checkbox.getAttribute('data-name').trim();
1872
- const checkboxGroup = checkbox.getAttribute('data-group');
1873
- if (checkboxGroup === "Raita/Sides" && window.most_common_addons.includes(checkboxName)) {
1874
- console.log(`Pre-selecting add-on: ${checkboxName}`);
1875
- checkbox.checked = true;
1876
- categorySelection["Raita/Sides"].push(checkboxName);
1877
- }
1878
- });
1879
- }
1880
  })
1881
  .catch(err => {
1882
  console.error('Error fetching add-ons:', err);
@@ -1889,7 +1628,7 @@
1889
  isProcessingRequest = true;
1890
  const modalSectionEl = document.getElementById('modal-section');
1891
  const section = modalSectionEl.getAttribute('data-section');
1892
- const selectedCategory = modalSectionEl.getAttribute('data-category');
1893
  const itemName = document.getElementById('modal-name').innerText;
1894
  const itemPrice = parseFloat(document.getElementById('modal-price').innerText.replace('$', '')) || 0;
1895
  const itemImage = document.getElementById('modal-img').src;
@@ -1938,7 +1677,7 @@
1938
  modal.hide();
1939
  }
1940
  })
1941
- .catch(err => {
1942
  console.error('Error adding item to cart:', err);
1943
  const cart = addToCartLocalStorage(cartPayload);
1944
  updateCartUI(cart);
@@ -1949,163 +1688,302 @@
1949
  isProcessingRequest = false;
1950
  });
1951
  }
1952
-
1953
- function handleToggle(toggleType) {
1954
- const vegToggle = document.getElementById('veg-toggle');
1955
- const customToggle = document.getElementById('category-CustomizedDish');
1956
- if (toggleType === 'veg') {
1957
- customToggle.checked = false;
1958
- } else if (toggleType === 'custom') {
1959
- vegToggle.checked = false;
 
 
 
 
1960
  }
1961
- document.getElementById('filter-form').submit();
1962
  }
1963
-
1964
- document.addEventListener('DOMContentLoaded', () => {
1965
- // Initialize cart UI
1966
- updateCartUI(getCartLocalStorage());
1967
-
1968
- // Avatar dropdown toggle
1969
- const avatarIcon = document.querySelector('.avatar-icon');
1970
- const dropdownMenu = document.querySelector('.dropdown-menu');
1971
- avatarIcon.addEventListener('click', () => {
1972
- dropdownMenu.style.display = dropdownMenu.style.display === 'block' ? 'none' : 'block';
1973
- });
1974
- document.addEventListener('click', (event) => {
1975
- if (!avatarIcon.contains(event.target) && !dropdownMenu.contains(event.target)) {
1976
- dropdownMenu.style.display = 'none';
1977
- }
1978
- });
1979
-
1980
- // Search bar functionality
1981
- const searchBar = document.getElementById('searchBar');
1982
- searchBar.addEventListener('keypress', (e) => {
1983
- if (e.key === 'Enter') {
1984
- const query = searchBar.value.trim();
1985
- if (query) {
1986
- window.location.href = `/search?query=${encodeURIComponent(query)}`;
1987
- }
1988
  }
1989
- });
1990
-
1991
- // Microphone functionality
1992
- const micIcon = document.getElementById('micIcon');
 
 
 
 
 
 
1993
  const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
1994
  if (SpeechRecognition) {
1995
- const recognition = new SpeechRecognition();
1996
  recognition.continuous = false;
1997
  recognition.interimResults = false;
1998
  recognition.lang = 'en-US';
1999
-
2000
- micIcon.addEventListener('click', () => {
2001
- micIcon.classList.add('active');
2002
- recognition.start();
2003
- });
2004
-
2005
- recognition.onresult = (event) => {
2006
- const transcript = event.results[0][0].transcript.trim();
2007
- searchBar.value = transcript;
2008
- micIcon.classList.remove('active');
2009
- if (transcript) {
2010
- window.location.href = `/search?query=${encodeURIComponent(transcript)}`;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2011
  }
2012
  };
2013
-
2014
- recognition.onerror = (event) => {
2015
  console.error('Speech recognition error:', event.error);
2016
- micIcon.classList.remove('active');
2017
- alert('Speech recognition failed. Please try again.');
 
 
 
 
 
 
2018
  };
2019
-
2020
- recognition.onend = () => {
2021
- micIcon.classList.remove('active');
 
 
 
 
2022
  };
2023
- } else {
2024
- micIcon.style.display = 'none'; // Hide mic if not supported
2025
  }
2026
-
2027
- // Quantity controls for modal
2028
- document.getElementById('increaseQuantity').addEventListener('click', () => {
 
 
 
 
 
 
 
 
 
 
 
2029
  const quantityInput = document.getElementById('quantityInput');
2030
- quantityInput.value = parseInt(quantityInput.value) + 1;
 
2031
  });
2032
-
2033
- document.getElementById('decreaseQuantity').addEventListener('click', () => {
2034
  const quantityInput = document.getElementById('quantityInput');
2035
- const currentQuantity = parseInt(quantityInput.value);
2036
- if (currentQuantity > 1) {
2037
- quantityInput.value = currentQuantity - 1;
2038
  }
2039
  });
2040
-
2041
- // Video lazy loading and visibility
2042
- const menuCards = document.querySelectorAll('.menu-card');
2043
- const observer = new IntersectionObserver((entries) => {
2044
- entries.forEach(entry => {
2045
- if (entry.isIntersecting) {
2046
- const card = entry.target;
2047
- card.classList.add('visible');
2048
- const video = card.querySelector('.menu-video');
2049
- if (video && !video.src) {
2050
- video.src = video.dataset.src;
2051
- video.classList.add('loaded');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2052
  }
2053
  }
2054
- });
2055
- }, { threshold: 0.1 });
2056
-
2057
- menuCards.forEach(card => observer.observe(card));
2058
-
2059
- // Toggle item details
2060
- document.querySelectorAll('.toggle-details').forEach(toggle => {
2061
- toggle.addEventListener('click', () => {
2062
- const itemName = toggle.getAttribute('data-item-name').replace(/\s+/g, '-');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2063
  const details = document.getElementById(`details-${itemName}`);
2064
- details.classList.toggle('show');
2065
- toggle.textContent = details.classList.contains('show') ? 'Hide Details' : 'Show Details';
 
 
2066
  });
2067
  });
2068
-
2069
- // Chatbot functionality for customized dish
2070
- const initialMessage = sessionStorage.getItem('chatInitialMessage') ||
2071
- 'Hello! I’m Chef Bot, here to help you create a customized dish. May I have your name, please?';
2072
- const chatMessages = document.getElementById('chatMessages');
2073
- chatMessages.innerHTML = `<div class="bot-message">${initialMessage}</div>`;
2074
-
2075
- // Load chat history from session storage
2076
- const chatHistory = JSON.parse(sessionStorage.getItem('chatHistory')) || [];
2077
- chatHistory.forEach(msg => {
2078
- const messageClass = msg.type === 'user' ? 'user-message' : 'bot-message';
2079
- chatMessages.innerHTML += `<div class="${messageClass}">${msg.content}</div>`;
2080
- });
2081
- chatMessages.scrollTop = chatMessages.scrollHeight;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2082
  });
2083
-
2084
- function sendMessage() {
2085
- const userInput = document.getElementById('userInput');
2086
- const message = userInput.value.trim();
2087
- if (!message) return;
2088
-
2089
- const chatMessages = document.getElementById('chatMessages');
2090
- chatMessages.innerHTML += `<div class="user-message">${message}</div>`;
2091
- userInput.value = '';
2092
-
2093
- // Save to chat history
2094
- let chatHistory = JSON.parse(sessionStorage.getItem('chatHistory')) || [];
2095
- chatHistory.push({ type: 'user', content: message });
2096
- sessionStorage.setItem('chatHistory', JSON.stringify(chatHistory));
2097
-
2098
- // Simulate bot response (replace with actual API call if needed)
2099
- setTimeout(() => {
2100
- const botResponse = `Got it! You said: "${message}". How can I assist you with your customized dish?`;
2101
- chatMessages.innerHTML += `<div class="bot-message">${botResponse}</div>`;
2102
- chatHistory.push({ type: 'bot', content: botResponse });
2103
- sessionStorage.setItem('chatHistory', JSON.stringify(chatHistory));
2104
- chatMessages.scrollTop = chatMessages.scrollHeight;
2105
- }, 1000);
2106
-
2107
- chatMessages.scrollTop = chatMessages.scrollHeight;
2108
- }
2109
  </script>
2110
  </body>
2111
  </html>
 
1
+ <!DOCTYPE688 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
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
8
  <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">
 
9
  <link rel="preload" href="/static/placeholder.mp4" as="video">
10
  {% for section, items in ordered_menu.items() %}
11
  {% for item in items[:1] %}
 
37
  transition: opacity 0.3s ease-in-out;
38
  box-shadow: 0 4px 8px rgba(0,0,0,0.1);
39
  }
 
40
  .menu-card.visible {
41
  opacity: 1;
42
  }
 
234
  .mic-icon.active {
235
  color: #007bff;
236
  }
 
237
  .addon-section {
238
  background-color: #fff;
239
  border-radius: 10px;
 
284
  background-color: #fff;
285
  position: relative;
286
  margin-left: 10px;
287
+ cursor: to;
288
  transition: all 0.2s ease;
289
  }
290
  .addon-section .form-check-input:checked {
 
351
  border-radius: 50%;
352
  animation: spin 1s linear infinite;
353
  }
 
354
  #softDrinkModal .modal-dialog {
355
  max-width: 400px;
356
  margin: 1.75rem auto;
 
490
  #softDrinkModal .modal-footer .quantity-controls-footer .btn:active {
491
  transform: scale(0.95);
492
  }
 
493
  #filter-form {
494
  display: flex;
495
  flex-direction: column;
496
+ align-items: center;
497
+ justify-content: center;
498
  margin-bottom: 20px;
499
  }
500
  .form-label {
 
542
  color: #333;
543
  cursor: pointer;
544
  }
545
+ #micModal .modal-dialog {
546
+ max-width: 300px;
547
+ margin: 1.75rem auto;
548
+ }
549
+ #micModal .modal-content {
550
+ border-radius: 12px;
551
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
552
+ background-color: #fff;
553
+ text-align: center;
554
+ }
555
+ #micModal .modal-header {
556
+ background: linear-gradient(45deg, #FFA07A, #FFB347);
557
+ border-top-left-radius: 12px;
558
+ border-top-right-radius: 12px;
559
+ padding: 12px 15px;
560
+ border-bottom: none;
561
+ }
562
+ #micModal .modal-title {
563
+ font-size: 1.3rem;
564
+ font-weight: 600;
565
+ color: #fff;
566
+ margin: 0 auto;
567
+ }
568
+ #micModal .modal-body {
569
+ padding: 20px;
570
+ display: flex;
571
+ flex-direction: column;
572
+ align-items: center;
573
+ gap: 15px;
574
+ min-height: 200px;
575
+ }
576
+ #micModal .modal-body i#mic-icon-animation {
577
+ font-size: 2.5rem;
578
+ color: #007bff;
579
+ animation: pulse 2s infinite;
580
+ }
581
+ #micModal .modal-body p#mic-status {
582
+ font-size: 1.1rem;
583
+ color: #333;
584
+ margin: 0;
585
+ transition: opacity 0.3s ease;
586
+ }
587
+ #micModal .modal-body #mic-item-details {
588
+ width: 100%;
589
+ text-align: center;
590
+ }
591
+ #micModal .modal-body #mic-item-image {
592
+ max-height: 100px;
593
+ width: 100%;
594
+ object-fit: cover;
595
+ border-radius: 8px;
596
+ margin-bottom: 10px;
597
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
598
+ transition: opacity 0.3s ease;
599
+ }
600
+ #micModal .modal-body #mic-item-name {
601
+ font-size: 1.2rem;
602
+ font-weight: 600;
603
+ color: #333333;
604
+ margin-bottom: 10px;
605
+ transition: opacity 0.3s ease;
606
+ }
607
+ #micModal .modal-body #mic-item-details.show {
608
+ animation: fadeIn 0.3s ease;
609
+ }
610
+ #micModal .modal-footer {
611
+ padding: 15px;
612
+ border-top: none;
613
+ justify-content: center;
614
+ }
615
+ #micModal .modal-footer .btn-secondary {
616
+ background-color: #6c757d;
617
+ border-color: #6c757d;
618
+ padding: 10px 20px;
619
+ font-size: 1rem;
620
+ border-radius: 8px;
621
+ }
622
+ #micModal .modal-footer .btn-secondary:hover {
623
+ background-color: #5a6268;
624
+ border-color: #5a6268;
625
+ }
626
+ .autocomplete-suggestions {
627
+ position: absolute;
628
+ background-color: #fff;
629
+ border: 1px solid #ccc;
630
+ border-radius: 4px;
631
+ max-height: 150px;
632
+ overflow-y: auto;
633
+ width: 100%;
634
+ z-index: 1000;
635
+ display: none;
636
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
637
+ }
638
+ .suggestion-item {
639
+ padding: 8px 12px;
640
+ cursor: pointer;
641
+ font-size: 0.9rem;
642
+ color: #333;
643
+ }
644
+ .suggestion-item:hover {
645
+ background-color: #f0f0f0;
646
+ }
647
  @keyframes checkmark {
648
  from { transform: scale(0); }
649
  to { transform: scale(1); }
 
660
  from { opacity: 0; transform: translateY(-20px); }
661
  to { opacity: 1; transform: translateY(0); }
662
  }
663
+ @keyframes pulse {
664
+ 0% { transform: scale(1); }
665
+ 50% { transform: scale(1.2); }
666
+ 100% { transform: scale(1); }
667
+ }
668
  .modal-header {
669
  padding: 10px 15px;
670
  }
 
875
  border-radius: 8px;
876
  font-weight: bold;
877
  font-size: 16px;
878
+ color: white;
879
  display: flex;
880
  align-items: center;
881
  justify-content: center;
 
884
  white-space: nowrap;
885
  }
886
  .bottom-action-bar .btn-order-history {
887
+ background-color: #FFA07A;
888
+ border-color: #FFA07A;
889
  }
890
  .bottom-action-bar .btn-order-history:hover {
891
+ background-color: #FF8C61;
892
+ border-color: #FF8C61;
893
  }
894
  .bottom-action-bar .btn-view-cart {
895
  background-color: #0FAA39;
 
911
  font-size: 12px;
912
  margin-left: 8px;
913
  }
 
914
  @media (max-width: 576px) {
915
  .fixed-top-bar {
916
  height: 60px;
 
1064
  font-size: 10px;
1065
  margin-left: 5px;
1066
  }
 
1067
  .addon-section {
1068
  margin-bottom: 10px;
1069
  }
 
1092
  margin-left: 6px;
1093
  font-size: 0.8rem;
1094
  }
 
1095
  #softDrinkModal .modal-dialog {
1096
  max-width: 90%;
1097
  }
 
1134
  padding: 10px;
1135
  }
1136
  #softDrinkModal .modal-footer .btn-primary {
1137
+ padding: 10px 25px;
1138
  font-size: 1rem;
1139
  }
1140
  #softDrinkModal .modal-footer .quantity-controls-footer .btn {
 
1143
  font-size: 1rem;
1144
  line-height: 28px;
1145
  }
 
1146
  #filter-form {
1147
  margin-bottom: 15px;
1148
  }
 
1168
  .toggle-container label {
1169
  font-size: 0.9rem;
1170
  }
1171
+ #micModal .modal-dialog {
1172
+ max-width: 90%;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1173
  }
1174
+ #micModal .modal-body i {
1175
+ font-size: 2rem;
1176
  }
1177
+ #micModal .modal-body p {
1178
+ font-size: 1rem;
1179
  }
1180
+ #micModal .modal-body img {
1181
+ max-height: 80px;
1182
+ margin-bottom: 8px;
1183
  }
1184
+ #micModal .modal-body h5 {
1185
+ font-size: 1rem;
1186
+ margin-bottom: 8px;
1187
  }
1188
+ #micModal .modal-footer .btn-secondary {
 
1189
  padding: 8px 15px;
1190
+ font-size: 0.9rem;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1191
  }
1192
  }
1193
  </style>
 
1211
  <i class="bi bi-mic mic-icon" id="micIcon"></i>
1212
  </div>
1213
  </div>
 
1214
  <form method="get" action="/menu" class="text-center mb-4" id="filter-form">
1215
  <label class="form-label fw-bold">Filters:</label>
1216
  <div class="toggle-container">
1217
+ <input type="checkbox" id="veg-toggle" name="veg" {% if selected_category == "Veg" %}checked{% endif %} class="custom-toggle" onchange="handleToggle('veg')" aria-label="Toggle Vegetarian filter">
 
 
 
 
1218
  <label for="veg-toggle">Veg</label>
1219
  </div>
1220
  <div class="toggle-container">
1221
+ <input type="radio" id="category-CustomizedDish" name="category" value="Customized Dish" {% if selected_category == "Customized Dish" %}checked{% endif %} class="custom-toggle" onchange="handleToggle('custom')" aria-label="Toggle Customized Dish filter">
 
 
 
 
1222
  <label for="category-CustomizedDish">Customized Dish</label>
1223
  </div>
1224
  </form>
 
1225
  <div class="container mt-4">
1226
  {% if selected_category == "Customized Dish" %}
1227
  <div id="custom-dish-form" class="mt-4">
1228
+ <h3>Create Your Custom Dish</h3>
1229
+ <form method="POST" action="/customdish/generate_custom_dish">
1230
+ <div class="mb-3">
1231
+ <label for="custom-dish-name" class="form-label">Dish Name</label>
1232
+ <input type="text" class="form-control" id="custom-dish-name" name="name" required>
1233
+ </div>
1234
+ <div class="mb-3 position-relative">
1235
+ <label for="custom-dish-description" class="form-label">Dish Description</label>
1236
+ <textarea class="form-control" id="custom-dish-description" name="description" required></textarea>
1237
+ <div id="descriptionSuggestions" class="autocomplete-suggestions"></div>
1238
+ </div>
1239
+ <button type="submit" class="btn btn-primary">Submit Custom Dish</button>
1240
+ </form>
1241
  </div>
1242
  {% else %}
1243
  {% if ordered_menu.items()|length == 0 %}
 
1249
  {% for item in items %}
1250
  <div class="col-md-6 mb-4">
1251
  <div class="card menu-card" data-item-name="{{ item.Name | default('Unnamed Item') }}" data-item-section="{{ item.Section__c | default(section) }}">
1252
+ <video class="card-img-top menu-video" muted loop preload="auto" data-src="{{ item.Video1__c | default('/static/placeholder.mp4') }}" poster="{{ item.Image1__c | default('/static/placeholder.jpg') }}" width="350" height="200" onmouseover="this.play()" onmouseout="this.pause(); this.currentTime = 0;" onerror="this.poster='/static/placeholder.jpg';">
 
 
 
 
 
 
 
 
 
 
 
1253
  <source src="{{ item.Video1__c | default('/static/placeholder.mp4') }}" type="video/mp4">
1254
  Your browser does not support the video tag.
1255
  </video>
 
1260
  <p class="card-text price">${{ item.Price__c | default('0.00') }}</p>
1261
  </div>
1262
  <div class="d-flex flex-column align-items-center justify-content-center">
1263
+ <div class="button-container" data-item-name="{{ item.Name | default('Unnamed Item') }}" data-item-price="{{ item.Price__c | default('0.00') }}" data-item-image="{{ item.Image1__c | default('/static/placeholder.jpg') }}" data-item-section="{{ item.Section__c | default(section) }}" data-item-category="{{ selected_category }}" data-item-description="{{ item.Description__c | default('No description') }}" data-item-image2="{{ item.Image2__c | default(item.Image1__c) }}">
 
 
 
 
 
 
 
1264
  {% if item.Section__c == 'Soft Drinks' %}
1265
  <button class="btn btn-primary add-to-cart-btn" onclick="showSoftDrinkModal(this)">ADD</button>
1266
  {% else %}
1267
+ <button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#itemModal" onclick="showItemDetails('{{ item.Name | default('Unnamed Item') }}', '{{ item.Price__c | default('0.00') }}', '{{ item.Image2__c | default(item.Image1__c) }}', '{{ item.Description__c | default('No description') }}', '{{ item.Section__c | default(section) }}', '{{ selected_category }}')">ADD</button>
 
 
 
 
 
1268
  {% if item.Section__c != 'Apetizer' and item.Section__c != 'Customized dish' %}
1269
  <span class="customisable-text">Customisable</span>
1270
  {% endif %}
 
1294
  {% endif %}
1295
  {% endif %}
1296
  </div>
 
1297
  <div class="bottom-action-bar">
1298
  <a href="{{ url_for('orderhistory.order_history') }}" class="btn btn-order-history">
1299
  <i class="bi bi-clock-history"></i> Order History
 
1303
  <span id="cart-item-count" class="cart-icon-badge" style="display: none;">0</span>
1304
  </a>
1305
  </div>
 
 
1306
  <div class="modal fade" id="itemModal" tabindex="-1" aria-labelledby="itemModalLabel" aria-hidden="true">
1307
  <div class="modal-dialog modal-dialog-centered">
1308
  <div class="modal-content">
1309
+ <div class="modal-header">
1310
  <h5 class="modal-title" id="itemModalLabel">Item Details</h5>
1311
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
1312
  </div>
 
1336
  </div>
1337
  </div>
1338
  </div>
 
 
1339
  <div class="modal fade" id="softDrinkModal" tabindex="-1" aria-labelledby="softDrinkModalLabel" aria-hidden="true">
1340
  <div class="modal-dialog modal-dialog-centered">
1341
  <div class="modal-content">
 
1365
  </div>
1366
  </div>
1367
  </div>
1368
+ <div class="modal fade" id="micModal" tabindex="-1" aria-labelledby="micModalLabel" aria-hidden="true">
1369
+ <div class="modal-dialog modal-dialog-centered">
1370
+ <div class="modal-content">
1371
+ <div class="modal-header">
1372
+ <h5 class="modal-title" id="micModalLabel">Speak Now</h5>
1373
+ </div>
1374
+ <div class="modal-body">
1375
+ <i class="bi bi-mic" id="mic-icon-animation"></i>
1376
+ <p id="mic-status" class="mt-3">Say the name of a menu item...</p>
1377
+ <div id="mic-item-details" style="display: none;">
1378
+ <img id="mic-item-image" class="img-fluid rounded mb-3 d-block mx-auto" alt="Spoken Item Image">
1379
+ <h5 id="mic-item-name" class="fw-bold text-center"></h5>
1380
+ </div>
1381
+ </div>
1382
+ <div class="modal-footer">
1383
+ <button type="button" class="btn btn-secondary" id="stopMicBtn" onclick="stopSpeechRecognition()">Stop</button>
1384
+ </div>
1385
+ </div>
1386
+ </div>
1387
+ </div>
1388
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
1389
  <script>
1390
  let isProcessingRequest = false;
1391
  let currentSoftDrinkButton = null;
1392
  let baseItemPrice = 0;
1393
+ let recognition = null;
1394
  const menuItems = [
1395
  {% for section, items in ordered_menu.items() %}
1396
  {% for item in items %}
1397
  {
1398
  name: "{{ item.Name | default('Unnamed Item') }}",
1399
+ section: "{{ item.Section__c | default(section) }}",
1400
+ image: "{{ item.Image1__c | default('/static/placeholder.jpg') }}"
1401
  },
1402
  {% endfor %}
1403
  {% endfor %}
 
1425
  JSON.stringify(item.addons) === JSON.stringify(payload.addons)
1426
  );
1427
  if (existingItem) {
1428
+ existingItem.quantity += payload.quantity;
1429
  } else {
1430
  cart.push(payload);
1431
  }
 
1452
  function getCartLocalStorage() {
1453
  return JSON.parse(localStorage.getItem('cart')) || [];
1454
  }
 
 
 
 
 
 
 
1455
  function updateModalPrice() {
1456
  const selectedAddOns = Array.from(
1457
  document.querySelectorAll('#addons-list input[type="checkbox"]:checked')
 
1472
  const itemName = buttonContainer.getAttribute('data-item-name');
1473
  const itemPrice = buttonContainer.getAttribute('data-item-price');
1474
  const itemImage = buttonContainer.getAttribute('data-item-image');
 
1475
  document.getElementById('soft-drink-name').textContent = itemName;
1476
+ document.getElementById('soft-drink-price').textContent = `$${parseFloat(itemPrice).toFixed(2)}`;
1477
  document.getElementById('soft-drink-quantity').value = '1';
1478
  document.getElementById('soft-drink-image').src = itemImage || '/static/placeholder.jpg';
 
1479
  const modal = new bootstrap.Modal(document.getElementById('softDrinkModal'));
1480
  modal.show();
1481
  }
1482
  function addSoftDrinkToCart() {
1483
  if (!currentSoftDrinkButton) return;
 
1484
  const buttonContainer = currentSoftDrinkButton.closest('.button-container');
1485
  const quantity = parseInt(document.getElementById('soft-drink-quantity').value) || 1;
 
1486
  const itemName = buttonContainer.getAttribute('data-item-name');
1487
  const itemPrice = parseFloat(buttonContainer.getAttribute('data-item-price'));
1488
  const itemImage = buttonContainer.getAttribute('data-item-image');
1489
  const section = buttonContainer.getAttribute('data-item-section');
1490
  const selectedCategory = buttonContainer.getAttribute('data-item-category');
 
1491
  const cartPayload = {
1492
  itemName: itemName,
1493
  itemPrice: itemPrice,
 
1498
  instructions: '',
1499
  quantity: quantity
1500
  };
 
1501
  fetch('/cart/add', {
1502
  method: 'POST',
1503
  headers: {
 
1542
  cartItemCount.style.display = totalQuantity > 0 ? 'inline-flex' : 'none';
1543
  }
1544
  }
 
 
 
1545
  function showItemDetails(name, price, image, description, section, selectedCategory) {
1546
  document.getElementById('modal-name').innerText = name;
1547
  baseItemPrice = parseFloat(price) || 0;
 
1616
  }
1617
  });
1618
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1619
  })
1620
  .catch(err => {
1621
  console.error('Error fetching add-ons:', err);
 
1628
  isProcessingRequest = true;
1629
  const modalSectionEl = document.getElementById('modal-section');
1630
  const section = modalSectionEl.getAttribute('data-section');
1631
+ const selectedartifactCategory = modalSectionEl.getAttribute('data-category');
1632
  const itemName = document.getElementById('modal-name').innerText;
1633
  const itemPrice = parseFloat(document.getElementById('modal-price').innerText.replace('$', '')) || 0;
1634
  const itemImage = document.getElementById('modal-img').src;
 
1677
  modal.hide();
1678
  }
1679
  })
1680
+ .catch(err => {
1681
  console.error('Error adding item to cart:', err);
1682
  const cart = addToCartLocalStorage(cartPayload);
1683
  updateCartUI(cart);
 
1688
  isProcessingRequest = false;
1689
  });
1690
  }
1691
+ function handleToggle(source) {
1692
+ const form = document.getElementById("filter-form");
1693
+ const veg = document.getElementById("veg-toggle");
1694
+ const custom = document.getElementById("category-CustomizedDish");
1695
+ if (source === 'veg') {
1696
+ if (veg.checked) {
1697
+ custom.checked = false;
1698
+ }
1699
+ } else if (source === 'custom') {
1700
+ if (custom.checked) {
1701
+ veg.checked = false;
1702
+ }
1703
  }
1704
+ form.submit();
1705
  }
1706
+ function stopSpeechRecognition() {
1707
+ if (recognition) {
1708
+ recognition.stop();
1709
+ document.getElementById('micIcon').classList.remove('active');
1710
+ const micModal = bootstrap.Modal.getInstance(document.getElementById('micModal'));
1711
+ if (micModal) {
1712
+ micModal.hide();
1713
+ resetMicModal();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1714
  }
1715
+ }
1716
+ }
1717
+ function resetMicModal() {
1718
+ document.getElementById('mic-status').textContent = 'Say the name of a menu item...';
1719
+ document.getElementById('mic-status').style.display = 'block';
1720
+ document.getElementById('mic-item-details').style.display = 'none';
1721
+ document.getElementById('mic-item-image').src = '';
1722
+ document.getElementById('mic-item-name').textContent = '';
1723
+ }
1724
+ document.addEventListener('DOMContentLoaded', function () {
1725
  const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
1726
  if (SpeechRecognition) {
1727
+ recognition = new SpeechRecognition();
1728
  recognition.continuous = false;
1729
  recognition.interimResults = false;
1730
  recognition.lang = 'en-US';
1731
+ recognition.onstart = function () {
1732
+ document.getElementById('micIcon').classList.add('active');
1733
+ document.getElementById('mic-status').textContent = 'Listening...';
1734
+ document.getElementById('mic-item-details').style.display = 'none';
1735
+ const micModal = new bootstrap.Modal(document.getElementById('micModal'));
1736
+ micModal.show();
1737
+ };
1738
+ recognition.onresult = function (event) {
1739
+ const transcript = event.results[0][0].transcript.trim().toLowerCase();
1740
+ document.getElementById('searchBar').value = transcript;
1741
+ const menuCards = document.querySelectorAll('.menu-card');
1742
+ let matchedItem = null;
1743
+ let matchedCard = null;
1744
+ menuCards.forEach(card => {
1745
+ const itemName = card.getAttribute('data-item-name').toLowerCase();
1746
+ const itemSection = card.getAttribute('data-item-section');
1747
+ if (itemName.includes(transcript) || transcript.includes(itemName)) {
1748
+ matchedItem = menuItems.find(item =>
1749
+ item.name.toLowerCase() === card.getAttribute('data-item-name').toLowerCase() &&
1750
+ item.section === itemSection
1751
+ );
1752
+ matchedCard = card;
1753
+ }
1754
+ });
1755
+ const micModal = bootstrap.Modal.getInstance(document.getElementById('micModal'));
1756
+ if (matchedItem && matchedCard) {
1757
+ document.getElementById('mic-status').style.display = 'none';
1758
+ const micItemDetails = document.getElementById('mic-item-details');
1759
+ const micItemImage = document.getElementById('mic-item-image');
1760
+ const micItemName = document.getElementById('mic-item-name');
1761
+ micItemImage.src = matchedItem.image || '/static/placeholder.jpg';
1762
+ micItemName.textContent = matchedItem.name;
1763
+ micItemDetails.style.display = 'block';
1764
+ matchedCard.classList.add('highlighted');
1765
+ matchedCard.scrollIntoView({ behavior: 'smooth', block: 'center' });
1766
+ const toggleLink = matchedCard.querySelector('.toggle-details');
1767
+ if (toggleLink) {
1768
+ toggleLink.click();
1769
+ }
1770
+ const buttonContainer = matchedCard.querySelector('.button-container');
1771
+ if (buttonContainer) {
1772
+ const section = buttonContainer.getAttribute('data-item-section');
1773
+ setTimeout(() => {
1774
+ micModal.hide();
1775
+ if (section === 'Soft Drinks') {
1776
+ showSoftDrinkModal(buttonContainer.querySelector('.add-to-cart-btn'));
1777
+ } else {
1778
+ const name = buttonContainer.getAttribute('data-item-name');
1779
+ const price = buttonContainer.getAttribute('data-item-price');
1780
+ const image = buttonContainer.getAttribute('data-item-image2');
1781
+ const description = buttonContainer.getAttribute('data-item-description');
1782
+ const category = buttonContainer.getAttribute('data-item-category');
1783
+ showItemDetails(name, price, image, description, section, category);
1784
+ const itemModal = new bootstrap.Modal(document.getElementById('itemModal'));
1785
+ itemModal.show();
1786
+ }
1787
+ resetMicModal();
1788
+ }, 1500);
1789
+ }
1790
+ } else {
1791
+ document.getElementById('mic-status').textContent = 'No matching item found. Try again...';
1792
+ setTimeout(() => {
1793
+ micModal.hide();
1794
+ resetMicModal();
1795
+ alert('No matching menu item found for: ' + transcript);
1796
+ }, 1500);
1797
  }
1798
  };
1799
+ recognition.onerror = function (event) {
 
1800
  console.error('Speech recognition error:', event.error);
1801
+ document.getElementById('mic-status').textContent = 'Error occurred. Please try again.';
1802
+ document.getElementById('micIcon').classList.remove('active');
1803
+ const micModal = bootstrap.Modal.getInstance(document.getElementById('micModal'));
1804
+ setTimeout(() => {
1805
+ micModal.hide();
1806
+ resetMicModal();
1807
+ alert('Speech recognition failed: ' + event.error);
1808
+ }, 1500);
1809
  };
1810
+ recognition.onend = function () {
1811
+ document.getElementById('micIcon').classList.remove('active');
1812
+ const micModal = bootstrap.Modal.getInstance(document.getElementById('micModal'));
1813
+ if (micModal && !matchedItem) {
1814
+ micModal.hide();
1815
+ resetMicModal();
1816
+ }
1817
  };
 
 
1818
  }
1819
+ document.getElementById('micIcon').addEventListener('click', function () {
1820
+ if (!recognition) {
1821
+ alert('Speech recognition is not supported in this browser.');
1822
+ return;
1823
+ }
1824
+ if (this.classList.contains('active')) {
1825
+ stopSpeechRecognition();
1826
+ } else {
1827
+ resetMicModal();
1828
+ this.classList.add('active');
1829
+ recognition.start();
1830
+ }
1831
+ });
1832
+ document.getElementById('increaseQuantity').addEventListener('click', function () {
1833
  const quantityInput = document.getElementById('quantityInput');
1834
+ let quantity = parseInt(quantityInput.value) || 1;
1835
+ quantityInput.value = quantity + 1;
1836
  });
1837
+ document.getElementById('decreaseQuantity').addEventListener('click', function () {
 
1838
  const quantityInput = document.getElementById('quantityInput');
1839
+ let quantity = parseInt(quantityInput.value) || 1;
1840
+ if (quantity > 1) {
1841
+ quantityInput.value = quantity - 1;
1842
  }
1843
  });
1844
+ const avatarContainer = document.querySelector('.avatar-dropdown-container');
1845
+ const dropdownMenu = document.querySelector('.dropdown-menu');
1846
+ avatarContainer.addEventListener('click', function (event) {
1847
+ event.stopPropagation();
1848
+ dropdownMenu.style.display = dropdownMenu.style.display === 'block' ? 'none' : 'block';
1849
+ });
1850
+ document.addEventListener('click', function (event) {
1851
+ if (!avatarContainer.contains(event.target)) {
1852
+ dropdownMenu.style.display = 'none';
1853
+ }
1854
+ });
1855
+ const dropdownItems = document.querySelectorAll('.dropdown-item');
1856
+ dropdownItems.forEach(item => {
1857
+ item.addEventListener('click', function () {
1858
+ dropdownMenu.style.display = 'none';
1859
+ });
1860
+ });
1861
+ const searchBar = document.getElementById('searchBar');
1862
+ searchBar.addEventListener('click', function () {
1863
+ window.location.href = '/search';
1864
+ });
1865
+ const selectedItem = localStorage.getItem('selectedItem');
1866
+ if (selectedItem) {
1867
+ try {
1868
+ const { name, section } = JSON.parse(selectedItem);
1869
+ const menuCards = document.querySelectorAll('.menu-card');
1870
+ let targetCard = null;
1871
+ let buttonContainer = null;
1872
+ menuCards.forEach(card => {
1873
+ const itemName = card.getAttribute('data-item-name');
1874
+ const itemSection = card.getAttribute('data-item-section');
1875
+ if (itemName === name && itemSection === section) {
1876
+ targetCard = card;
1877
+ buttonContainer = card.querySelector('.button-container');
1878
+ card.classList.add('highlighted');
1879
+ card.scrollIntoView({ behavior: 'smooth', block: 'center' });
1880
+ const toggleLink = card.querySelector('.toggle-details');
1881
+ if (toggleLink) {
1882
+ toggleLink.click();
1883
+ }
1884
+ buttonContainer = card.querySelector('.button-container');
1885
+ }
1886
+ });
1887
+ if (buttonContainer) {
1888
+ const section = buttonContainer.getAttribute('data-item-section');
1889
+ if (section === 'Soft Drinks') {
1890
+ showSoftDrinkModal(buttonContainer.querySelector('.add-to-cart-btn'));
1891
+ } else {
1892
+ const name = buttonContainer.getAttribute('data-item-name');
1893
+ const price = buttonContainer.getAttribute('data-item-price');
1894
+ const image = buttonContainer.getAttribute('data-item-image2');
1895
+ const description = buttonContainer.getAttribute('data-item-description');
1896
+ const category = buttonContainer.getAttribute('data-item-category');
1897
+ showItemDetails(name, price, image, description, section, category);
1898
+ const itemModal = new bootstrap.Modal(document.getElementById('itemModal'));
1899
+ itemModal.show();
1900
  }
1901
  }
1902
+ localStorage.removeItem('selectedItem');
1903
+ } catch (error) {
1904
+ console.error('Error parsing selectedItem from localStorage:', error);
1905
+ localStorage.removeItem('selectedItem');
1906
+ }
1907
+ }
1908
+ const menuVideos = document.querySelectorAll('.menu-video');
1909
+ menuVideos.forEach(video => {
1910
+ const src = video.getAttribute('data-src');
1911
+ if (src) {
1912
+ video.src = src;
1913
+ video.load();
1914
+ video.addEventListener('loadeddata', () => {
1915
+ video.classList.add('loaded');
1916
+ });
1917
+ video.addEventListener('error', () => {
1918
+ console.error('Error loading video:', src);
1919
+ video.poster = video.poster || '/static/placeholder.jpg';
1920
+ });
1921
+ }
1922
+ });
1923
+ const menuCards = document.querySelectorAll('.menu-card');
1924
+ menuCards.forEach((card, index) => {
1925
+ setTimeout(() => {
1926
+ card.classList.add('visible');
1927
+ }, index * 100);
1928
+ });
1929
+ const toggleLinks = document.querySelectorAll('.toggle-details');
1930
+ toggleLinks.forEach(link => {
1931
+ link.addEventListener('click', function () {
1932
+ const itemName = this.getAttribute('data-item-name').replace(/\s+/g, '-');
1933
  const details = document.getElementById(`details-${itemName}`);
1934
+ if (details) {
1935
+ details.classList.toggle('show');
1936
+ this.textContent = details.classList.contains('show') ? 'Hide Details' : 'Show Details';
1937
+ }
1938
  });
1939
  });
1940
+ function updateDescriptionSuggestions(input) {
1941
+ const suggestionsContainer = document.getElementById('descriptionSuggestions');
1942
+ suggestionsContainer.innerHTML = '';
1943
+ if (input.length === 0) {
1944
+ suggestionsContainer.style.display = 'none';
1945
+ return;
1946
+ }
1947
+ const filteredIngredients = ingredientsList.filter(ingredient =>
1948
+ ingredient.toLowerCase().includes(input.toLowerCase())
1949
+ );
1950
+ if (filteredIngredients.length === 0) {
1951
+ suggestionsContainer.style.display = 'none';
1952
+ return;
1953
+ }
1954
+ filteredIngredients.forEach(ingredient => {
1955
+ const suggestion = document.createElement('div');
1956
+ suggestion.classList.add('suggestion-item');
1957
+ suggestion.textContent = ingredient;
1958
+ suggestion.addEventListener('click', () => {
1959
+ const textarea = document.getElementById('custom-dish-description');
1960
+ const currentText = textarea.value;
1961
+ const lastCommaIndex = currentText.lastIndexOf(',');
1962
+ const baseText = lastCommaIndex === -1 ? '' : currentText.substring(0, lastCommaIndex + 1);
1963
+ textarea.value = baseText ? `${baseText} ${ingredient}` : ingredient;
1964
+ suggestionsContainer.style.display = 'none';
1965
+ });
1966
+ suggestionsContainer.appendChild(suggestion);
1967
+ });
1968
+ suggestionsContainer.style.display = 'block';
1969
+ }
1970
+ const descriptionInput = document.getElementById('custom-dish-description');
1971
+ if (descriptionInput) {
1972
+ descriptionInput.addEventListener('input', function () {
1973
+ const input = this.value;
1974
+ const lastCommaIndex = input.lastIndexOf(',');
1975
+ const currentWord = input.substring(lastCommaIndex + 1).trim();
1976
+ updateDescriptionSuggestions(currentWord);
1977
+ });
1978
+ document.addEventListener('click', function (event) {
1979
+ const suggestionsContainer = document.getElementById('descriptionSuggestions');
1980
+ if (!descriptionInput.contains(event.target) && !suggestionsContainer.contains(event.target)) {
1981
+ suggestionsContainer.style.display = 'none';
1982
+ }
1983
+ });
1984
+ }
1985
+ updateCartUI(getCartLocalStorage());
1986
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1987
  </script>
1988
  </body>
1989
  </html>