"use client"; import { useState, useEffect, useMemo } from 'react'; import { useAuth } from '@/contexts/auth-context'; import { useContacts } from '@/contexts/contacts-context'; import { useGroups } from '@/contexts/groups-context'; import { useSettings } from '@/contexts/settings-context'; import { useFirebase } from '@/contexts/firebase-context'; import { Button } from './ui/button'; import { Cog, LogOut, Users, Sparkles, Globe, UserPlus, Search, X, Loader2, MoreVertical, Ban, Check, Mail, LayoutGrid, Phone, Settings, User } from 'lucide-react'; import type { ChatRecipient, Contact, Group, User as UserType, ChatRequest, GroupInvitation } from '@/lib/types'; import { Input } from './ui/input'; import { Avatar, AvatarFallback, AvatarImage } from './ui/avatar'; import { Badge } from './ui/badge'; import { Separator } from './ui/separator'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from './ui/dropdown-menu'; import { Tabs, TabsContent, TabsList, TabsTrigger } from './ui/tabs'; import { UserListItem } from './user-list-item'; import { onValue, ref } from 'firebase/database'; import Link from 'next/link'; import { useRouter } from 'next/navigation'; const loodaAssistant: ChatRecipient = { uid: 'looda-assistant', displayName: 'Looda', isBot: true, photoURL: 'https://api.dicebear.com/8.x/bottts/svg?seed=Looda' } const khaloushAssistant: ChatRecipient = { uid: 'khaloush-assistant', displayName: 'Khaloush', isBot: true, photoURL: 'https://api.dicebear.com/8.x/bottts/svg?seed=Khaloush' } const GroupListItem = ({ group, onSelectRecipient }: { group: Group, onSelectRecipient: (recipient: ChatRecipient) => void }) => { const { playSound, t } = useSettings(); const groupType = group.info.type || 'general'; return ( )}; const ChatRequestItem = ({ request, onAccept, onDecline }: { request: ChatRequest; onAccept: (request: ChatRequest) => void; onDecline: (request: ChatRequest, andBlock: boolean) => void; }) => { const { playSound, t } = useSettings(); return (
{request.displayName.charAt(0)}

{request.displayName}

@{request.publicId}

playSound('touch')}> onDecline(request, false)}>{t('decline')} onDecline(request, true)} className="text-destructive"> {t('declineAndBlock')}
); }; const GroupInvitationItem = ({ invitation, onAccept, onDecline }: { invitation: GroupInvitation; onAccept: (invitation: GroupInvitation) => void; onDecline: (invitation: GroupInvitation) => void; }) => { const { playSound, t } = useSettings(); return (
{invitation.groupName.charAt(0)}

{invitation.groupName}

{t('invitedBy', { name: invitation.invitedBy })}

); }; export function UserList({ onSelectRecipient, onOpenCreateGroup, onOpenSettings, onSignOut, onViewProfile }: { onSelectRecipient: (recipient: ChatRecipient) => void, onOpenCreateGroup: () => void, onOpenSettings: () => void, onSignOut: () => void, onViewProfile: (user: UserType) => void }) { const { currentUser } = useAuth(); const { contacts, chatRequests, findUserByPublicId, sendChatRequest, acceptChatRequest, declineChatRequest } = useContacts(); const { groups, groupInvitations, acceptGroupInvitation, declineGroupInvitation } = useGroups(); const { rtdb } = useFirebase(); const { addToast, playSound, t } = useSettings(); const [searchTerm, setSearchTerm] = useState(''); const [searchResult, setSearchResult] = useState(null); const [isSearching, setIsSearching] = useState(false); const [onlineStatus, setOnlineStatus] = useState<{[key: string]: {isOnline: boolean, lastSeen: number}}>({}); const router = useRouter(); useEffect(() => { if (!currentUser) return; const presenceRef = ref(rtdb, 'presence'); const unsubscribe = onValue(presenceRef, (snapshot) => { const data = snapshot.val() || {}; setOnlineStatus(data); }); return () => unsubscribe(); }, [rtdb, currentUser]); const contactsWithStatus = useMemo(() => { return contacts.map(contact => ({ ...contact, isOnline: onlineStatus[contact.uid]?.isOnline, })); }, [contacts, onlineStatus]); const handleSearch = async (e: React.KeyboardEvent) => { if (e.key !== 'Enter' || !searchTerm.trim()) return; playSound('touch'); const term = searchTerm.trim().toLowerCase(); setIsSearching(true); setSearchResult(null); if (term === currentUser?.publicId) { addToast(t("youCantAddYourself"), { variant: "destructive" }); setIsSearching(false); return; } const user = await findUserByPublicId(term); setSearchResult(user || 'not_found'); setIsSearching(false); }; const handleStartChat = async (user: UserType) => { playSound('touch'); const isContact = contacts.some(c => c.uid === user.uid); if (isContact) { onSelectRecipient({ ...user, isGroup: false, uid: user.uid, displayName: user.displayName }); } else { await sendChatRequest(user); } setSearchTerm(''); setSearchResult(null); } if (!currentUser) { return null; } return (
{ setSearchTerm(e.target.value); if (!e.target.value) setSearchResult(null); }} onKeyDown={handleSearch} />
{isSearching && (
)} {searchResult && searchResult !== 'not_found' && (

{t('searchResult')}

)} {searchResult === 'not_found' && (

{t('userNotFound')}

)}
playSound('touch')}>{t('chatsTab')} playSound('touch')}> {t('requestsTab')} {(chatRequests.length + groupInvitations.length > 0) && {chatRequests.length + groupInvitations.length}}

{t('mainSection')}

{groups.length > 0 && ( <>

{t('groupsSection')}

{groups.map(group => )} )}

{t('contactsSection')}

{contactsWithStatus.map(contact => )} {contacts.length === 0 && !searchTerm &&

{t('noContacts')}

}
{(chatRequests.length > 0 || groupInvitations.length > 0) ? (
{groupInvitations.length > 0 && (

{t('groupInvitations')}

{groupInvitations.map(inv => ( ))}
)} {chatRequests.length > 0 && (

{t('chatRequests')}

{chatRequests.map(req => ( ))}
)}
) : (

{t('noNewRequests')}

)}
); }