"use client"; import React, { useState, useEffect, useRef } from 'react'; import { Send, User as UserIcon, Building2, ChevronLeft, Loader2, MessageSquare, Archive, Inbox, ArchiveRestore, Flag } from 'lucide-react'; import { useUser } from '../UserProvider'; import { toast } from 'react-hot-toast'; interface Message { id: string; content: string; senderId: string; createdAt: string; sender: { name: string; email?: string; avatar?: string; }; } interface Conversation { id: string; business: { id: string; name: string; logoUrl: string; ownerId: string; }; participants: { isArchived: boolean; user: { id: string; name: string; email?: string; avatar?: string; }; }[]; messages: Message[]; } interface DashboardMessagesProps { onMessagesRead?: () => void; initialConversationId?: string | null; } const DashboardMessages = ({ onMessagesRead, initialConversationId }: DashboardMessagesProps) => { const { user } = useUser(); const [conversations, setConversations] = useState([]); const [selectedConversation, setSelectedConversation] = useState(null); const [messages, setMessages] = useState([]); const [newMessage, setNewMessage] = useState(''); const [loading, setLoading] = useState(true); const [sending, setSending] = useState(false); const [isMobileListVisible, setIsMobileListVisible] = useState(true); const [showArchived, setShowArchived] = useState(false); const messagesEndRef = useRef(null); useEffect(() => { fetchConversations(); }, []); useEffect(() => { if (selectedConversation) { fetchMessages(selectedConversation.id); } }, [selectedConversation]); useEffect(() => { scrollToBottom(); }, [messages]); const scrollToBottom = () => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }; const fetchConversations = async () => { try { const res = await fetch('/api/conversations', { headers: { 'x-user-id': user?.id || '' } }); const data = await res.json(); if (!data.error) { setConversations(data); // Handle initial auto-selection if (initialConversationId) { const found = data.find((c: Conversation) => c.id === initialConversationId); if (found) { setSelectedConversation(found); setIsMobileListVisible(false); } } } } catch (error) { console.error('Error fetching conversations:', error); } finally { setLoading(false); } }; const fetchMessages = async (id: string) => { try { const res = await fetch(`/api/conversations/${id}`, { headers: { 'x-user-id': user?.id || '' } }); const data = await res.json(); if (!data.error) { setMessages(data); // After fetching messages (which marks them as read in the backend), // notify the parent to refresh the unread count badge if (onMessagesRead) onMessagesRead(); } } catch (error) { console.error('Error fetching messages:', error); } }; const handleSendMessage = async (e: React.FormEvent) => { e.preventDefault(); if (!newMessage.trim() || !selectedConversation || sending) return; setSending(true); try { const res = await fetch('/api/messages', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-user-id': user?.id || '' }, body: JSON.stringify({ conversationId: selectedConversation.id, content: newMessage }) }); const data = await res.json(); if (!data.error) { setMessages([...messages, { ...data, sender: { name: user?.name || '' } }]); setNewMessage(''); // Refresh conversations list to update last message/order fetchConversations(); } else { toast.error(data.error); } } catch (error) { toast.error('Erreur lors de l\'envoi'); } finally { setSending(false); } }; const handleToggleArchive = async (conversation: Conversation) => { const isCurrentlyArchived = conversation.participants.find(p => p.user.id === user?.id)?.isArchived; try { const res = await fetch(`/api/conversations/${conversation.id}/archive`, { method: 'PATCH', headers: { 'Content-Type': 'application/json', 'x-user-id': user?.id || '' }, body: JSON.stringify({ archived: !isCurrentlyArchived }) }); if (res.ok) { toast.success(isCurrentlyArchived ? 'Conversation désarchivée' : 'Conversation archivée'); fetchConversations(); // If we archived the currently selected conversation, close it if (!isCurrentlyArchived && selectedConversation?.id === conversation.id) { setSelectedConversation(null); } } } catch (error) { toast.error('Erreur lors de l\'archivage'); } }; const handleReportMessage = async (messageId: string) => { if (!window.confirm('Voulez-vous vraiment signaler ce message aux administrateurs ?')) return; try { const res = await fetch(`/api/messages/${messageId}/report`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-user-id': user?.id || '' }, body: JSON.stringify({ reason: "Signalement rapide" }) }); const data = await res.json(); if (res.ok) { toast.success('Message signalé avec succès'); } else { toast.error(data.error || 'Erreur lors du signalement'); } } catch (error) { toast.error('Erreur réseau lors du signalement'); } }; if (loading) { return (
); } return (
{/* 1. Conversations Sidebar */}

Messages

{(() => { const filtered = conversations.filter(conv => { const myParticipant = conv.participants.find(p => p.user.id === user?.id); return !!myParticipant?.isArchived === showArchived; }); if (filtered.length === 0) { return (

{showArchived ? 'Aucune conversation archivée.' : 'Aucune conversation pour le moment.'}

); } return filtered.map((conv) => { const lastMsg = conv.messages[0]; const isSelected = selectedConversation?.id === conv.id; // Determine display name: If current user is business owner, show customer name const isOwner = user?.id === conv.business.ownerId; const partner = conv.participants.find(p => p.user.id !== user?.id)?.user; const displayName = isOwner ? partner?.name : conv.business.name; const displayAvatar = isOwner ? partner?.avatar : conv.business.logoUrl; return ( ); }); })()}
{/* 2. Chat Window */}
{selectedConversation ? ( <> {/* Chat Header */}
{/* Determine header display */} {(() => { const isOwner = user?.id === selectedConversation.business.ownerId; const partner = selectedConversation.participants.find(p => p.user.id !== user?.id)?.user; const displayName = isOwner ? partner?.name : selectedConversation.business.name; const displayAvatar = isOwner ? partner?.avatar : selectedConversation.business.logoUrl; return ( <>

{displayName} {isOwner && "(Client)"}

En ligne
); })()}
{/* Messages Area */}
{messages.map((msg) => { // Triple-check identity: ID, Email, or Name const isMe = user && ( msg.senderId === user.id || (msg.sender?.email && msg.sender.email === user.email) || (msg.sender?.name && msg.sender.name === user.name) ); return (
{isMe ? 'Vous' : (user?.id === selectedConversation.business.ownerId ? (selectedConversation.participants.find(p => p.user.id !== user?.id)?.user.name || 'Client') : selectedConversation.business.name )}

{msg.content}

{new Date(msg.createdAt).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} {!isMe && ( )}
); })}
{/* Input Area */}
setNewMessage(e.target.value)} placeholder="Écrivez votre message..." className="flex-1 bg-gray-100 border-none rounded-full px-4 py-2 text-sm focus:ring-2 focus:ring-brand-500 outline-none" />
) : (

Votre messagerie

Sélectionnez une conversation pour commencer à échanger avec vos entrepreneurs préférés.

)}
); }; export default DashboardMessages;