import React, { useState, useEffect, useCallback } from 'react'; import { useAuth } from '../context/AuthContext'; import { useSocket } from '../context/SocketContext'; import ServerList from './ServerList'; import ChannelSidebar from './ChannelSidebar'; // Lazy-loaded modals — these will be built in a separate batch const CreateServerModal = React.lazy(() => import('./modals/CreateServerModal')); const ServerSettings = React.lazy(() => import('./modals/ServerSettings')); const UserSettings = React.lazy(() => import('./modals/UserSettings')); const InviteModal = React.lazy(() => import('./modals/InviteModal')); // Chat area — will be built separately const ChatArea = React.lazy(() => import('./ChatArea')); const MemberList = React.lazy(() => import('./MemberList')); export default function Layout() { const { user, token } = useAuth(); const { socket } = useSocket(); const [servers, setServers] = useState([]); const [activeServer, setActiveServer] = useState(null); const [activeChannel, setActiveChannel] = useState(null); const [serverDetail, setServerDetail] = useState(null); const [showServerSettings, setShowServerSettings] = useState(false); const [showUserSettings, setShowUserSettings] = useState(false); const [showCreateServer, setShowCreateServer] = useState(false); const [showInviteModal, setShowInviteModal] = useState(false); const [showMemberList, setShowMemberList] = useState(true); // Fetch user's servers const fetchServers = useCallback(async () => { try { const res = await fetch('/api/servers', { headers: { Authorization: `Bearer ${token}` }, }); if (!res.ok) return; const data = await res.json(); const list = data.servers || data; setServers(list); // Auto-select first server if none active if (!activeServer && list.length > 0) { setActiveServer(list[0]); } } catch (err) { console.error('Failed to fetch servers:', err); } }, [token, activeServer]); useEffect(() => { fetchServers(); }, [fetchServers]); // Fetch full server detail when active server changes useEffect(() => { if (!activeServer) { setServerDetail(null); setActiveChannel(null); return; } const fetchDetail = async () => { try { const res = await fetch(`/api/servers/${activeServer.id}`, { headers: { Authorization: `Bearer ${token}` }, }); if (!res.ok) return; const data = await res.json(); const detail = data.server || data; setServerDetail(detail); // Auto-select first channel if (detail.channels && detail.channels.length > 0) { setActiveChannel(detail.channels[0]); } else if (detail.categories) { for (const cat of detail.categories) { if (cat.channels && cat.channels.length > 0) { setActiveChannel(cat.channels[0]); break; } } } } catch (err) { console.error('Failed to fetch server detail:', err); } }; fetchDetail(); // Join server room via socket if (socket) { socket.emit('server:join', activeServer.id); } return () => { if (socket && activeServer) { socket.emit('server:leave', activeServer.id); } }; }, [activeServer?.id, token, socket]); // Socket listeners for server updates useEffect(() => { if (!socket) return; const handleServerUpdate = (data) => { setServers((prev) => prev.map((s) => (s.id === data.id ? { ...s, ...data } : s)) ); if (activeServer?.id === data.id) { setActiveServer((prev) => (prev ? { ...prev, ...data } : prev)); } }; socket.on('server:updated', handleServerUpdate); return () => { socket.off('server:updated', handleServerUpdate); }; }, [socket, activeServer?.id]); const handleSelectServer = (server) => { setActiveServer(server); }; const handleOpenDMs = () => { setActiveServer(null); setServerDetail(null); setActiveChannel(null); }; const handleSelectChannel = (channel) => { setActiveChannel(channel); }; const handleServerCreated = (newServer) => { setServers((prev) => [...prev, newServer]); setActiveServer(newServer); setShowCreateServer(false); }; const dmMode = activeServer === null; return (