feat(pos/chat): add 4 AI chatbot improvements — symptom diagnosis, smart quotes, photo ID, multilanguage
1. Symptom diagnosis: AI now detects vehicle symptoms and suggests probable parts 2. Smart quotations: "cotizame frenos completos" returns multiple search_queries (pipe-separated), backend searches each term and deduplicates 3. Photo identification: camera button in chat widget uploads image and sends placeholder prompt (ready for vision model) 4. Multilanguage: AI detects user language and responds accordingly, search_query always in English Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -39,6 +39,8 @@
|
||||
</div>
|
||||
<div class="chat-input-area">
|
||||
<textarea class="chat-input" id="chatInput" placeholder="Ej: Balatas para Tsuru 2015..." rows="1"></textarea>
|
||||
<input type="file" id="chatImageInput" accept="image/*" capture="environment" style="display:none;">
|
||||
<button class="chat-cam-btn" id="chatCam" aria-label="Enviar foto de parte" title="Identificar parte por foto">📷</button>
|
||||
${hasSpeechAPI ? '<button class="chat-mic-btn" id="chatMic" aria-label="Entrada por voz" title="Entrada por voz">🎤</button>' : ''}
|
||||
<button class="chat-send-btn" id="chatSend" aria-label="Enviar">▶</button>
|
||||
</div>
|
||||
@@ -58,6 +60,12 @@
|
||||
}
|
||||
});
|
||||
|
||||
// Camera button — identify part by photo
|
||||
document.getElementById('chatCam').addEventListener('click', function () {
|
||||
document.getElementById('chatImageInput').click();
|
||||
});
|
||||
document.getElementById('chatImageInput').addEventListener('change', handleImageUpload);
|
||||
|
||||
// Mic button (only if Speech API available)
|
||||
if (hasSpeechAPI) {
|
||||
document.getElementById('chatMic').addEventListener('click', toggleVoice);
|
||||
@@ -162,6 +170,82 @@
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
// ─── Image Upload (Part identification placeholder) ───
|
||||
function handleImageUpload(e) {
|
||||
const file = e.target.files && e.target.files[0];
|
||||
if (!file) return;
|
||||
|
||||
// Reset input so the same file can be selected again
|
||||
e.target.value = '';
|
||||
|
||||
// Validate file type and size (max 5MB)
|
||||
if (!file.type.startsWith('image/')) {
|
||||
addBubble('Solo se permiten imagenes.', 'ai');
|
||||
return;
|
||||
}
|
||||
if (file.size > 5 * 1024 * 1024) {
|
||||
addBubble('La imagen es muy grande (max 5MB).', 'ai');
|
||||
return;
|
||||
}
|
||||
|
||||
// Show image thumbnail in chat
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (ev) {
|
||||
const container = document.getElementById('chatMessages');
|
||||
const typing = document.getElementById('chatTyping');
|
||||
const div = document.createElement('div');
|
||||
div.className = 'chat-msg user chat-msg-image';
|
||||
div.innerHTML = '<img src="' + ev.target.result + '" alt="Foto de parte" style="max-width:180px;max-height:140px;border-radius:8px;display:block;margin-bottom:4px;">'
|
||||
+ '<span>Identificar esta parte</span>';
|
||||
container.insertBefore(div, typing);
|
||||
scrollToBottom();
|
||||
|
||||
// Send to AI as a text description (vision model placeholder)
|
||||
const photoPrompt = 'El usuario envio una foto de una parte automotriz. Describe que parte podria ser y sugiere busquedas.';
|
||||
history.push({ role: 'user', content: photoPrompt });
|
||||
if (history.length > 20) history.splice(0, 2);
|
||||
|
||||
isSending = true;
|
||||
document.getElementById('chatSend').disabled = true;
|
||||
showTyping(true);
|
||||
|
||||
const token = getToken();
|
||||
fetch('/pos/api/chat', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + token
|
||||
},
|
||||
body: JSON.stringify({
|
||||
message: photoPrompt,
|
||||
history: history.slice(-10)
|
||||
})
|
||||
})
|
||||
.then(function (resp) { return resp.json(); })
|
||||
.then(function (data) {
|
||||
const aiMsg = data.response || 'No pude identificar la parte. Intenta describirla con texto.';
|
||||
addBubble(aiMsg, 'ai');
|
||||
history.push({ role: 'assistant', content: aiMsg });
|
||||
|
||||
if (data.vehicle && data.vehicle.brand_id) {
|
||||
addVehicleBanner(data.vehicle);
|
||||
}
|
||||
if (data.search_results && data.search_results.length > 0) {
|
||||
addPartResults(data.search_results);
|
||||
}
|
||||
})
|
||||
.catch(function (err) {
|
||||
addBubble('Error al procesar imagen: ' + err.message, 'ai');
|
||||
})
|
||||
.finally(function () {
|
||||
isSending = false;
|
||||
document.getElementById('chatSend').disabled = false;
|
||||
showTyping(false);
|
||||
});
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
|
||||
function toggleChat() {
|
||||
isOpen = !isOpen;
|
||||
const panel = document.getElementById('chatPanel');
|
||||
|
||||
Reference in New Issue
Block a user