import React, { useState, useEffect, useRef } from 'react'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; // Separator unused, removing import { useAuthStore } from '@/features/auth/store/authStore'; // TODO: wsService should be replaced with websocketService or a proper chat service import { wsService } from '@/services/websocket'; import { apiClient } from '@/services/api/client'; import { useToast } from '@/hooks/useToast'; import { ChatMessage, ChatStats } from '@/types'; import { Send, MessageCircle, Users, Wifi, WifiOff, Loader2, Settings, Hash, } from 'lucide-react'; interface ChatInterfaceProps { room?: string; onRoomChange?: (room: string) => void; } export function ChatInterface({ room = 'general', onRoomChange: _onRoomChange, }: ChatInterfaceProps) { const { user } = useAuthStore(); const { success: showSuccess, error: showError } = useToast(); const [messages, setMessages] = useState([]); const [newMessage, setNewMessage] = useState(''); const [isConnected, setIsConnected] = useState(false); const [isLoading, setIsLoading] = useState(false); const [isSending, setIsSending] = useState(false); const [chatStats, setChatStats] = useState(null); const messagesEndRef = useRef(null); // Auto-scroll vers le bas const scrollToBottom = () => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }; useEffect(() => { scrollToBottom(); }, [messages]); // Gestion des événements WebSocket useEffect(() => { const handleChatConnected = () => { setIsConnected(true); showSuccess('Chat connecté'); }; const handleChatDisconnected = () => { setIsConnected(false); showError('Connexion au chat perdue'); }; const handleChatMessage = (message: ChatMessage) => { setMessages((prev) => [...prev, message]); }; const handleChatError = (error: any) => { console.error('Erreur chat:', error); showError('Une erreur est survenue dans le chat'); }; // S'abonner aux événements wsService.on('chat_connected', handleChatConnected); wsService.on('chat_disconnected', handleChatDisconnected); wsService.on('chat_message', handleChatMessage); wsService.on('chat_error', handleChatError); // Se connecter au chat wsService.connectChat(); if (room) { wsService.joinRoom(room); } // Charger les messages existants loadMessages(); loadChatStats(); return () => { wsService.off('chat_connected', handleChatConnected); wsService.off('chat_disconnected', handleChatDisconnected); wsService.off('chat_message', handleChatMessage); wsService.off('chat_error', handleChatError); }; }, [room]); const loadMessages = async () => { setIsLoading(true); try { const response = await apiClient.get<{ data: ChatMessage[] }>('/messages', { params: { conversation_id: room, limit: 50 }, }); // apiClient unwrap déjà le format { success, data } const data = response.data; setMessages(data.data || []); } catch (error) { console.error('Erreur lors du chargement des messages:', error); } finally { setIsLoading(false); } }; const loadChatStats = async () => { try { const response = await apiClient.get<{ active_users: number; total_messages: number; rooms_active: number; }>('/chat/stats'); // apiClient unwrap déjà le format { success, data } const data = response.data; setChatStats(data); } catch (error) { console.error('Erreur lors du chargement des statistiques:', error); } }; const handleSendMessage = async (e: React.FormEvent) => { e.preventDefault(); if (!newMessage.trim() || !user || isSending) return; setIsSending(true); try { // Envoyer via WebSocket wsService.sendMessage(room, newMessage.trim()); // Aussi envoyer via API REST pour la persistance await apiClient.post('/messages', { conversation_id: room, content: newMessage.trim(), }); setNewMessage(''); } catch (error) { console.error("Erreur lors de l'envoi du message:", error); showError("Impossible d'envoyer le message"); } finally { setIsSending(false); } }; const formatTimestamp = (timestamp: string) => { const date = new Date(timestamp); return date.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit', }); }; return (
{/* En-tête du chat - Card Header removed custom wrapper if CardHeader handles padding */}
{room}
{isConnected ? ( <> Connecté ) : ( <> Déconnecté )}
{chatStats && (
{chatStats.active_users || 0}
{chatStats.total_messages || 0}
)}
{/* Zone des messages */}
{isLoading ? (
) : messages.length === 0 ? (

Aucun message dans ce salon

Soyez le premier à écrire quelque chose !

) : (
{messages.map((message, index) => (
{(message.sender_id || '?').charAt(0).toUpperCase()}
{message.sender_id} {formatTimestamp(message.created_at)}

{message.content}

))}
)}
{/* Zone de saisie */}
setNewMessage(e.target.value)} placeholder={`Écrire dans #${room}...`} disabled={!isConnected || isSending} className="flex-1" />
); }