'use client'; import Link from 'next/link'; import { useEffect, useMemo, useState } from 'react'; import { Loader2, Pin, Search, UsersRound } from 'lucide-react'; import { AvatarWithPresence } from '@/components/family/avatar-with-presence'; import { FamilyGroupSelector } from '@/components/family/family-group-selector'; import { FamilyInviteDialog } from '@/components/family/family-invite-dialog'; import { useFamilyOverlay } from '@/components/family/family-overlay-provider'; import { useAuth } from '@/components/id/auth-provider'; import { useSelectedFamily } from '@/hooks/use-primary-family'; import { Button } from '@/components/ui/button'; import { cn } from '@/lib/utils'; import { ChatRoom, fetchChatRooms, getApiErrorMessage, setChatRoomPinned } from '@/lib/api'; import { useToast } from '@/components/id/toast-provider'; export function FamilySidebarPanel() { const { user, token, isContentReady } = useAuth(); const { group, groupSummaries, loading, hasFamily, selectedGroupId, setSelectedGroupId, presenceByUserId, refresh } = useSelectedFamily(Boolean(user && token && isContentReady)); const { openChatWithMember } = useFamilyOverlay(); const { showToast } = useToast(); const [inviteOpen, setInviteOpen] = useState(false); const [rooms, setRooms] = useState([]); const [pinningRoomId, setPinningRoomId] = useState(null); const currentUserId = user?.id ?? ''; useEffect(() => { if (!group?.id || !token) { setRooms([]); return; } fetchChatRooms(group.id, token) .then((response) => setRooms(response.rooms ?? [])) .catch(() => undefined); }, [group?.id, token]); const roomByPeerUserId = useMemo(() => { const map = new Map(); for (const room of rooms) { if (room.type !== 'DIRECT' && room.type !== 'BOT' && room.type !== 'E2E') continue; const peer = room.members.find((member) => member.userId !== currentUserId); if (peer) map.set(peer.userId, room); } return map; }, [currentUserId, rooms]); const sortedMembers = useMemo(() => { return [...(group?.members ?? [])].sort((left, right) => { const leftRoom = roomByPeerUserId.get(left.userId); const rightRoom = roomByPeerUserId.get(right.userId); const pinDiff = Number(Boolean(rightRoom?.isPinned)) - Number(Boolean(leftRoom?.isPinned)); if (pinDiff !== 0) return pinDiff; if (leftRoom?.isPinned && rightRoom?.isPinned) { return (rightRoom.pinnedAt ?? '').localeCompare(leftRoom.pinnedAt ?? ''); } if (left.userId === currentUserId) return -1; if (right.userId === currentUserId) return 1; return left.displayName.localeCompare(right.displayName, 'ru'); }); }, [currentUserId, group?.members, roomByPeerUserId]); async function toggleMemberPinned(memberUserId: string) { const room = roomByPeerUserId.get(memberUserId); if (!room || !token) { showToast('Откройте чат с участником, чтобы его можно было закрепить'); return; } setPinningRoomId(room.id); try { const updated = await setChatRoomPinned(room.id, !room.isPinned, token); setRooms((current) => current.map((item) => (item.id === updated.id ? updated : item))); showToast(updated.isPinned ? 'Чат закреплён' : 'Чат откреплён'); } catch (error) { showToast(getApiErrorMessage(error, 'Не удалось закрепить чат') ?? 'Ошибка'); } finally { setPinningRoomId(null); } } if (!user || !token) return null; return ( <>

Семья

{hasFamily ? ( ) : ( Создать семью )}
{hasFamily ? ( ) : null}
{loading ? (
Загрузка...
) : hasFamily ? (
{sortedMembers.map((member) => { const presence = presenceByUserId.get(member.userId); const isSelf = member.userId === currentUserId; const memberRoom = roomByPeerUserId.get(member.userId); const memberPinned = Boolean(memberRoom?.isPinned); return (
{!isSelf ? ( ) : null}
); })}
) : (
Приглашайте близких и общайтесь в чатах
)}
{hasFamily ? ( void refresh()} /> ) : null} ); }