/** * CHATBOT IA - Client JavaScript */ class ChatbotIA { constructor(tentativeId) { this.tentativeId = tentativeId; this.currentQuestionId = null; this.helpRemaining = 3; this.isLoading = false; this.initElements(); this.attachEvents(); } initElements() { this.btnOpenChat = document.getElementById('btn-open-chat'); this.modalChat = document.getElementById('modal-chat'); this.btnCloseChat = document.getElementById('btn-close-chat'); this.chatMessages = document.getElementById('chat-messages'); this.chatInput = document.getElementById('chat-input'); this.btnSend = document.getElementById('btn-send'); this.helpRemainingSpan = document.getElementById('help-remaining'); } attachEvents() { // Ouvrir chat this.btnOpenChat?.addEventListener('click', () => this.ouvrirChat()); // Fermer chat this.btnCloseChat?.addEventListener('click', () => this.fermerChat()); // Clic en dehors du modal this.modalChat?.addEventListener('click', (e) => { if (e.target === this.modalChat) this.fermerChat(); }); // Envoyer message this.btnSend?.addEventListener('click', () => this.envoyerMessage()); // Enter pour envoyer (Shift+Enter pour nouvelle ligne) this.chatInput?.addEventListener('keypress', (e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); this.envoyerMessage(); } }); } ouvrirChat() { // Récupérer l'ID de la question actuelle this.currentQuestionId = this.getCurrentQuestionId(); if (!this.currentQuestionId) { alert('Erreur : impossible de déterminer la question actuelle'); return; } this.modalChat.classList.add('show'); this.chatInput.focus(); } fermerChat() { this.modalChat.classList.remove('show'); } getCurrentQuestionId() { // À adapter selon ton code de passer_evaluation.php // Option 1 : Variable globale JS if (typeof currentQuestionId !== 'undefined') { return currentQuestionId; } // Option 2 : Data attribute const questionElement = document.querySelector('[data-question-id]'); if (questionElement) { return questionElement.dataset.questionId; } // Option 3 : Input hidden const hiddenInput = document.querySelector('input[name="id_question"]'); if (hiddenInput) { return hiddenInput.value; } return null; } async envoyerMessage() { const message = this.chatInput.value.trim(); if (!message || this.isLoading) return; // Afficher message utilisateur this.ajouterMessage(message, 'user'); this.chatInput.value = ''; // Loading this.isLoading = true; this.btnSend.disabled = true; this.afficherTypingIndicator(); try { const response = await fetch('/mathematiques/api/chatbot.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ id_tentative: this.tentativeId, id_question: this.currentQuestionId, message: message }) }); const data = await response.json(); // Retirer typing indicator this.retirerTypingIndicator(); if (data.error) { this.ajouterMessage(data.message || data.error, 'system'); if (data.remaining === 0) { this.helpRemaining = 0; this.updateHelpBadge(); setTimeout(() => this.fermerChat(), 3000); } } else { this.ajouterMessage(data.response, 'assistant'); this.helpRemaining = data.remaining; this.updateHelpBadge(); if (this.helpRemaining === 0) { setTimeout(() => { this.ajouterMessage( 'Tu as utilisé toute ton aide pour cette question (3/3). Continue, tu peux le faire ! 💪', 'system' ); setTimeout(() => this.fermerChat(), 3000); }, 500); } } } catch (error) { console.error('Erreur chatbot:', error); this.retirerTypingIndicator(); this.ajouterMessage('❌ Erreur de connexion au serveur.', 'system'); } finally { this.isLoading = false; this.btnSend.disabled = false; this.chatInput.focus(); } } ajouterMessage(texte, type) { const msgDiv = document.createElement('div'); msgDiv.className = `message message-${type}`; msgDiv.textContent = texte; this.chatMessages.appendChild(msgDiv); this.scrollToBottom(); } afficherTypingIndicator() { const typingDiv = document.createElement('div'); typingDiv.className = 'typing-indicator'; typingDiv.id = 'typing-indicator'; typingDiv.innerHTML = ` `; this.chatMessages.appendChild(typingDiv); this.scrollToBottom(); } retirerTypingIndicator() { document.getElementById('typing-indicator')?.remove(); } scrollToBottom() { this.chatMessages.scrollTop = this.chatMessages.scrollHeight; } updateHelpBadge() { if (this.helpRemainingSpan) { this.helpRemainingSpan.textContent = this.helpRemaining; } } } // Initialisation automatique si tentativeId existe document.addEventListener('DOMContentLoaded', () => { // À adapter : récupérer tentativeId de ton code const tentativeId = document.querySelector('[data-tentative-id]')?.dataset.tentativeId; if (tentativeId) { window.chatbot = new ChatbotIA(tentativeId); } });