import React, { useEffect, useState } from 'react'; import { useChatStore } from '../store/chatStore'; import { useAuthStore } from '@/features/auth/store/authStore'; import { apiClient } from '@/services/api/client'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { cn } from '@/lib/utils'; import { Loader2, Plus, Trash2, LogOut, MessageSquare, Hash, User, MoreVertical } from 'lucide-react'; import { CreateRoomDialog } from './CreateRoomDialog'; import { useToast } from '@/hooks/useToast'; import { Button } from '@/components/ui/button'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import { ConfirmationDialog } from '@/components/ui/confirmation-dialog'; interface ConversationItemProps { conversation: { id: string; name: string; type: string; unread_count?: number }; onSelect: (id: string) => void; isSelected: boolean; } const ConversationItem: React.FC = ({ conversation, onSelect, isSelected, }) => { const { user } = useAuthStore(); const queryClient = useQueryClient(); const toast = useToast(); const { setCurrentConversation } = useChatStore(); const [showLeaveDialog, setShowLeaveDialog] = useState(false); const [showDeleteDialog, setShowDeleteDialog] = useState(false); const leaveRoomMutation = useMutation({ mutationFn: async (roomId: string) => { await apiClient.delete(`/conversations/${roomId}/participants/${user?.id}`); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['chatConversations', user?.id] }); toast.success('Left room successfully'); setCurrentConversation(null); setShowLeaveDialog(false); }, onError: (error: any) => { toast.error(error.response?.data?.error || 'Failed to leave room'); }, }); const deleteRoomMutation = useMutation({ mutationFn: async (roomId: string) => { await apiClient.delete(`/conversations/${roomId}`); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['chatConversations', user?.id] }); toast.success('Room deleted successfully'); setCurrentConversation(null); setShowDeleteDialog(false); }, onError: (error: any) => { toast.error(error.response?.data?.error || 'Failed to delete room'); }, }); const handleLeave = (e: React.MouseEvent) => { e.stopPropagation(); setShowLeaveDialog(true); }; const handleDelete = (e: React.MouseEvent) => { e.stopPropagation(); setShowDeleteDialog(true); }; const confirmLeave = () => { leaveRoomMutation.mutate(conversation.id); }; const confirmDelete = () => { deleteRoomMutation.mutate(conversation.id); }; return ( <>
onSelect(conversation.id)} className={cn( 'group relative flex items-center justify-between p-3 rounded-xl cursor-pointer transition-all duration-300 border border-transparent', isSelected ? 'bg-kodo-cyan/10 border-kodo-cyan/30 shadow-[0_0_15px_rgba(102,252,241,0.1)]' : 'hover:bg-white/5 hover:border-white/5' )} >
{conversation.type === 'direct' ? : }
{conversation.name || `Channel ${conversation.id.substring(0, 4)}`} {conversation.type !== 'direct' && ( {conversation.type} )}
{conversation.unread_count && conversation.unread_count > 0 ? ( {conversation.unread_count} ) : null} e.stopPropagation()}> Leave Channel {conversation.type !== 'direct' && ( Delete Channel )} {/* Active Indicator Line */} {isSelected && (
)}
setShowLeaveDialog(false)} onConfirm={confirmLeave} title="Leave Channel" description="Disconnect from this secure frequency? Incoming transmission will cease." confirmLabel="Disconnect" cancelLabel="Cancel" variant="default" isLoading={leaveRoomMutation.isPending} /> setShowDeleteDialog(false)} onConfirm={confirmDelete} title="Delete Channel" description="Permanently purge this channel from the network? This action is irreversible." confirmLabel="Purge" cancelLabel="Cancel" variant="destructive" isLoading={deleteRoomMutation.isPending} /> ); }; export const ChatSidebar: React.FC = () => { const { user } = useAuthStore(); const userId = user?.id; const { conversations, currentConversationId, setCurrentConversation, addConversation, } = useChatStore(); const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false); 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, }); useEffect(() => { if (data) { data.forEach((conv: any) => { if (!conversations.some(c => c.id === conv.id)) { addConversation({ id: conv.id, name: conv.name, type: conv.type, participants: conv.participants, unread_count: 0, }); } }); } }, [data, conversations, addConversation]); if (isLoading) { return (
); } if (error) { return (

Signal Lost

); } return (

Active Channels

{conversations.length}
{conversations.length === 0 ? (
No active frequencies detected.
Initialize a new channel.
) : ( conversations.map((conv) => ( )) )}
setIsCreateDialogOpen(false)} />
); };