diff --git "a/templates/menu.html" "b/templates/menu.html" --- "a/templates/menu.html" +++ "b/templates/menu.html" @@ -4,8 +4,10 @@ Menu + + {% for section, items in ordered_menu.items() %} {% for item in items[:1] %} @@ -13,66 +15,1393 @@ {% endfor %} {% endfor %} @@ -84,7 +1413,7 @@ @@ -95,9 +1424,10 @@ -
+
+ Veg
+ +
{% if selected_category == "Customized Dish" %}
-
-
🍳 Chef Bot
-
-
- - -
-
+
+
🍳 Chef Bot
+
+ +
+
+ + +
+
{% else %} {% if ordered_menu.items()|length == 0 %} @@ -174,8 +1508,8 @@ 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 - {% if item.Section__c != 'Apetizer' and item.Section__c != 'Customized Dish' %} - Customizable + {% if item.Section__c != 'Apetizer' and item.Section__c != 'Customized dish' %} + Customisable {% endif %} {% endif %}
@@ -285,7 +1619,31 @@ let isProcessingRequest = false; let currentSoftDrinkButton = null; let baseItemPrice = 0; - + const menuItems = [ + {% for section, items in ordered_menu.items() %} + {% for item in items %} + { + name: "{{ item.Name | default('Unnamed Item') }}", + section: "{{ item.Section__c | default(section) }}" + }, + {% endfor %} + {% endfor %} + ]; + const ingredientsList = [ + "Basmati Rice", "Bell Pepper", "Biryani Masala", "Butter", "Capsicum", "Cauliflower", + "Chickpea Flour (Besan)", "Chickpea Flour (for batter)", "Chickpeas (Channa)", "Chili Powder", + "Chili Sauce", "Coconut Milk", "Coriander Powder", "Cornflour", "Cream", "Cumin Powder", + "Cumin Seeds", "Curd (Yogurt)", "Curry Leaves", "Fish (e.g., King Fish or Salmon)", + "Fresh Coriander Leaves", "Garam Masala", "Garlic", "Ghee (Clarified Butter)", "Ginger", + "Ginger-Garlic Paste", "Goat Meat (Mutton)", "Green Chilies", "Honey", + "Kasuri Methi (dried fenugreek leaves)", "Lemon Juice", "Mango Puree", "Mint Leaves", + "Mixed Vegetables (Carrot, Peas, Potato, Cauliflower)", "Mixed Vegetables (Carrot, Peas, Potato)", + "Mustard Seeds", "Mutton (Goat Meat)", "Oil", "Oil (for frying)", "Onion", + "Paneer (Indian Cottage Cheese)", "Peas", "Potatoes", "Prawns", "Red Chili Powder", + "Rice Flour", "Saffron", "Salt", "Soy Sauce", "Spring Onion", "Tamarind (for sourness)", + "Tomato Ketchup", "Tomatoes", "Turmeric Powder", "Vinegar", "Water", "Wheat Flour (for dough)", + "Whole Wheat Flour", "Yogurt (Curd)" + ]; function addToCartLocalStorage(payload) { let cart = JSON.parse(localStorage.getItem('cart')) || []; const existingItem = cart.find(item => @@ -301,11 +1659,33 @@ localStorage.setItem('cart', JSON.stringify(cart)); return cart; } - - function getCartLocalStorage() { - return JSON.parse(localStorage.getItem('cart')) || []; - } - + function removeFromCartLocalStorage(itemName, quantityToRemove, instructions, addons) { + let cart = JSON.parse(localStorage.getItem('cart')) || []; + const itemIndex = cart.findIndex(item => + item.itemName === itemName && + item.instructions === instructions && + JSON.stringify(item.addons) === JSON.stringify(addons) + ); + if (itemIndex !== -1) { + if (quantityToRemove >= cart[itemIndex].quantity) { + cart.splice(itemIndex, 1); + } else { + cart[itemIndex].quantity -= quantityToRemove; + } + } + localStorage.setItem('cart', JSON.stringify(cart)); + return cart; + } + function getCartLocalStorage() { + return JSON.parse(localStorage.getItem('cart')) || []; + } + function debounce(func, wait) { + let timeout; + return function (...args) { + clearTimeout(timeout); + timeout = setTimeout(() => func.apply(this, args), wait); + }; + } function updateModalPrice() { const selectedAddOns = Array.from( document.querySelectorAll('#addons-list input[type="checkbox"]:checked') @@ -314,14 +1694,12 @@ const totalPrice = baseItemPrice + totalAddOnPrice; document.getElementById('modal-price').innerText = `$${totalPrice.toFixed(2)}`; } - function updateSoftDrinkQuantity(delta) { const quantityInput = document.getElementById('soft-drink-quantity'); let currentQuantity = parseInt(quantityInput.value) || 1; currentQuantity = Math.max(1, currentQuantity + delta); quantityInput.value = currentQuantity; } - function showSoftDrinkModal(button) { currentSoftDrinkButton = button; const buttonContainer = button.closest('.button-container'); @@ -330,14 +1708,13 @@ const itemImage = buttonContainer.getAttribute('data-item-image'); document.getElementById('soft-drink-name').textContent = itemName; - document.getElementById('soft-drink-price').textContent = `$${itemPrice}`; + document.getElementById('soft-drink-price').textContent = `${itemPrice}`; document.getElementById('soft-drink-quantity').value = '1'; document.getElementById('soft-drink-image').src = itemImage || '/static/placeholder.jpg'; const modal = new bootstrap.Modal(document.getElementById('softDrinkModal')); modal.show(); } - function addSoftDrinkToCart() { if (!currentSoftDrinkButton) return; @@ -363,7 +1740,9 @@ fetch('/cart/add', { method: 'POST', - headers: { 'Content-Type': 'application/json' }, + headers: { + 'Content-Type': 'application/json', + }, body: JSON.stringify(cartPayload) }) .then(response => response.json()) @@ -388,7 +1767,6 @@ modal.hide(); }); } - function updateCartUI(cart) { if (!Array.isArray(cart)) { console.error('Invalid cart data:', cart); @@ -405,8 +1783,9 @@ } } - window.most_common_addons = {{ most_common_addons | tojson }}; + window.most_common_addons = {{ most_common_addons | tojson }}; + console.log("Most common add-ons: ", window.most_common_addons); function showItemDetails(name, price, image, description, section, selectedCategory) { document.getElementById('modal-name').innerText = name; baseItemPrice = parseFloat(price) || 0; @@ -415,16 +1794,18 @@ modalImg.src = image || '/static/placeholder.jpg'; document.getElementById('modal-description').innerText = description || 'No description available.'; document.getElementById('addons-list').innerHTML = ''; + document.getElementById('addons-list').classList.add('addon-loading'); document.getElementById('modal-instructions').value = ''; const modalSectionEl = document.getElementById('modal-section'); modalSectionEl.setAttribute('data-section', section); modalSectionEl.setAttribute('data-category', selectedCategory); document.getElementById('quantityInput').value = 1; - fetch(`/api/addons?item_name=${encodeURIComponent(name)}&item_section=${encodeURIComponent(section)}`) .then(response => response.json()) .then(data => { const addonsList = document.getElementById('addons-list'); + addonsList.classList.remove('addon-loading'); + addonsList.innerHTML = ''; if (!data.success || !data.addons || data.addons.length === 0) { addonsList.innerHTML = '

No customization options available.

'; return; @@ -454,20 +1835,77 @@ sectionDiv.appendChild(optionsContainer); addonsList.appendChild(sectionDiv); }); + const addonSections = addonsList.querySelectorAll('.addon-section'); + addonSections.forEach(section => { + const title = section.querySelector('h6'); + const options = section.querySelector('.addon-options'); + title.addEventListener('click', () => { + section.classList.toggle('collapsed'); + options.classList.toggle('collapsed'); + }); + }); document.querySelectorAll('.addon-option').forEach(checkbox => { checkbox.addEventListener('change', updateModalPrice); }); + document.querySelectorAll('.addon-option').forEach(checkbox => { + checkbox.addEventListener('change', function () { + const groupName = this.getAttribute('data-group'); + const isMultiSelectGroup = ["Extra Toppings", "Choose Raita/Sides", "Select Dip/Sauce", "Extra Add-ons", "Make it a Combo", "Beverages", "Sauces"].includes(groupName); + if (!isMultiSelectGroup && this.checked) { + document.querySelectorAll(`.addon-option[data-group="${groupName}"]`).forEach(otherCheckbox => { + if (otherCheckbox !== this) { + otherCheckbox.checked = false; + } + }); + } + }); + }); + // Pre-select the highest-count spice level + if (window.most_common_addons && window.most_common_addons.length > 0) { + const checkboxes = document.querySelectorAll('.addon-option'); + const categorySelection = { + "Select Spice Level": null, + "Choose Spice Level": null, + "Raita/Sides": [], + }; + // First pass: Find and select the highest-count spice level + for (let spice of window.most_common_addons) { + const isSpiceLevel = ["Mild", "Medium", "Spicy", "Extra Spicy"].includes(spice); // Define valid spice levels + if (isSpiceLevel) { + checkboxes.forEach(checkbox => { + const checkboxName = checkbox.getAttribute('data-name').trim(); + const checkboxGroup = checkbox.getAttribute('data-group'); + if ((checkboxGroup === "Select Spice Level" || checkboxGroup === "Choose Spice Level") && + checkboxName === spice && categorySelection[checkboxGroup] === null) { + console.log(`Pre-selecting highest-count spice level: ${checkboxName}`); + checkbox.checked = true; + categorySelection[checkboxGroup] = checkboxName; + } + }); + if (categorySelection["Select Spice Level"] || categorySelection["Choose Spice Level"]) break; // Stop after selecting the first spice + } + } + // Second pass: Select other non-spice add-ons (e.g., Raita/Sides) + checkboxes.forEach(checkbox => { + const checkboxName = checkbox.getAttribute('data-name').trim(); + const checkboxGroup = checkbox.getAttribute('data-group'); + if (checkboxGroup === "Raita/Sides" && window.most_common_addons.includes(checkboxName)) { + console.log(`Pre-selecting add-on: ${checkboxName}`); + checkbox.checked = true; + categorySelection["Raita/Sides"].push(checkboxName); + } + }); + } }) .catch(err => { console.error('Error fetching add-ons:', err); + document.getElementById('addons-list').classList.remove('addon-loading'); document.getElementById('addons-list').innerHTML = '

Error loading customization options.

'; }); } - function addToCartFromModal() { if (isProcessingRequest) return; isProcessingRequest = true; - const modalSectionEl = document.getElementById('modal-section'); const section = modalSectionEl.getAttribute('data-section'); const selectedCategory = modalSectionEl.getAttribute('data-category'); @@ -482,7 +1920,12 @@ name: addon.getAttribute('data-name'), price: parseFloat(addon.getAttribute('data-price')) || 0 })); - + if (!itemName || isNaN(itemPrice) || !section || !itemImage || quantity < 1) { + console.error('Invalid cart item data:', { itemName, itemPrice, section, itemImage, quantity }); + alert('Invalid item data. Please try again.'); + isProcessingRequest = false; + return; + } const cartPayload = { itemName: itemName, itemPrice: itemPrice, @@ -493,10 +1936,11 @@ instructions: instructions, quantity: quantity }; - fetch('/cart/add', { method: 'POST', - headers: { 'Content-Type': 'application/json' }, + headers: { + 'Content-Type': 'application/json', + }, body: JSON.stringify(cartPayload) }) .then(response => response.json()) @@ -524,7 +1968,6 @@ isProcessingRequest = false; }); } - function handleToggle(source) { const form = document.getElementById("filter-form"); const veg = document.getElementById("veg-toggle"); @@ -538,10 +1981,15 @@ veg.checked = false; } } + if (!custom.checked && !veg.checked) { + custom.checked = false; + } form.submit(); } + - document.addEventListener('DOMContentLoaded', function () { + + document.addEventListener('DOMContentLoaded', function () { const avatarContainer = document.querySelector('.avatar-dropdown-container'); const dropdownMenu = document.querySelector('.dropdown-menu'); avatarContainer.addEventListener('click', function (event) { @@ -553,14 +2001,182 @@ dropdownMenu.style.display = 'none'; } }); - + const dropdownItems = document.querySelectorAll('.dropdown-item'); + dropdownItems.forEach(item => { + item.addEventListener('click', function () { + dropdownMenu.style.display = 'none'; + }); + }); const searchBar = document.getElementById('searchBar'); searchBar.addEventListener('click', function () { window.location.href = '/search'; }); - + const selectedItem = localStorage.getItem('selectedItem'); + if (selectedItem) { + try { + const { name, section } = JSON.parse(selectedItem); + const menuCards = document.querySelectorAll('.menu-card'); + let targetCard = null; + let buttonContainer = null; + menuCards.forEach(card => { + const itemName = card.getAttribute('data-item-name'); + const itemSection = card.getAttribute('data-item-section'); + if (itemName === name && itemSection === section) { + targetCard = card; + buttonContainer = card.querySelector('.button-container'); + card.classList.add('highlighted'); + card.scrollIntoView({ behavior: 'smooth', block: 'center' }); + const toggleLink = card.querySelector('.toggle-details'); + if (toggleLink) { + toggleLink.click(); + } + } + }); + if (buttonContainer) { + if (section === 'Soft Drinks') { + showSoftDrinkModal(buttonContainer.querySelector('.add-to-cart-btn')); + } else { + const name = buttonContainer.getAttribute('data-item-name'); + const price = buttonContainer.getAttribute('data-item-price'); + const image = buttonContainer.getAttribute('data-item-image2'); + const description = buttonContainer.getAttribute('data-item-description'); + const category = buttonContainer.getAttribute('data-item-category'); + showItemDetails(name, price, image, description, section, category); + const modal = new bootstrap.Modal(document.getElementById('itemModal')); + modal.show(); + } + } + } catch (err) { + console.error('Error parsing selected item:', err); + } + localStorage.removeItem('selectedItem'); + } + const menuCards = document.querySelectorAll('.menu-card'); + const menuVideos = document.querySelectorAll('.menu-video'); + const cardObserver = new IntersectionObserver((entries, observer) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + entry.target.classList.add('visible'); + observer.unobserve(entry.target); + } + }); + }, { + root: null, + rootMargin: '0px', + threshold: 0.1 + }); + const videoObserver = new IntersectionObserver((entries, observer) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + const video = entry.target; + const src = video.getAttribute('data-src'); + if (src && !video.querySelector('source[src="' + src + '"]')) { + const nextSibling = video.nextElementSibling; + if (nextSibling && nextSibling.tagName === 'SOURCE') { + nextSibling.src = src; + } else { + const source = video.querySelector('source'); + if (source) { + source.src = src; + } + } + video.load(); + } + video.classList.add('loaded'); + observer.unobserve(video); + } + }); + }, { + root: null, + rootMargin: '200px', + threshold: 0.01 + }); + menuCards.forEach(card => cardObserver.observe(card)); + menuVideos.forEach(video => videoObserver.observe(video)); + const toggleLinks = document.querySelectorAll('.toggle-details'); + toggleLinks.forEach(link => { + link.addEventListener('click', function () { + const itemName = this.getAttribute('data-item-name').replace(/ /g, '-'); + const detailsDiv = document.getElementById(`details-${itemName}`); + const isCurrentlyShown = detailsDiv.classList.contains('show'); + document.querySelectorAll('.item-details.show').forEach(otherDetails => { + if (otherDetails !== detailsDiv) { + otherDetails.classList.remove('show'); + const otherLink = document.querySelector(`.toggle-details[data-item-name="${otherDetails.id.replace('details-', '').replace(/-/g, ' ')}"]`); + if (otherLink) { + otherLink.innerText = 'Show Details'; + } + } + }); + if (!isCurrentlyShown) { + detailsDiv.classList.add('show'); + this.innerText = 'Hide Details'; + } else { + detailsDiv.classList.remove('show'); + this.innerText = 'Show Details'; + } + }); + }); + const descriptionTextarea = document.getElementById('custom-dish-description'); + const descriptionSuggestions = document.getElementById('descriptionSuggestions'); + if (descriptionTextarea && descriptionSuggestions) { + let usedIngredients = new Set(); + function updateUsedIngredients() { + const inputText = descriptionTextarea.value.trim(); + usedIngredients.clear(); + if (inputText) { + const words = inputText.split(/,\s*/).map(word => word.trim()); + words.forEach(word => { + if (word && ingredientsList.includes(word)) { + usedIngredients.add(word); + } + }); + } + } + descriptionTextarea.addEventListener('input', function () { + const inputText = this.value.trim(); + const words = inputText.split(/,\s*/); + const lastWord = words[words.length - 1].trim().toLowerCase(); + descriptionSuggestions.innerHTML = ''; + descriptionSuggestions.style.display = 'none'; + updateUsedIngredients(); + if (lastWord) { + const filteredIngredients = ingredientsList.filter(ingredient => + ingredient.toLowerCase().includes(lastWord) && !usedIngredients.has(ingredient) + ); + if (filteredIngredients.length > 0) { + filteredIngredients.forEach(ingredient => { + const suggestionDiv = document.createElement('div'); + suggestionDiv.classList.add('suggestion-item'); + suggestionDiv.innerText = ingredient; + suggestionDiv.addEventListener('click', function () { + const currentValue = descriptionTextarea.value; + const lastCommaIndex = currentValue.lastIndexOf(','); + const baseText = lastCommaIndex !== -1 ? currentValue.substring(0, lastCommaIndex + 1) : ''; + descriptionTextarea.value = baseText + (baseText ? ' ' : '') + ingredient + ', '; + descriptionSuggestions.style.display = 'none'; + descriptionTextarea.focus(); + updateUsedIngredients(); + }); + descriptionSuggestions.appendChild(suggestionDiv); + }); + descriptionSuggestions.style.display = 'block'; + } + } + }); + document.addEventListener('click', function (event) { + if (!descriptionTextarea.contains(event.target) && !descriptionSuggestions.contains(event.target)) { + descriptionSuggestions.style.display = 'none'; + } + }); + } fetch('/cart/get') - .then(response => response.json()) + .then(response => { + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + return response.json(); + }) .then(data => { if (data.success) { updateCartUI(data.cart); @@ -575,7 +2191,12 @@ const cart = getCartLocalStorage(); updateCartUI(cart); }); - + const preloadedVideos = document.querySelectorAll('link[rel="preload"][as="video"]'); + preloadedVideos.forEach(link => { + const video = document.createElement('video'); + video.src = link.href; + video.preload = 'auto'; + }); const decreaseBtn = document.getElementById('decreaseQuantity'); const increaseBtn = document.getElementById('increaseQuantity'); const quantityInput = document.getElementById('quantityInput'); @@ -590,181 +2211,182 @@ quantityInput.value = quantity; }); }); - - let currentStep = 'greeting'; - let conversation = []; - let selectedIngredients = []; - let selectedMenuItem = null; - const userName = "{{ user_name }}"; - - window.onload = function() { - if (userName) { - conversation.push({ role: 'bot', message: `Nice to meet you, ${userName}! 😊 Let's create your perfect meal! What type of food would you prefer?` }); - displayConversation(); - displayOptions([ - { text: 'Vegetarian', class: 'green' }, - { text: 'Non-Vegetarian', class: 'red' } - ]); - } else { - conversation.push({ role: 'bot', message: "Hi there! I'm Chef Bot! May I know your name?" }); - displayConversation(); - } - }; - - function displayConversation() { - const chatMessages = document.getElementById('chatMessages'); - chatMessages.innerHTML = ''; - conversation.forEach(msg => { - addMessage(msg.role, msg.message); - }); - chatMessages.scrollTop = chatMessages.scrollHeight; + let currentStep = 'greeting'; // other possible values: 'food_type', 'select_ingredients', 'menu_display', 'customization', 'post_cart' + let conversation = []; + let selectedIngredients = []; + let selectedMenuItem = null; + let cart = []; + // Get the user name passed from Flask (via Jinja) + const userName = "{{ user_name }}"; // Jinja syntax to inject user_name from Flask session + window.onload = function() { + if (userName) { + // If user_name exists, greet the user directly and proceed to food preference + conversation.push({ role: 'bot', message: `Nice to meet you, ${userName}! 😊 Let's create your perfect meal! What type of food would you prefer?` }); + displayConversation(); // Display the current conversation + displayOptions([ + { text: 'Vegetarian', class: 'green' }, + { text: 'Non-Vegetarian', class: 'red' } + ]); + } else { + // Ask for the name if it's not found + conversation.push({ role: 'bot', message: "Hi there! I'm Chef Bot! May I know your name?" }); + displayConversation(); // Display the conversation } - - function addMessage(role, message) { - const chatMessages = document.getElementById('chatMessages'); + }; + // Function to add messages to the chat + function addMessage(role, message) { + const chatMessages = document.getElementById('chatMessages'); + if (!chatMessages) { + console.error('Chat messages container not found!'); + return; + } + const messageDiv = document.createElement('div'); + messageDiv.className = role === 'bot' ? 'bot-message' : 'user-message'; + messageDiv.textContent = message; + chatMessages.appendChild(messageDiv); + chatMessages.scrollTop = chatMessages.scrollHeight; + } + // Function to display all conversation messages + function displayConversation() { + const chatMessages = document.getElementById('chatMessages'); + chatMessages.innerHTML = ''; // Clear previous messages + conversation.forEach(msg => { const messageDiv = document.createElement('div'); - messageDiv.className = role === 'bot' ? 'bot-message' : 'user-message'; - messageDiv.textContent = message; + messageDiv.className = msg.role === 'bot' ? 'bot-message' : 'user-message'; + messageDiv.textContent = msg.message; chatMessages.appendChild(messageDiv); - chatMessages.scrollTop = chatMessages.scrollHeight; - } - - function sendMessage() { - const userInput = document.getElementById('userInput').value.trim(); - if (userInput) { - addMessage('user', userInput); - conversation.push({ role: 'user', message: userInput }); - document.getElementById('userInput').value = ''; - setTimeout(() => handleResponse(userInput), 500); - } + }); + chatMessages.scrollTop = chatMessages.scrollHeight; // Scroll to bottom + } + // Function to handle user input + function sendMessage() { + const userInput = document.getElementById('userInput').value.trim(); + if (userInput) { + addMessage('user', userInput); + conversation.push({ role: 'user', message: userInput }); + document.getElementById('userInput').value = ''; // Clear input field + setTimeout(() => handleResponse(userInput), 500); + } else { + console.warn('Empty message!'); } - + } function handleResponse(userInput) { + const lastMessage = conversation[conversation.length - 1].message.toLowerCase(); let botResponse = ''; let options = []; - const lastMessage = userInput.toLowerCase(); - - if (currentStep === 'greeting' && !userName) { - currentStep = 'food_type'; - botResponse = `Nice to meet you, ${userInput}! 😊 What type of food would you prefer?`; - options = [ - { text: 'Vegetarian', class: 'green' }, - { text: 'Non-Vegetarian', class: 'red' } - ]; + // If user has already selected food type, proceed without repeating the question + if (lastMessage.includes('non-vegetarian')) { + conversation.push({ role: 'user', message: 'Non-Vegetarian' }); + console.log("Food preference selected: Non-Vegetarian"); + botResponse = 'Great choice! 🍽️ Please select a non-vegetarian option:'; + fetchIngredients('non-vegetarian'); + return; } else if (lastMessage.includes('vegetarian')) { - currentStep = 'ingredients'; + conversation.push({ role: 'user', message: 'Vegetarian' }); + console.log("Food preference selected: Vegetarian"); botResponse = 'Great choice! 🍽️ Here are some vegetarian ingredients:'; fetchIngredients('vegetarian'); return; - } else if (lastMessage.includes('non-vegetarian')) { - currentStep = 'ingredients'; - botResponse = 'Great choice! 🍽️ Please select a non-vegetarian option:'; - fetchIngredients('non-vegetarian'); + } else if (lastMessage.includes('chicken') || lastMessage.includes('beef') || lastMessage.includes('lamb')) { + conversation.push({ role: 'user', message: lastMessage }); + console.log(`Non-veg option selected: ${lastMessage}`); + botResponse = `Great! Here are some ${lastMessage} ingredients available:`; + fetchIngredients(lastMessage.toLowerCase()); return; } else if (lastMessage.includes('yes') && selectedMenuItem) { - currentStep = 'customize'; botResponse = 'Here are some ingredients to customize your dish:'; - fetchIngredientsForCustomization('both'); + handleYesResponse(); return; } else if (lastMessage.includes('no') && selectedMenuItem) { + // Submit the dish without customization submitCustomizationIngredients(); return; + } else if (lastMessage.includes('yes') && currentStep === 'post_cart') { + // After user says 'yes', ask again for food preference (veg or non-veg) + botResponse = `Let's get started again! What type of food would you prefer this time?`; + options = [ + { text: 'Vegetarian', class: 'green' }, + { text: 'Non-Vegetarian', class: 'red' } + ]; + currentStep = 'food_type'; + addMessage('bot', botResponse); + displayOptions(options); + return; + } else if (lastMessage.includes('non-vegetarian') && currentStep === 'food_type') { + // Handle non-vegetarian selection + conversation.push({ role: 'user', message: 'Non-Vegetarian' }); + console.log("Food preference selected: Non-Vegetarian"); + botResponse = 'Great choice! 🍽️ Please select a non-vegetarian option:'; + fetchIngredients('non-vegetarian'); + return; + } else if (lastMessage.includes('vegetarian') && currentStep === 'food_type') { + // Handle vegetarian selection + conversation.push({ role: 'user', message: 'Vegetarian' }); + console.log("Food preference selected: Vegetarian"); + botResponse = 'Great choice! 🍽️ Here are some vegetarian ingredients:'; + fetchIngredients('vegetarian'); + return; + } else if (lastMessage.includes('no') && currentStep === 'post_cart') { + addMessage('bot', 'Awesome! 🧾 Here’s your final cart:'); + displayCart(); // Optional: show final cart again + addMessage('bot', 'Thank you for your order! πŸ‘¨β€πŸ³πŸ²'); + currentStep = 'end'; + return; } - addMessage('bot', botResponse); if (options.length > 0) { displayOptions(options); } + displayCart(); } - - function fetchIngredients(foodPreference) { - fetch('/get_ingredients', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ dietary_preference: foodPreference }) - }) - .then(response => response.json()) - .then(data => { - if (data.error) { - addMessage('bot', `Error: ${data.error}`); - } else { - const ingredients = data.ingredients || []; - displayIngredientsList(ingredients); - } - }) - .catch(error => { - addMessage('bot', `Error fetching ingredients: ${error.message}`); - }); + function handleYesResponse() { + if (!selectedMenuItem) { + addMessage('bot', 'No dish selected. Please choose a dish first.'); + return; + } + const botResponse = `Here is your selected dish: ${selectedMenuItem.name}`; + addMessage('bot', botResponse); + // Display selected menu item + const chatMessages = document.getElementById('chatMessages'); + const menuItemDiv = document.createElement('div'); + menuItemDiv.className = 'menu-item'; + const img = document.createElement('img'); + img.src = selectedMenuItem.image_url || 'https://via.placeholder.com/120'; + img.alt = selectedMenuItem.name; + const name = document.createElement('div'); + name.textContent = selectedMenuItem.name; + menuItemDiv.appendChild(img); + menuItemDiv.appendChild(name); + chatMessages.appendChild(menuItemDiv); + // Fetch ingredients for customization + fetchIngredientsForCustomization('both'); } - function fetchIngredientsForCustomization(foodPreference) { - fetch('/get_ingredients', { + fetch('/get_ingredients', { // Reuse existing endpoint method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ dietary_preference: foodPreference }) }) - .then(response => response.json()) - .then(data => { - if (data.error) { - addMessage('bot', `Error: ${data.error}`); - } else { - const ingredients = data.ingredients || []; - addMessage('bot', 'Please select ingredients to customize:'); - displayCustomizationIngredients(ingredients); - } - }) - .catch(error => { - addMessage('bot', `Error fetching ingredients: ${error.message}`); - }); - } - - function displayIngredientsList(ingredients) { - const chatMessages = document.getElementById('chatMessages'); - let ingredientsList = document.querySelector('.ingredients-list'); - if (!ingredientsList) { - ingredientsList = document.createElement('div'); - ingredientsList.className = 'ingredients-list'; - chatMessages.appendChild(ingredientsList); - } else { - ingredientsList.innerHTML = ''; - } - - ingredients.forEach(ingredient => { - const item = document.createElement('div'); - item.className = 'ingredient-item'; - const img = document.createElement('img'); - img.src = ingredient.image_url || 'https://via.placeholder.com/120'; - img.alt = ingredient.name; - const name = document.createElement('div'); - name.textContent = ingredient.name; - const button = document.createElement('button'); - button.textContent = 'Add'; - button.onclick = () => { - if (!selectedIngredients.some(i => i.name === ingredient.name)) { - selectedIngredients.push(ingredient); - displaySelectedIngredients(); + .then(response => response.json()) + .then(data => { + if (data.error) { + addMessage('bot', `Sorry, there was an error fetching ingredients: ${data.error}`); + } else { + const ingredients = data.ingredients || []; + addMessage('bot', 'Please select ingredients to customize:'); + displayCustomizationIngredients(ingredients); } - }; - item.appendChild(img); - item.appendChild(name); - item.appendChild(button); - ingredientsList.appendChild(item); - }); - - if (selectedIngredients.length > 0) { - let submitButton = document.querySelector('.submit-button'); - if (!submitButton) { - submitButton = document.createElement('button'); - submitButton.className = 'submit-button'; - submitButton.textContent = 'Submit Ingredients'; - submitButton.onclick = submitIngredients; - chatMessages.appendChild(submitButton); - } - } + }) + .catch(error => { + addMessage('bot', `Error: Unable to connect to the ingredient database. ${error.message}`); + }); } - function displayCustomizationIngredients(ingredients) { const chatMessages = document.getElementById('chatMessages'); + if (!chatMessages) { + console.error('Chat messages container not found for customization ingredients!'); + return; + } let ingredientsList = document.querySelector('.customization-ingredients-list'); if (!ingredientsList) { ingredientsList = document.createElement('div'); @@ -773,7 +2395,6 @@ } else { ingredientsList.innerHTML = ''; } - ingredients.forEach(ingredient => { const item = document.createElement('div'); item.className = 'ingredient-item'; @@ -785,7 +2406,7 @@ const button = document.createElement('button'); button.textContent = 'Add'; button.onclick = () => { - if (!selectedIngredients.some(i => i.name === ingredient.name)) { + if (!selectedIngredients.some(item => item.name === ingredient.name)) { selectedIngredients.push({ name: ingredient.name, image_url: ingredient.image_url }); displaySelectedCustomizationIngredients(); } @@ -795,38 +2416,14 @@ item.appendChild(button); ingredientsList.appendChild(item); }); - displaySelectedCustomizationIngredients(); } - - function displaySelectedIngredients() { - const chatMessages = document.getElementById('chatMessages'); - let selectedArea = document.querySelector('.selected-ingredients'); - if (!selectedArea) { - selectedArea = document.createElement('div'); - selectedArea.className = 'selected-ingredients'; - chatMessages.appendChild(selectedArea); - } else { - selectedArea.innerHTML = ''; - } - - selectedIngredients.forEach(ingredient => { - const div = document.createElement('div'); - div.textContent = ingredient.name; - const removeButton = document.createElement('button'); - removeButton.textContent = 'X'; - removeButton.className = 'remove-button'; - removeButton.onclick = () => { - selectedIngredients = selectedIngredients.filter(i => i.name !== ingredient.name); - displaySelectedIngredients(); - }; - div.appendChild(removeButton); - selectedArea.appendChild(div); - }); - } - function displaySelectedCustomizationIngredients() { const chatMessages = document.getElementById('chatMessages'); + if (!chatMessages) { + console.error('Chat messages container not found for selected customization ingredients!'); + return; + } let selectedArea = document.querySelector('.selected-customization-ingredients'); if (!selectedArea) { selectedArea = document.createElement('div'); @@ -835,28 +2432,31 @@ } else { selectedArea.innerHTML = ''; } - const selectedIngredientsText = selectedIngredients.length > 0 - ? `${selectedMenuItem.name} with ${selectedIngredients.map(i => i.name).join(', ')}` + ? `${selectedMenuItem.name} with ${selectedIngredients.map(ingredient => ingredient.name).join(', ')}` : selectedMenuItem.name; const ingredientsDiv = document.createElement('div'); ingredientsDiv.textContent = selectedIngredientsText; selectedArea.appendChild(ingredientsDiv); - selectedIngredients.forEach(ingredient => { const div = document.createElement('div'); div.textContent = ingredient.name; const removeButton = document.createElement('button'); removeButton.textContent = 'X'; - removeButton.className = 'remove-button'; + removeButton.style.marginLeft = '5px'; + removeButton.style.padding = '2px 5px'; + removeButton.style.backgroundColor = '#dc3545'; + removeButton.style.color = '#ffffff'; + removeButton.style.border = 'none'; + removeButton.style.borderRadius = '4px'; + removeButton.style.cursor = 'pointer'; removeButton.onclick = () => { - selectedIngredients = selectedIngredients.filter(i => i.name !== ingredient.name); + selectedIngredients = selectedIngredients.filter(item => item.name !== ingredient.name); displaySelectedCustomizationIngredients(); }; div.appendChild(removeButton); selectedArea.appendChild(div); }); - if (!document.querySelector('.submit-customization-button')) { const textarea = document.createElement('textarea'); textarea.placeholder = 'Enter any special instructions...'; @@ -868,39 +2468,124 @@ selectedArea.appendChild(submitButton); } } - - function submitIngredients() { - if (selectedIngredients.length === 0) { - addMessage('bot', 'No ingredients selected. Please choose some ingredients.'); + function submitCustomizationIngredients() { + if (!selectedMenuItem) { + addMessage('bot', 'No dish selected. Please choose a dish first.'); return; } - const ingredientNames = selectedIngredients.map(i => i.name.toLowerCase()).join(' '); - fetchMenuItems({ ingredient_names: ingredientNames }); + + const textarea = document.querySelector('.selected-customization-ingredients textarea'); + const instructions = textarea ? textarea.value.trim() : ''; + + fetch('/submit_customization_ingredients', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + menu_item: selectedMenuItem, + ingredients: selectedIngredients, + instructions: instructions + }) + }) + .then(response => response.json()) + .then(data => { + if (data.success) { + addToCart({ ...selectedMenuItem, instructions, ingredients: selectedIngredients }); + currentStep = 'post_cart'; + addMessage('bot', 'Customization submitted successfully! Item added to cart.'); + + // Redirect to the cart page + window.location.href = '/cart/cart'; // This will redirect the user to the cart page + } else { + addMessage('bot', `Error: ${data.error}`); + } + }) + .catch(error => { + addMessage('bot', `Error submitting customization: ${error.message}`); + }); + } + function fetchIngredients(foodPreference) { + fetch('/get_ingredients', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ dietary_preference: foodPreference }) + }) + .then(response => response.json()) + .then(data => { + if (data.error) { + addMessage('bot', `Sorry, there was an error fetching ingredients: ${data.error}`); + } else { + const ingredients = data.ingredients || []; + addMessage('bot', 'Please select ingredients:'); + displayIngredientsList(ingredients); + displaySelectedIngredients(); + } + }) + .catch(error => { + addMessage('bot', `Error: Unable to connect to the ingredient database. ${error.message}`); + }); } - function fetchMenuItems(params) { fetch('/get_menu_items', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(params) }) - .then(response => response.json()) - .then(data => { - if (data.error) { - addMessage('bot', `Error: ${data.error}`); - } else { - const menuItems = data.menu_items || []; - addMessage('bot', 'Here are some dishes based on your selection:'); - displayMenuItems(menuItems); - } - }) - .catch(error => { - addMessage('bot', `Error fetching menu items: ${error.message}`); + .then(response => response.json()) + .then(data => { + if (data.error) { + addMessage('bot', `Sorry, there was an error fetching menu items: ${data.error}`); + } else { + const menuItems = data.menu_items || []; + addMessage('bot', 'Here are some dishes based on your selection:'); + displayMenuItems(menuItems); + } + }) + .catch(error => { + addMessage('bot', `Error: Unable to connect to the menu database. ${error.message}`); + }); + } + function displayIngredientsList(ingredients) { + const chatMessages = document.getElementById('chatMessages'); + if (!chatMessages) { + console.error('Chat messages container not found for ingredients!'); + return; + } + let ingredientsList = document.querySelector('.ingredients-list'); + if (!ingredientsList) { + ingredientsList = document.createElement('div'); + ingredientsList.className = 'ingredients-list'; + chatMessages.appendChild(ingredientsList); + } else { + ingredientsList.innerHTML = ''; + } + ingredients.forEach(ingredient => { + const item = document.createElement('div'); + item.className = 'ingredient-item'; + const img = document.createElement('img'); + img.src = ingredient.image_url || 'https://via.placeholder.com/120'; + img.alt = ingredient.name; + const name = document.createElement('div'); + name.textContent = ingredient.name; + const button = document.createElement('button'); + button.textContent = 'Add'; + button.onclick = () => { + if (!selectedIngredients.some(item => item.name === ingredient.name)) { + selectedIngredients.push(ingredient); + displaySelectedIngredients(); + } + }; + item.appendChild(img); + item.appendChild(name); + item.appendChild(button); + ingredientsList.appendChild(item); }); } - function displayMenuItems(menuItems) { const chatMessages = document.getElementById('chatMessages'); + if (!chatMessages) { + console.error('Chat messages container not found for menu items!'); + return; + } let menuItemsList = document.querySelector('.menu-items-list'); if (!menuItemsList) { menuItemsList = document.createElement('div'); @@ -909,7 +2594,6 @@ } else { menuItemsList.innerHTML = ''; } - menuItems.forEach(item => { const menuItem = document.createElement('div'); menuItem.className = 'menu-item'; @@ -919,14 +2603,15 @@ const name = document.createElement('div'); name.textContent = item.name; const button = document.createElement('button'); - button.textContent = 'Select'; + button.textContent = 'Add to Cart'; button.onclick = () => { selectedMenuItem = item; - addMessage('bot', `Great selection! Would you like to customize your dish further?`); - displayOptions([ + addMessage('bot', `World-class selection! Would you like to customize your dish further?`); + const options = [ { text: 'Yes', class: 'green' }, { text: 'No', class: 'red' } - ]); + ]; + displayOptions(options); }; menuItem.appendChild(img); menuItem.appendChild(name); @@ -934,95 +2619,170 @@ menuItemsList.appendChild(menuItem); }); } - - function submitCustomizationIngredients() { - if (!selectedMenuItem) { - addMessage('bot', 'No dish selected. Please choose a dish first.'); + function displaySelectedIngredients() { + const chatMessages = document.getElementById('chatMessages'); + if (!chatMessages) { + console.error('Chat messages container not found for selected ingredients!'); return; } - - const textarea = document.querySelector('.selected-customization-ingredients textarea'); - const instructions = textarea ? textarea.value.trim() : ''; - const ingredientsList = selectedIngredients.map(i => i.name).join(', '); - const itemPrice = 10.00; // Fixed price for custom dishes - const itemImage = selectedMenuItem.image_url || 'https://via.placeholder.com/120'; - - const customDishPayload = { - menu_item: selectedMenuItem, - ingredients: selectedIngredients, - instructions: instructions, - itemPrice: itemPrice, - itemImage: itemImage - }; - - // Save the custom dish in Salesforce - fetch('/menu/save_custom_dish', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(customDishPayload) - }) - .then(response => response.json()) - .then(data => { - if (!data.success) { - throw new Error(data.error || 'Failed to save custom dish'); - } - - // Add to cart - const cartPayload = { - itemName: selectedMenuItem.name, - itemPrice: itemPrice, - itemImage: itemImage, - section: 'Customized Dish', - category: 'Custom', - addons: [], - instructions: instructions, - quantity: 1, - ingredients: ingredientsList + let selectedArea = document.querySelector('.selected-ingredients'); + if (!selectedArea) { + selectedArea = document.createElement('div'); + selectedArea.className = 'selected-ingredients'; + chatMessages.appendChild(selectedArea); + } else { + selectedArea.innerHTML = ''; + } + selectedIngredients.forEach(ingredient => { + const div = document.createElement('div'); + div.textContent = ingredient.name; + const removeButton = document.createElement('button'); + removeButton.textContent = 'X'; + removeButton.style.marginLeft = '5px'; + removeButton.style.padding = '2px 5px'; + removeButton.style.backgroundColor = '#dc3545'; + removeButton.style.color = '#ffffff'; + removeButton.style.border = 'none'; + removeButton.style.borderRadius = '4px'; + removeButton.style.cursor = 'pointer'; + removeButton.onclick = () => { + selectedIngredients = selectedIngredients.filter(item => item.name !== ingredient.name); + displaySelectedIngredients(); }; - - return fetch('/cart/add', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(cartPayload) + div.appendChild(removeButton); + selectedArea.appendChild(div); + }); + if (selectedIngredients.length > 0) { + let submitButton = document.querySelector('.submit-button'); + if (!submitButton) { + submitButton = document.createElement('button'); + submitButton.className = 'submit-button'; + submitButton.textContent = 'Submit Ingredients'; + submitButton.onclick = submitIngredients; + chatMessages.appendChild(submitButton); + } + } + } + function submitIngredients() { + if (selectedIngredients.length === 0) { + addMessage('bot', 'No ingredients selected. Please choose some ingredients.'); + return; + } + const ingredientNames = selectedIngredients.map(ingredient => ingredient.name.toLowerCase()).join(' '); + fetchMenuItems({ ingredient_names: ingredientNames }); + } + function addToCart(item) { + cart.push(item); + console.log('Cart:', cart); + displayCart(); + } + function displayCart() { + const chatMessages = document.getElementById('chatMessages'); + if (!chatMessages) { + console.error('Chat messages container not found for cart!'); + return; + } + let cartArea = document.querySelector('.cart-items'); + if (!cartArea) { + cartArea = document.createElement('div'); + cartArea.className = 'cart-items'; + chatMessages.appendChild(cartArea); + } else { + cartArea.innerHTML = ''; + } + if (cart.length > 0) { + const label = document.createElement('div'); + label.textContent = 'Cart:'; + cartArea.appendChild(label); + cart.forEach((item, index) => { + const itemDiv = document.createElement('div'); + itemDiv.className = 'cart-item'; + const img = document.createElement('img'); + img.src = item.image_url || 'https://via.placeholder.com/30'; + img.alt = item.name; + const name = document.createElement('div'); + const text = item.instructions + ? `${item.name} (${item.instructions})` + : item.name; + name.textContent = item.ingredients.length > 0 + ? `${text} with ${item.ingredients.map(i => i.name).join(', ')}` + : text; + const removeButton = document.createElement('button'); + removeButton.className = 'remove-button'; + removeButton.textContent = 'X'; + removeButton.onclick = () => { + cart.splice(index, 1); + displayCart(); + }; + itemDiv.appendChild(img); + itemDiv.appendChild(name); + itemDiv.appendChild(removeButton); + cartArea.appendChild(itemDiv); }); - }) - .then(response => response.json()) - .then(data => { - if (data.success) { - addMessage('bot', 'Customization submitted successfully! Item added to cart.'); - updateCartUI(data.cart); - // Redirect to menu page to see the custom dish - window.location.href = '/menu?category=Customized+Dish'; - } else { - throw new Error(data.error || 'Failed to add item to cart'); + let submitCartButton = document.querySelector('.submit-cart-button'); + if (!submitCartButton) { + submitCartButton = document.createElement('button'); + submitCartButton.className = 'submit-cart-button'; + submitCartButton.textContent = 'Submit Cart'; + submitCartButton.onclick = submitCart; + cartArea.appendChild(submitCartButton); } + } + } + function submitCart() { + if (cart.length === 0) { + addMessage('bot', 'Your cart is empty!'); + return; + } + fetch('/submit_customization_ingredients', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ items: cart }) }) - .catch(error => { - addMessage('bot', `Error: ${error.message}`); - }); + .then(response => response.json()) + .then(data => { + if (data.success) { + addMessage('bot', 'Cart submitted successfully!'); + cart = []; + displayCart(); + } else { + addMessage('bot', `Error submitting cart: ${data.error}`); + } + }) + .catch(error => { + addMessage('bot', `Error submitting cart: ${error.message}`); + }); } - function displayOptions(options) { - const chatMessages = document.getElementById('chatMessages'); - options.forEach(opt => { - const button = document.createElement('button'); - button.textContent = opt.text; - button.className = `option-button ${opt.class}`; - button.onclick = () => { - addMessage('user', opt.text); - conversation.push({ role: 'user', message: opt.text }); - handleResponse(opt.text); - }; - chatMessages.appendChild(button); - }); - chatMessages.scrollTop = chatMessages.scrollHeight; - } + const chatMessages = document.getElementById('chatMessages'); + if (!chatMessages) { + console.error('Chat messages container not found for options!'); + return; + } + console.log('Displaying options:', options); + options.forEach(opt => { + const button = document.createElement('button'); + button.textContent = opt.text; + button.className = `option-button ${opt.class}`; + button.onclick = () => { + addMessage('user', opt.text); + conversation.push({ role: 'user', message: opt.text }); + console.log(`User selected option: ${opt.text}`); + setTimeout(() => handleResponse(opt.text), 500); + }; + chatMessages.appendChild(button); + }); + chatMessages.appendChild(document.createElement('br')); + chatMessages.scrollTop = chatMessages.scrollHeight; + console.log('Options displayed'); + } document.getElementById('userInput').addEventListener('keypress', function(e) { if (e.key === 'Enter') { sendMessage(); } }); + console.log('Script loaded successfully'); \ No newline at end of file