import { useState, useEffect } from 'react'; import { Search, Edit, LogOut, Settings, Shield, Wifi, WifiOff } from 'lucide-react'; import { useStore } from '../store'; import { useNavigate } from 'react-router-dom'; import { wsClient } from '../api/ws'; import api from '../api/client'; import Avatar from '../components/Avatar'; import ChatListItem from '../components/ChatListItem'; import MessageList from '../components/MessageList'; import ChatHeader from '../components/ChatHeader'; import ChatInfoPanel from '../components/ChatInfoPanel'; import NewChatModal from '../components/NewChatModal'; import AdminPanel from '../components/admin/AdminPanel'; import { usePushNotifications } from '../hooks/usePushNotifications'; import { Chat } from '../types'; export default function MainLayout() { const { user, chats, activeChat, setActiveChat, connected, logout, onlineUsers, updateChat } = useStore(); const navigate = useNavigate(); const [search, setSearch] = useState(''); const [showNew, setShowNew] = useState(false); const [showAdmin, setShowAdmin] = useState(false); const [showInfo, setShowInfo] = useState(false); const [mobileChatOpen, setMobileChatOpen] = useState(false); const [fullChat, setFullChat] = useState(null); usePushNotifications(!!user); // Handle URL param ?chat=xxx useEffect(() => { const params = new URLSearchParams(location.search); const chatId = params.get('chat'); if (chatId) { const chat = chats.find(c => c.id === chatId); if (chat) openChat(chat); } }, [chats]); // Handle SW messages useEffect(() => { if (!('serviceWorker' in navigator)) return; const handler = (event: MessageEvent) => { if (event.data?.type === 'open_chat') { const chat = chats.find(c => c.id === event.data.chatId); if (chat) openChat(chat); } }; navigator.serviceWorker.addEventListener('message', handler); return () => navigator.serviceWorker.removeEventListener('message', handler); }, [chats]); async function openChat(chat: Chat) { // Load full chat info try { const { data } = await api.get(`/api/chats/${chat.id}`); const merged = { ...chat, ...data }; setActiveChat(merged); setFullChat(merged); updateChat({ id: chat.id, unreadCount: 0 }); wsClient.send('read_messages', { chatId: chat.id }); } catch { setActiveChat(chat); setFullChat(chat); } setMobileChatOpen(true); setShowInfo(false); } function handleLogout() { wsClient.disconnect(); logout(); navigate('/login'); } const filtered = chats.filter(c => c.title?.toLowerCase().includes(search.toLowerCase()) ); const canSend = (() => { if (!activeChat) return false; if (activeChat.type === 'private') return true; if (activeChat.type === 'group') return activeChat.canSendMessages !== false; if (activeChat.type === 'channel') return activeChat.myRole === 'owner' || activeChat.myRole === 'admin' || !!user?.isAdmin; return false; })(); return (
{/* Sidebar */}
{/* Sidebar Header */}
{user?.displayName}
{connected ? <> Online : <> Offline }
{user?.isAdmin && ( )}
{/* Search */}
setSearch(e.target.value)} placeholder="Поиск чатов..." className="flex-1 bg-transparent text-sm outline-none text-gray-700 placeholder-gray-400" />
{/* Chat List */}
{filtered.length === 0 && (
{search ? 'Ничего не найдено' : 'Нет чатов. Создайте новый!'}
)} {filtered.map(chat => ( openChat(chat)} /> ))}
{/* Main Chat Area */}
{activeChat && fullChat ? ( <>
{ setMobileChatOpen(false); setActiveChat(null); }} onRefresh={() => openChat(activeChat)} onShowInfo={() => setShowInfo(!showInfo)} />
{/* Info Panel */} {showInfo && ( setShowInfo(false)} onRefresh={() => openChat(activeChat)} /> )}
) : (

JaniChat

Выберите чат или создайте новый

)}
{/* Modals */} {showNew && setShowNew(false)} onOpen={(id) => { const chat = chats.find(c => c.id === id); if (chat) openChat(chat); }} />} {showAdmin && setShowAdmin(false)} />}
); }