document.addEventListener('DOMContentLoaded', () => { const generateBtn = document.getElementById('generate-btn'); const productDesc = document.getElementById('product-desc'); const resultsSection = document.getElementById('results-section'); const loader = document.getElementById('loader'); // Accordion Logic document.querySelectorAll('.accordion-header').forEach(header => { header.addEventListener('click', () => { const item = header.parentElement; item.classList.toggle('active'); const content = item.querySelector('.accordion-content'); if (item.classList.contains('active')) { content.style.maxHeight = content.scrollHeight + "px"; } else { content.style.maxHeight = "0"; } }); }); generateBtn.addEventListener('click', async () => { const desc = productDesc.value.trim(); if (!desc) return alert("Please enter a product description!"); // UI Reset resultsSection.classList.add('hidden'); loader.classList.remove('hidden'); generateBtn.disabled = true; const loaderMessage = document.getElementById('loader-message'); const loadingSteps = [ "Parsing item description...", "Searching DuckDuckGo for context...", "Retrieving official Canadian Tariff schedules...", "Running self-consistency ensemble 1 of 3...", "Running self-consistency ensemble 2 of 3...", "Running self-consistency ensemble 3 of 3...", "Cross-verifying confidence and vote share...", "Finalizing HTS code and extracting reasoning..." ]; let stepIdx = 0; loaderMessage.textContent = loadingSteps[0]; const loaderInterval = setInterval(() => { stepIdx++; if (stepIdx < loadingSteps.length) { loaderMessage.style.opacity = '0'; setTimeout(() => { loaderMessage.textContent = loadingSteps[stepIdx]; loaderMessage.style.transition = 'opacity 0.3s ease'; loaderMessage.style.opacity = '1'; }, 300); } else { loaderMessage.style.opacity = '0'; setTimeout(() => { loaderMessage.textContent = "Almost done... rendering final classification."; loaderMessage.style.opacity = '1'; }, 300); } }, 3000); try { const res = await fetch('/api/classify', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ description: desc }) }); const data = await res.json(); if (res.ok) { renderResults(data); } else { alert("Error: " + data.detail); } } catch (err) { console.error(err); alert("An error occurred while calling the API."); } finally { clearInterval(loaderInterval); loader.classList.add('hidden'); generateBtn.disabled = false; } }); function renderResults(data) { resultsSection.classList.remove('hidden'); // HTS Code & Warning document.getElementById('hts-code-display').textContent = data.final_hts_code || "XXXX.XX.XX.XX"; const warningBox = document.getElementById('escalation-warning'); if (data.escalation_needed) { warningBox.classList.remove('hidden'); } else { warningBox.classList.add('hidden'); } // Confidence Grid renderConfidenceGrid(data.element_confidences); // Reasoning & Context document.getElementById('reasoning-text').innerText = data.reasoning_steps || "No reasoning provided."; document.getElementById('search-queries').innerHTML = (data.search_queries || []).map(q => `
  • ${q}
  • `).join(''); document.getElementById('web-context').innerText = data.search_results || "None."; document.getElementById('rag-context').innerText = data.rag_context || "None."; // Chatbot Initialization const chatContainer = document.getElementById('escalation-chat-container'); const chatMessages = document.getElementById('chat-messages'); const chatInput = document.getElementById('chat-input'); const sendChatBtn = document.getElementById('send-chat-btn'); chatMessages.innerHTML = ""; const finalCodeContainer = document.getElementById('final-code-container'); const reasoningPanelContainer = document.getElementById('reasoning-panel-container'); if (data.escalation_needed) { chatContainer.classList.remove('hidden'); finalCodeContainer.classList.add('hidden'); reasoningPanelContainer.classList.add('hidden'); window.currentEscalationContext = { description: document.getElementById('product-desc').value.trim(), search_results: data.search_results, rag_context: data.rag_context, chat_history: [] }; appendChatMessage("assistant", data.escalation_question || "I need more details to finalize this code."); } else { chatContainer.classList.add('hidden'); finalCodeContainer.classList.remove('hidden'); reasoningPanelContainer.classList.remove('hidden'); } // Chat Handlers sendChatBtn.onclick = async () => { const text = chatInput.value.trim(); if (!text) return; appendChatMessage("user", text); chatInput.value = ""; sendChatBtn.disabled = true; try { const res = await fetch('/api/escalation', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(window.currentEscalationContext) }); const escData = await res.json(); if (res.ok && escData.success) { const r = escData.result; if (r.is_final) { appendChatMessage("assistant", "Excellent, I have enough confidence now! Updating the final code."); document.getElementById('hts-code-display').textContent = r.data.final_hts_code; document.getElementById('escalation-warning').classList.add('hidden'); document.getElementById('chat-input-area').classList.add('hidden'); // Show AI reasoning chain if (r.data.reasoning) { document.getElementById('reasoning-text').innerText = r.data.reasoning; } // Re-render confidence grid with human-verified values if (r.data.element_confidences) { renderConfidenceGrid(r.data.element_confidences); } // Output the final HTS code and reasoning, show the confidence grid document.getElementById('final-code-container').classList.remove('hidden'); document.getElementById('reasoning-panel-container').classList.remove('hidden'); document.getElementById('confidence-grid').classList.remove('hidden'); // Collapse the Chat Accordion const chatAccordionItem = document.getElementById('chat-accordion-item'); if (chatAccordionItem) { chatAccordionItem.classList.remove('active'); const content = chatAccordionItem.querySelector('.accordion-content'); if (content) content.style.maxHeight = "0"; } } else { appendChatMessage("assistant", r.message); } } else { alert("Chat error: " + (escData.detail || "Unknown error")); } } catch (err) { console.error(err); alert("Error sending chat message."); } finally { sendChatBtn.disabled = false; } }; chatInput.onkeypress = (e) => { if (e.key === 'Enter') sendChatBtn.click(); } } function renderConfidenceGrid(element_confidences) { if (!element_confidences) return; const grid = document.getElementById('confidence-grid'); grid.innerHTML = ''; const order = [ { key: 'chapter', label: 'Chapter' }, { key: 'heading', label: 'Heading' }, { key: 'subheading', label: 'Subheading' }, { key: 'additional_subheading', label: 'Additional' }, { key: 'statistical_suffix', label: 'Statistical' } ]; order.forEach(item => { const conf = element_confidences[item.key]; if (!conf) return; const isLow = conf.score < 0.6; const card = document.createElement('div'); card.className = `conf-card ${isLow ? 'low-conf' : ''}`; card.innerHTML = `
    ${item.label}
    ${conf.value}
    ${conf.confidence}
    `; grid.appendChild(card); }); } function appendChatMessage(role, text) { const chatMessages = document.getElementById('chat-messages'); const div = document.createElement('div'); div.className = `chat-msg msg-${role}`; if (role === 'assistant' && typeof window.marked !== 'undefined') { div.innerHTML = window.marked.parse(text); } else { div.textContent = text; } chatMessages.appendChild(div); chatMessages.scrollTop = chatMessages.scrollHeight; if (window.currentEscalationContext) { window.currentEscalationContext.chat_history.push({ role, content: text }); } } });