2025-12-03 21:56:50 +00:00
|
|
|
import React, { useEffect } from 'react';
|
|
|
|
|
import { useChatStore } from '../store/chatStore';
|
|
|
|
|
import { useAuthStore } from '@/features/auth/store/authStore';
|
|
|
|
|
import { apiClient } from '@/lib/apiClient';
|
|
|
|
|
import { useQuery } from '@tanstack/react-query';
|
|
|
|
|
import { cn } from '@/lib/utils';
|
|
|
|
|
import { Loader2 } from 'lucide-react';
|
|
|
|
|
|
|
|
|
|
interface ConversationItemProps {
|
|
|
|
|
conversation: { id: string; name: string; type: string };
|
|
|
|
|
onSelect: (id: string) => void;
|
|
|
|
|
isSelected: boolean;
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-13 02:34:34 +00:00
|
|
|
const ConversationItem: React.FC<ConversationItemProps> = ({
|
|
|
|
|
conversation,
|
|
|
|
|
onSelect,
|
|
|
|
|
isSelected,
|
|
|
|
|
}) => {
|
2025-12-03 21:56:50 +00:00
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
onClick={() => onSelect(conversation.id)}
|
|
|
|
|
className={cn(
|
2025-12-13 02:34:34 +00:00
|
|
|
'flex items-center p-3 rounded-lg cursor-pointer transition-colors',
|
|
|
|
|
isSelected ? 'bg-blue-100 text-blue-800' : 'hover:bg-gray-100',
|
2025-12-03 21:56:50 +00:00
|
|
|
)}
|
|
|
|
|
>
|
2025-12-13 02:34:34 +00:00
|
|
|
<span className="font-medium">
|
|
|
|
|
{conversation.name || `Conversation ${conversation.id.substring(0, 8)}`}
|
|
|
|
|
</span>
|
2025-12-03 21:56:50 +00:00
|
|
|
{/* <span className="ml-auto text-sm opacity-70">3</span> */}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const ChatSidebar: React.FC = () => {
|
2025-12-13 02:34:34 +00:00
|
|
|
const { user } = useAuthStore();
|
|
|
|
|
const userId = user?.id;
|
|
|
|
|
const {
|
|
|
|
|
conversations,
|
|
|
|
|
currentConversationId,
|
|
|
|
|
setCurrentConversation,
|
|
|
|
|
addConversation,
|
|
|
|
|
} = useChatStore();
|
2025-12-03 21:56:50 +00:00
|
|
|
|
|
|
|
|
// Fetch conversations from backend
|
|
|
|
|
const { data, isLoading, error } = useQuery({
|
|
|
|
|
queryKey: ['chatConversations', userId],
|
|
|
|
|
queryFn: async () => {
|
|
|
|
|
if (!userId) return [];
|
|
|
|
|
const response = await apiClient.get('/conversations');
|
|
|
|
|
return response.data.conversations;
|
|
|
|
|
},
|
|
|
|
|
enabled: !!userId,
|
|
|
|
|
});
|
|
|
|
|
|
2025-12-13 02:34:34 +00:00
|
|
|
useEffect(() => {
|
|
|
|
|
if (data) {
|
|
|
|
|
data.forEach((conv: any) =>
|
|
|
|
|
addConversation({
|
|
|
|
|
id: conv.id,
|
|
|
|
|
name: conv.name,
|
|
|
|
|
type: conv.type,
|
|
|
|
|
participants: conv.participants,
|
|
|
|
|
unread_count: 0, // Default for now
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}, [data, addConversation]);
|
|
|
|
|
|
2025-12-03 21:56:50 +00:00
|
|
|
if (isLoading) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="w-64 border-r bg-gray-50 flex items-center justify-center">
|
|
|
|
|
<Loader2 className="animate-spin text-blue-500" size={24} />
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="w-64 border-r bg-gray-50 flex items-center justify-center text-red-500 p-4">
|
2025-12-13 02:34:34 +00:00
|
|
|
Erreur:{' '}
|
|
|
|
|
{(error as any).message || 'Impossible de charger les conversations'}
|
2025-12-03 21:56:50 +00:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="w-64 border-r bg-gray-50 flex flex-col">
|
|
|
|
|
<div className="p-4 border-b">
|
|
|
|
|
<h2 className="text-xl font-bold">Conversations</h2>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex-1 overflow-y-auto p-2">
|
|
|
|
|
{conversations.length === 0 ? (
|
|
|
|
|
<div className="text-gray-500 text-sm p-2">
|
|
|
|
|
Aucune conversation. Créez-en une !
|
|
|
|
|
</div>
|
|
|
|
|
) : (
|
|
|
|
|
conversations.map((conv) => (
|
|
|
|
|
<ConversationItem
|
|
|
|
|
key={conv.id}
|
|
|
|
|
conversation={conv}
|
|
|
|
|
onSelect={setCurrentConversation}
|
|
|
|
|
isSelected={conv.id === currentConversationId}
|
|
|
|
|
/>
|
|
|
|
|
))
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
<div className="p-4 border-t">
|
|
|
|
|
{/* Button to create new conversation (TODO) */}
|
|
|
|
|
<button className="w-full p-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700">
|
|
|
|
|
Nouvelle Conversation
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
2025-12-13 02:34:34 +00:00
|
|
|
};
|