import React, { useState, useRef, useEffect } from 'react'; import ReactMarkdown from 'react-markdown'; import Avatar from './Avatar.jsx'; import '../App.css'; const ChatInterface = ({ messages = [], setMessages = () => {}, onMessageSent = () => {}, activeConversationId, saveBotResponse, toLogin, onCreateNewConversation = () => {},onNewChat = () => {},refreshConversationList = () => {} }) => { const [inputMessage, setInputMessage] = useState(''); const [isLoading, setIsLoading] = useState(false); const messagesEndRef = useRef(null); const textareaRef = useRef(null); const [streamingText, setStreamingText] = useState(''); const [isStreaming, setIsStreaming] = useState(false); const [fullResponse, setFullResponse] = useState(''); const [tokenLimitReached, setTokenLimitReached] = useState(false); const [hasInteractionStarted, setHasInteractionStarted] = useState(false); const scrollToBottom = () => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }; useEffect(scrollToBottom, [messages]); const streamResponse = (response) => { setIsStreaming(true); setFullResponse(response); setStreamingText(''); // Garder une référence au message de streaming let streamMessageId = Date.now().toString(); setMessages(prev => [...prev, { sender: 'bot-streaming', text: '', id: streamMessageId }]); const totalCharacters = response.length; let charCount = 0; const streamInterval = setInterval(() => { if (charCount < totalCharacters) { charCount += 5; const fragment = response.substring(0, charCount); setMessages(prev => prev.map(msg => msg.id === streamMessageId ? { ...msg, text: fragment } : msg ) ); setStreamingText(fragment); } else { clearInterval(streamInterval); setIsStreaming(false); setMessages(prev => prev.map(msg => msg.id === streamMessageId ? { sender: 'bot', text: response, id: streamMessageId } : msg ) ); } }, 30); return () => clearInterval(streamInterval); }; const sendMessage = async (message) => { try { setHasInteractionStarted(true); setIsLoading(true); setMessages(prev => [...prev, { sender: 'user', text: message }]); const updatedConversationId = await onMessageSent(message); const chatRes = await fetch('/api/chat', { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify({ message, conversation_id: activeConversationId, skip_save: true }), }); const responseData = await chatRes.json(); if (responseData.error === 'token_limit_exceeded') { setIsLoading(false); setTokenLimitReached(true); setMessages(prev => [...prev, { sender: 'bot', text: "⚠️ **Limite de taille de conversation atteinte**\n\nCette conversation est devenue trop longue. Pour continuer à discuter, veuillez créer une nouvelle conversation." }]); return; } if (!chatRes.ok) throw new Error(`Chat API error ${chatRes.status}`); const { response: botResponse } = responseData; setIsLoading(false); streamResponse(botResponse); if (activeConversationId && typeof refreshConversationList === 'function') { refreshConversationList(); } if (updatedConversationId) { saveBotResponse(updatedConversationId, botResponse, true); } else if (activeConversationId) { saveBotResponse(activeConversationId, botResponse, true); } } catch (error) { console.error('Erreur:', error); setIsLoading(false); setMessages(prev => [...prev, { sender: 'bot', text: "Désolé, une erreur s'est produite. Veuillez réessayer." } ]); } }; const handleCreateNewConversation = () => { onNewChat(); setTokenLimitReached(false); setHasInteractionStarted(false); }; useEffect(() => { if (activeConversationId === null && messages.length === 0) { setHasInteractionStarted(false); } }, [activeConversationId, messages]); const handleSubmit = (e) => { e.preventDefault(); const txt = inputMessage.trim(); if (!txt) return; sendMessage(txt); setInputMessage(''); if (textareaRef.current) textareaRef.current.style.height = 'auto'; }; const isMarkdown = (text) => { return /(?:\*\*|__|##|\*|_|`|>|\d+\.\s|\-\s|\[.*\]\(.*\))/.test(text); }; return (
Bonjour ! Comment puis-je vous aider aujourd'hui ? 🧑⚕️