const state = { step: 'tileType', tileType: null, area: null, tileLength: null, tileWidth: null }; const chatArea = document.getElementById('chat-area'); const userInput = document.getElementById('user-input'); const recommendations = document.getElementById('recommendations'); const resetBtn = document.getElementById('reset-btn'); resetBtn.addEventListener('click', resetConversation); userInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') sendMessage(); }); resetConversation(); function resetConversation() { Object.assign(state, { step: 'tileType', tileType: null, area: null, tileLength: null, tileWidth: null }); chatArea.innerHTML = `
`; recommendations.innerHTML = ''; } function selectTileType(type) { state.tileType = type; state.step = 'area'; addMessage('user', `${type.charAt(0).toUpperCase() + type.slice(1)} tiles`); showTyping(); setTimeout(() => { hideTyping(); addMessage('bot', 'Great! What is the total area to cover (in sq.ft)?'); }, 800); } function sendMessage() { const message = userInput.value.trim(); if (!message) return; addMessage('user', message); userInput.value = ''; processUserMessage(message); } function processUserMessage(message) { showTyping(); setTimeout(() => { hideTyping(); if (state.step === 'area') { const area = parseFloat(message); if (isNaN(area) || area <= 0) { return addMessage('bot', '❗ Please enter a valid positive number for area (e.g., 100).'); } state.area = area; state.step = 'tileLength'; addMessage('bot', 'Now enter the tile length (in feet):'); } else if (state.step === 'tileLength') { const length = parseFloat(message); if (isNaN(length) || length <= 0) { return addMessage('bot', '❗ Please enter a valid positive number for tile length.'); } state.tileLength = length; state.step = 'tileWidth'; addMessage('bot', 'Now enter the tile width (in feet):'); } else if (state.step === 'tileWidth') { const width = parseFloat(message); if (isNaN(width) || width <= 0) { return addMessage('bot', '❗ Please enter a valid positive number for tile width.'); } state.tileWidth = width; calculateTiles(); } }, 800); } function calculateTiles() { const { tileLength, tileWidth, area, tileType } = state; const tileArea = tileLength * tileWidth; if (tileArea <= 0) { return addMessage('bot', `❗ Invalid tile dimensions. Length × width must be greater than 0.`); } if (tileArea > area) { return addMessage('bot', `⚠ The tile size (${tileLength}×${tileWidth} = ${tileArea} sq.ft) is larger than the total area (${area} sq.ft). Please enter smaller tile dimensions.`); } if (tileArea > 20) { addMessage('bot', `🔍 That's a large tile (${tileArea.toFixed(2)} sq.ft). Please confirm the size is correct.`); } const aspectRatio = Math.max(tileLength / tileWidth, tileWidth / tileLength); if (aspectRatio > 10) { addMessage('bot', `📐 This tile has a very high aspect ratio (${aspectRatio.toFixed(1)}:1). Please double-check if that's correct.`); } const numTiles = Math.ceil((area / tileArea) * 1.1); const numBoxes = Math.ceil(numTiles / 10); chatArea.insertAdjacentHTML('beforeend', ` `); state.step = 'complete'; const sizeLabel = `${Math.round(tileLength * 304.8)}x${Math.round(tileWidth * 304.8)} MM`; fetch('/recommend', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ tile_type: tileType, coverage: tileArea, area: area, preferred_sizes: [sizeLabel] }) }) .then(res => res.json()) .then(data => { if (data.recommended_products?.length) { loadProductRecommendations(data.recommended_products); } else { recommendations.innerHTML = `