lokesh341 commited on
Commit
b4c3319
·
verified ·
1 Parent(s): 1e67183

Update static/script.js

Browse files
Files changed (1) hide show
  1. static/script.js +629 -0
static/script.js CHANGED
@@ -0,0 +1,629 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ let conversation = [
2
+ { role: 'bot', message: 'Hello! I’m Chef Bot, your culinary assistant! What’s your name?' }
3
+ ];
4
+ let selectedItems = [];
5
+ let selectionBoxVisible = false;
6
+ const searchCache = new Map();
7
+ const MAX_RETRIES = 3;
8
+
9
+ function addMessage(role, message, isDebug = false) {
10
+ const chatMessages = document.getElementById('chatMessages');
11
+ if (!chatMessages) {
12
+ console.error('Chat messages container not found!');
13
+ return;
14
+ }
15
+ const messageDiv = document.createElement('div');
16
+ messageDiv.className = role === 'bot' ? 'bot-message' : 'user-message';
17
+ messageDiv.textContent = message;
18
+ chatMessages.appendChild(messageDiv);
19
+ chatMessages.scrollTop = chatMessages.scrollHeight;
20
+ if (isDebug) console.log(`[${role.toUpperCase()}] ${message}`);
21
+ }
22
+
23
+ function showToast(message) {
24
+ const toast = document.createElement('div');
25
+ toast.className = 'toast';
26
+ toast.textContent = message;
27
+ document.body.appendChild(toast);
28
+ setTimeout(() => toast.remove(), 3000);
29
+ }
30
+
31
+ function sendMessage() {
32
+ const userInput = document.getElementById('userInput');
33
+ if (!userInput) {
34
+ console.error('User input field not found!');
35
+ return;
36
+ }
37
+ const message = userInput.value.trim();
38
+ if (message) {
39
+ addMessage('user', message, true);
40
+ conversation.push({ role: 'user', message: message });
41
+ selectionBoxVisible = true;
42
+ handleResponse(message);
43
+ showToast(`Sent: "${message}"`);
44
+ } else {
45
+ addMessage('bot', 'Please type a dish or preference! 😄');
46
+ showToast('Input is empty!');
47
+ }
48
+ userInput.value = '';
49
+ updateSelectionBox();
50
+ }
51
+
52
+ function handleResponse(userInput) {
53
+ const lowerInput = userInput.toLowerCase();
54
+ let botResponse = '';
55
+
56
+ if (conversation.length === 2) {
57
+ botResponse = `Hi ${userInput}! 🍳 Search for a dish or choose a preference below!`;
58
+ displayOptions([
59
+ { text: 'Vegetarian', class: 'green' },
60
+ { text: 'Non-Vegetarian', class: 'red' },
61
+ { text: 'Both', class: 'gray' }
62
+ ]);
63
+ addMessage('bot', botResponse);
64
+ } else if (lowerInput === 'vegetarian' || lowerInput === 'non-vegetarian' || lowerInput === 'both') {
65
+ botResponse = `Fetching ${lowerInput} dishes...`;
66
+ addMessage('bot', botResponse);
67
+ fetchMenuItems(lowerInput);
68
+ } else {
69
+ botResponse = `Looking for "${userInput}"...`;
70
+ addMessage('bot', botResponse);
71
+ fetchMenuItems(null, userInput);
72
+ }
73
+ }
74
+
75
+ function debounce(func, wait) {
76
+ let timeout;
77
+ return function (...args) {
78
+ clearTimeout(timeout);
79
+ timeout = setTimeout(() => func.apply(this, args), wait);
80
+ };
81
+ }
82
+
83
+ function updateSelectionBox() {
84
+ const chatMessages = document.getElementById('chatMessages');
85
+ if (!chatMessages) return;
86
+
87
+ const existingBox = document.querySelector('.selection-box');
88
+ if (existingBox) existingBox.remove();
89
+
90
+ if (!selectionBoxVisible && selectedItems.length === 0) return;
91
+
92
+ const selectionBox = document.createElement('div');
93
+ selectionBox.className = 'selection-box';
94
+
95
+ const clearAllButton = document.createElement('button');
96
+ clearAllButton.textContent = 'Clear All';
97
+ clearAllButton.className = 'remove-button';
98
+ clearAllButton.setAttribute('aria-label', 'Clear all selected items');
99
+ clearAllButton.tabIndex = 0;
100
+ clearAllButton.onclick = () => {
101
+ selectedItems = [];
102
+ addMessage('bot', 'Cleared all items.');
103
+ showToast('All items cleared!');
104
+ updateSelectionBox();
105
+ };
106
+ selectionBox.appendChild(clearAllButton);
107
+
108
+ const vegButton = document.createElement('button');
109
+ vegButton.textContent = 'Veg';
110
+ vegButton.className = 'option-button green';
111
+ vegButton.setAttribute('aria-label', 'Select vegetarian dishes');
112
+ vegButton.tabIndex = 0;
113
+ vegButton.onclick = () => {
114
+ addMessage('user', 'Vegetarian', true);
115
+ conversation.push({ role: 'user', message: 'Vegetarian' });
116
+ handleResponse('vegetarian');
117
+ showToast('Selected Vegetarian');
118
+ };
119
+ selectionBox.appendChild(vegButton);
120
+
121
+ const nonVegButton = document.createElement('button');
122
+ nonVegButton.textContent = 'Non-Veg';
123
+ nonVegButton.className = 'option-button red';
124
+ nonVegButton.setAttribute('aria-label', 'Select non-vegetarian dishes');
125
+ nonVegButton.tabIndex = 0;
126
+ nonVegButton.onclick = () => {
127
+ addMessage('user', 'Non-Vegetarian', true);
128
+ conversation.push({ role: 'user', message: 'Non-Vegetarian' });
129
+ handleResponse('non-vegetarian');
130
+ showToast('Selected Non-Vegetarian');
131
+ };
132
+ selectionBox.appendChild(nonVegButton);
133
+
134
+ const bothButton = document.createElement('button');
135
+ bothButton.textContent = 'Both';
136
+ bothButton.className = 'option-button gray';
137
+ bothButton.setAttribute('aria-label', 'Select both vegetarian and non-vegetarian dishes');
138
+ bothButton.tabIndex = 0;
139
+ bothButton.onclick = () => {
140
+ addMessage('user', 'Both', true);
141
+ conversation.push({ role: 'user', message: 'Both' });
142
+ handleResponse('both');
143
+ showToast('Selected Both');
144
+ };
145
+ selectionBox.appendChild(bothButton);
146
+
147
+ const label = document.createElement('span');
148
+ label.textContent = 'Selected:';
149
+ selectionBox.appendChild(label);
150
+
151
+ selectedItems.forEach((item, index) => {
152
+ const itemContainer = document.createElement('div');
153
+ itemContainer.className = 'selected-item';
154
+ itemContainer.dataset.hidden = item.source === 'Sector_Detail__c' ? 'true' : 'false';
155
+
156
+ const img = document.createElement('img');
157
+ img.src = item.image_url || 'https://via.placeholder.com/30?text=Item';
158
+ img.alt = item.name;
159
+ img.className = 'selected-item-image';
160
+ itemContainer.appendChild(img);
161
+
162
+ const contentDiv = document.createElement('div');
163
+ contentDiv.className = 'selected-item-content';
164
+
165
+ const itemSpan = document.createElement('span');
166
+ itemSpan.textContent = `${item.name} (Qty: ${item.quantity || 1})`;
167
+ contentDiv.appendChild(itemSpan);
168
+
169
+ const quantityDiv = document.createElement('div');
170
+ quantityDiv.className = 'quantity-controls';
171
+ const decButton = document.createElement('button');
172
+ decButton.textContent = '-';
173
+ decButton.className = 'quantity-button';
174
+ decButton.setAttribute('aria-label', `Decrease quantity of ${item.name}`);
175
+ decButton.tabIndex = 0;
176
+ decButton.onclick = () => {
177
+ if (item.quantity > 1) {
178
+ item.quantity -= 1;
179
+ updateSelectionBox();
180
+ showToast(`Decreased quantity of ${item.name}`);
181
+ }
182
+ };
183
+ quantityDiv.appendChild(decButton);
184
+
185
+ const incButton = document.createElement('button');
186
+ incButton.textContent = '+';
187
+ incButton.className = 'quantity-button';
188
+ incButton.setAttribute('aria-label', `Increase quantity of ${item.name}`);
189
+ incButton.tabIndex = 0;
190
+ incButton.onclick = () => {
191
+ item.quantity += 1;
192
+ updateSelectionBox();
193
+ showToast(`Increased quantity of ${item.name}`);
194
+ };
195
+ quantityDiv.appendChild(incButton);
196
+ contentDiv.appendChild(quantityDiv);
197
+
198
+ if (item.source === 'Sector_Detail__c') {
199
+ const showButton = document.createElement('button');
200
+ showButton.textContent = 'Show';
201
+ showButton.className = 'show-button';
202
+ showButton.setAttribute('aria-label', `Show details for ${item.name}`);
203
+ showButton.tabIndex = 0;
204
+ showButton.onclick = () => toggleDescription(itemContainer, item.description, item.name);
205
+ contentDiv.appendChild(showButton);
206
+ }
207
+
208
+ itemContainer.appendChild(contentDiv);
209
+
210
+ const removeButton = document.createElement('button');
211
+ removeButton.textContent = 'X';
212
+ removeButton.className = 'remove-button';
213
+ removeButton.setAttribute('aria-label', `Remove ${item.name} from selection`);
214
+ removeButton.tabIndex = 0;
215
+ removeButton.onclick = () => {
216
+ selectedItems.splice(index, 1);
217
+ addMessage('bot', `Removed "${item.name}".`);
218
+ showToast(`Removed "${item.name}"`);
219
+ updateSelectionBox();
220
+ };
221
+ itemContainer.appendChild(removeButton);
222
+
223
+ selectionBox.appendChild(itemContainer);
224
+ });
225
+
226
+ const textInput = document.createElement('input');
227
+ textInput.type = 'text';
228
+ textInput.placeholder = 'Add item...';
229
+ textInput.className = 'manual-input';
230
+ textInput.setAttribute('aria-label', 'Add item manually');
231
+ textInput.tabIndex = 0;
232
+ const debouncedFetch = debounce((e) => {
233
+ if (e.key === 'Enter' && textInput.value.trim()) {
234
+ const itemName = textInput.value.trim();
235
+ fetchSectorItemDetails(itemName);
236
+ textInput.value = '';
237
+ showToast(`Searching for "${itemName}"...`);
238
+ }
239
+ }, 300);
240
+ textInput.addEventListener('keypress', debouncedFetch);
241
+ selectionBox.appendChild(textInput);
242
+
243
+ if (selectedItems.length > 0) {
244
+ const quantityInput = document.createElement('input');
245
+ quantityInput.type = 'number';
246
+ quantityInput.min = '1';
247
+ quantityInput.value = '1';
248
+ quantityInput.placeholder = 'Qty';
249
+ quantityInput.className = 'quantity-input';
250
+ quantityInput.setAttribute('aria-label', 'Set default quantity for all items');
251
+ quantityInput.tabIndex = 0;
252
+ selectionBox.appendChild(quantityInput);
253
+
254
+ const submitButton = document.createElement('button');
255
+ submitButton.textContent = 'Submit';
256
+ submitButton.className = 'submit-button';
257
+ submitButton.setAttribute('aria-label', 'Submit selected items');
258
+ submitButton.tabIndex = 0;
259
+ submitButton.onclick = () => promptAndSubmit(quantityInput.value);
260
+ selectionBox.appendChild(submitButton);
261
+
262
+ const orderNameInput = document.createElement('input');
263
+ orderNameInput.type = 'text';
264
+ orderNameInput.placeholder = 'Order Name';
265
+ orderNameInput.className = 'order-name-input';
266
+ orderNameInput.setAttribute('aria-label', 'Enter order name');
267
+ orderNameInput.tabIndex = 0;
268
+ selectionBox.appendChild(orderNameInput);
269
+ }
270
+
271
+ chatMessages.appendChild(selectionBox);
272
+ chatMessages.scrollTop = chatMessages.scrollHeight;
273
+ }
274
+
275
+ async function fetchWithRetry(url, options, retries = MAX_RETRIES) {
276
+ for (let i = 0; i < retries; i++) {
277
+ try {
278
+ const response = await fetch(url, options);
279
+ if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
280
+ return await response.json();
281
+ } catch (error) {
282
+ if (i === retries - 1) {
283
+ throw error;
284
+ }
285
+ await new Promise(resolve => setTimeout(resolve, 2000));
286
+ }
287
+ }
288
+ }
289
+
290
+ function fetchMenuItems(dietaryPreference = '', searchTerm = '') {
291
+ const cacheKey = `${dietaryPreference}:${searchTerm}`;
292
+ if (searchCache.has(cacheKey)) {
293
+ const data = searchCache.get(cacheKey);
294
+ displayCachedMenuItems(data, searchTerm, dietaryPreference);
295
+ return;
296
+ }
297
+
298
+ const payload = {};
299
+ if (dietaryPreference) payload.dietary_preference = dietaryPreference;
300
+ if (searchTerm) payload.search_term = searchTerm;
301
+
302
+ const chatMessages = document.getElementById('chatMessages');
303
+ const spinner = document.createElement('div');
304
+ spinner.className = 'spinner';
305
+ chatMessages.appendChild(spinner);
306
+
307
+ fetchWithRetry('/get_menu_items', {
308
+ method: 'POST',
309
+ headers: { 'Content-Type': 'application/json' },
310
+ body: JSON.stringify(payload)
311
+ })
312
+ .then(data => {
313
+ spinner.remove();
314
+ if (data.error) {
315
+ addMessage('bot', `Error: ${data.error}. Try again!`);
316
+ showToast(`Error: ${data.error}`);
317
+ } else if (data.menu_items.length > 0) {
318
+ searchCache.set(cacheKey, data);
319
+ addMessage('bot', `--- Found ${data.menu_items.length} item${data.menu_items.length > 1 ? 's' : ''} ---`);
320
+ displayItemsList(data.menu_items);
321
+ } else {
322
+ addMessage('bot', `No matches for "${searchTerm || dietaryPreference}". Try "paneer" or "chicken curry"!`);
323
+ showToast('No items found!');
324
+ }
325
+ })
326
+ .catch(error => {
327
+ spinner.remove();
328
+ addMessage('bot', `Connection issue: ${error.message}. Please try again later.`);
329
+ showToast('Connection issue!');
330
+ });
331
+ }
332
+
333
+ function displayCachedMenuItems(data, searchTerm, dietaryPreference) {
334
+ if (data.error) {
335
+ addMessage('bot', `Error: ${data.error}. Try again!`);
336
+ showToast(`Error: ${data.error}`);
337
+ } else if (data.menu_items.length > 0) {
338
+ addMessage('bot', `--- Found ${data.menu_items.length} item${data.menu_items.length > 1 ? 's' : ''} ---`);
339
+ displayItemsList(data.menu_items);
340
+ } else {
341
+ addMessage('bot', `No matches for "${searchTerm || dietaryPreference}". Try "paneer" or "chicken curry"!`);
342
+ showToast('No items found!');
343
+ }
344
+ }
345
+
346
+ function fetchSectorItemDetails(itemName) {
347
+ const cacheKey = `sector:${itemName}`;
348
+ if (searchCache.has(cacheKey)) {
349
+ const data = searchCache.get(cacheKey);
350
+ displayCachedSectorItems(data, itemName);
351
+ return;
352
+ }
353
+
354
+ fetchWithRetry('/get_sector_item_details', {
355
+ method: 'POST',
356
+ headers: { 'Content-Type': 'application/json' },
357
+ body: JSON.stringify({ item_name: itemName })
358
+ })
359
+ .then(data => {
360
+ if (data.error) {
361
+ addMessage('bot', `No "${itemName}" found. Try another!`);
362
+ showToast(`No "${itemName}" found`);
363
+ } else {
364
+ searchCache.set(cacheKey, data);
365
+ const details = data.item_details;
366
+ if (selectedItems.some(item => item.name === details.name)) {
367
+ addMessage('bot', `"${details.name}" already selected!`);
368
+ showToast(`"${details.name}" already selected`);
369
+ } else {
370
+ selectedItems.push({ ...details, quantity: 1 });
371
+ addMessage('bot', `Added "${details.name}"!`);
372
+ showToast(`Added "${details.name}"`);
373
+ updateSelectionBox();
374
+ }
375
+ }
376
+ })
377
+ .catch(error => {
378
+ addMessage('bot', `Error for "${itemName}". Please try again later.`);
379
+ showToast(`Error fetching "${itemName}"`);
380
+ });
381
+ }
382
+
383
+ function displayCachedSectorItems(data, itemName) {
384
+ if (data.error) {
385
+ addMessage('bot', `No "${itemName}" found. Try another!`);
386
+ showToast(`No "${itemName}" found`);
387
+ } else {
388
+ const details = data.item_details;
389
+ if (selectedItems.some(item => item.name === details.name)) {
390
+ addMessage('bot', `"${details.name}" already selected!`);
391
+ showToast(`"${details.name}" already selected`);
392
+ } else {
393
+ selectedItems.push({ ...details, quantity: 1 });
394
+ addMessage('bot', `Added "${details.name}"!`);
395
+ showToast(`Added "${details.name}"`);
396
+ updateSelectionBox();
397
+ }
398
+ }
399
+ }
400
+
401
+ function toggleDescription(itemContainer, description, itemName) {
402
+ let descElement = itemContainer.querySelector('.item-description');
403
+ if (!descElement) {
404
+ descElement = document.createElement('p');
405
+ descElement.className = 'item-description';
406
+ descElement.textContent = description;
407
+ itemContainer.querySelector('.selected-item-content').appendChild(descElement);
408
+ itemContainer.dataset.hidden = 'false';
409
+ showToast(`Showing details for ${itemName}`);
410
+ } else {
411
+ descElement.remove();
412
+ itemContainer.dataset.hidden = 'true';
413
+ showToast(`Hid details for ${itemName}`);
414
+ }
415
+ }
416
+
417
+ function displayItemsList(items) {
418
+ const chatMessages = document.getElementById('chatMessages');
419
+ if (!chatMessages) {
420
+ addMessage('bot', 'Display issue. Try again?');
421
+ showToast('Display issue!');
422
+ return;
423
+ }
424
+
425
+ const itemsGrid = document.createElement('div');
426
+ itemsGrid.className = 'items-grid';
427
+
428
+ items.forEach((item, index) => {
429
+ const itemDiv = document.createElement('article');
430
+ itemDiv.className = 'item-card';
431
+
432
+ const img = document.createElement('img');
433
+ img.src = item.image_url || 'https://via.placeholder.com/120?text=Item';
434
+ img.alt = item.name;
435
+ img.className = 'item-image';
436
+ if (index < 3) img.loading = 'eager'; // Preload first 3 images
437
+ itemDiv.appendChild(img);
438
+
439
+ const contentDiv = document.createElement('div');
440
+ contentDiv.className = 'item-content';
441
+
442
+ const nameDiv = document.createElement('div');
443
+ nameDiv.textContent = item.name;
444
+ nameDiv.className = 'item-name';
445
+ contentDiv.appendChild(nameDiv);
446
+
447
+ const fields = [
448
+ { label: 'Price', value: item.price ? `$${item.price.toFixed(2)}` : 'N/A' },
449
+ { label: 'Veg/Non-Veg', value: item.veg_nonveg },
450
+ { label: 'Spice', value: item.spice_levels },
451
+ { label: 'Category', value: item.category },
452
+ { label: 'Ingredients', value: item.ingredients },
453
+ { label: 'Nutrition', value: item.nutritional_info },
454
+ { label: 'Sector', value: item.sector },
455
+ { label: 'Dynamic', value: item.dynamic_dish ? 'Yes' : 'No' }
456
+ ];
457
+ fields.forEach(field => {
458
+ if (field.value) {
459
+ const p = document.createElement('p');
460
+ p.className = 'item-field';
461
+ p.innerHTML = `<strong>${field.label}:</strong> ${field.value}`;
462
+ contentDiv.appendChild(p);
463
+ }
464
+ });
465
+
466
+ itemDiv.appendChild(contentDiv);
467
+
468
+ const buttonContainer = document.createElement('div');
469
+ buttonContainer.className = 'button-container';
470
+
471
+ const addButton = document.createElement('button');
472
+ addButton.textContent = 'Add';
473
+ addButton.className = 'add-button';
474
+ addButton.setAttribute('aria-label', `Add ${item.name} to selection`);
475
+ addButton.tabIndex = 0;
476
+ addButton.onclick = () => {
477
+ const selectedItem = {
478
+ name: item.name,
479
+ image_url: item.image_url || '',
480
+ category: item.category || 'Not specified',
481
+ description: item.description || 'No description available',
482
+ source: item.source,
483
+ quantity: 1,
484
+ ingredients: item.ingredients,
485
+ nutritional_info: item.nutritional_info,
486
+ price: item.price,
487
+ sector: item.sector,
488
+ spice_levels: item.spice_levels,
489
+ veg_nonveg: item.veg_nonveg,
490
+ dynamic_dish: item.dynamic_dish
491
+ };
492
+ if (selectedItems.some(existing => existing.name === selectedItem.name)) {
493
+ addMessage('bot', `"${selectedItem.name}" already selected!`);
494
+ showToast(`"${selectedItem.name}" already selected`);
495
+ } else {
496
+ selectedItems.push(selectedItem);
497
+ addMessage('bot', `Added "${selectedItem.name}"!`);
498
+ showToast(`Added "${selectedItem.name}"`);
499
+ updateSelectionBox();
500
+ }
501
+ };
502
+ buttonContainer.appendChild(addButton);
503
+
504
+ itemDiv.appendChild(buttonContainer);
505
+ itemsGrid.appendChild(itemDiv);
506
+ });
507
+
508
+ chatMessages.appendChild(itemsGrid);
509
+ chatMessages.scrollTop = chatMessages.scrollHeight;
510
+ }
511
+
512
+ function displayOptions(options) {
513
+ const chatMessages = document.getElementById('chatMessages');
514
+ if (!chatMessages) {
515
+ console.error('Chat messages container not found!');
516
+ return;
517
+ }
518
+ const optionsDiv = document.createElement('div');
519
+ optionsDiv.className = 'options-container';
520
+
521
+ options.forEach(opt => {
522
+ const button = document.createElement('button');
523
+ button.textContent = opt.text;
524
+ button.className = `option-button ${opt.class}`;
525
+ button.setAttribute('aria-label', `Select ${opt.text} dishes`);
526
+ button.tabIndex = 0;
527
+ button.onclick = () => {
528
+ addMessage('user', opt.text, true);
529
+ conversation.push({ role: 'user', message: opt.text });
530
+ selectionBoxVisible = true;
531
+ handleResponse(opt.text);
532
+ updateSelectionBox();
533
+ showToast(`Selected ${opt.text}`);
534
+ };
535
+ optionsDiv.appendChild(button);
536
+ });
537
+
538
+ const backButton = document.createElement('button');
539
+ backButton.textContent = 'Back';
540
+ backButton.className = 'option-button';
541
+ backButton.setAttribute('aria-label', 'Reset conversation');
542
+ backButton.tabIndex = 0;
543
+ backButton.onclick = () => resetConversation();
544
+ optionsDiv.appendChild(backButton);
545
+
546
+ chatMessages.appendChild(optionsDiv);
547
+ }
548
+
549
+ function promptAndSubmit(quantity) {
550
+ const orderNameInput = document.querySelector('.order-name-input');
551
+ const customOrderName = orderNameInput ? orderNameInput.value.trim() : '';
552
+ const qty = parseInt(quantity);
553
+ if (isNaN(qty) || qty <= 0) {
554
+ addMessage('bot', 'Please enter a valid quantity (1 or more)!');
555
+ showToast('Invalid quantity!');
556
+ return;
557
+ }
558
+ if (confirm(`Submit ${selectedItems.length} items with default quantity ${qty}?`)) {
559
+ submitToSalesforce(customOrderName, qty);
560
+ showToast('Submitting order...');
561
+ } else {
562
+ addMessage('bot', 'Cancelled. Add more items?');
563
+ showToast('Order cancelled');
564
+ }
565
+ }
566
+
567
+ function submitToSalesforce(customOrderName, quantity) {
568
+ if (selectedItems.length === 0) {
569
+ addMessage('bot', 'No items selected! Add some dishes! 😊');
570
+ showToast('No items selected');
571
+ return;
572
+ }
573
+
574
+ const itemsToSubmit = selectedItems.map(item => ({
575
+ name: item.name,
576
+ category: item.category || 'Not specified',
577
+ description: item.description || 'No description available',
578
+ image_url: item.image_url || '',
579
+ quantity: item.quantity || parseInt(quantity) || 1
580
+ }));
581
+
582
+ fetchWithRetry('/submit_items', {
583
+ method: 'POST',
584
+ headers: { 'Content-Type': 'application/json' },
585
+ body: JSON.stringify({ items: itemsToSubmit, custom_order_name: customOrderName })
586
+ })
587
+ .then(data => {
588
+ if (data.error) {
589
+ addMessage('bot', `Submission failed: ${data.error}. Try again?`);
590
+ showToast(`Submission failed: ${data.error}`);
591
+ } else {
592
+ addMessage('bot', `Order "${customOrderName || 'Order'}" with ${itemsToSubmit.length} items submitted! What's next?`);
593
+ selectedItems = [];
594
+ updateSelectionBox();
595
+ showToast('Order submitted successfully!');
596
+ }
597
+ })
598
+ .catch(error => {
599
+ addMessage('bot', `Submission error: ${error.message}. Please try again later.`);
600
+ showToast('Submission error!');
601
+ });
602
+ }
603
+
604
+ function resetConversation() {
605
+ const userName = conversation.length > 1 ? conversation[1].message : 'Friend';
606
+ conversation = [
607
+ { role: 'bot', message: `Hello! I’m Chef Bot, your culinary assistant! What’s your name?` },
608
+ { role: 'user', message: userName },
609
+ { role: 'bot', message: `Hi ${userName}! 🍳 Search for a dish or choose a preference below!` }
610
+ ];
611
+ selectedItems = [];
612
+ selectionBoxVisible = true;
613
+ const chatMessages = document.getElementById('chatMessages');
614
+ chatMessages.innerHTML = '';
615
+ conversation.forEach(msg => addMessage(msg.role, msg.message));
616
+ displayOptions([
617
+ { text: 'Vegetarian', class: 'green' },
618
+ { text: 'Non-Vegetarian', class: 'red' },
619
+ { text: 'Both', class: 'gray' }
620
+ ]);
621
+ updateSelectionBox();
622
+ showToast('Conversation reset');
623
+ }
624
+
625
+ document.getElementById('userInput').addEventListener('keypress', (e) => {
626
+ if (e.key === 'Enter') sendMessage();
627
+ });
628
+
629
+ console.log('Chef Bot script loaded!');