sync: phase 1 backend + frontend from server
This commit is contained in:
@@ -2,13 +2,13 @@ import { useEffect, useState } from 'react';
|
||||
import { Link, Outlet, useLocation, useNavigate } from 'react-router-dom';
|
||||
import { useAuthStore, type UserStatus } from '../stores/auth.ts';
|
||||
import { useWebSocketStore } from '../stores/ws.ts';
|
||||
import { useServerStore } from '../stores/server.ts';
|
||||
import { ServerBar } from './ServerBar.tsx';
|
||||
import { ChannelList } from './ChannelList.tsx';
|
||||
import { ConversationList } from './ConversationList.tsx';
|
||||
import { MemberList } from './MemberList.tsx';
|
||||
import { VoicePanel } from './VoicePanel.tsx';
|
||||
|
||||
const STATUS_CYCLE: UserStatus[] = ['online', 'idle', 'dnd', 'offline'];
|
||||
|
||||
function statusColor(status: UserStatus): string {
|
||||
switch (status) {
|
||||
case 'online':
|
||||
@@ -21,11 +21,9 @@ function statusColor(status: UserStatus): string {
|
||||
return 'bg-gb-gray';
|
||||
}
|
||||
}
|
||||
|
||||
function statusLabel(status: UserStatus): string {
|
||||
return status.toUpperCase();
|
||||
}
|
||||
|
||||
export function Layout() {
|
||||
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
|
||||
const isLoading = useAuthStore((state) => state.isLoading);
|
||||
@@ -35,22 +33,21 @@ export function Layout() {
|
||||
const updateProfile = useAuthStore((state) => state.updateProfile);
|
||||
const wsConnect = useWebSocketStore((s) => s.connect);
|
||||
const wsDisconnect = useWebSocketStore((s) => s.disconnect);
|
||||
const setActiveServer = useServerStore((s) => s.setActiveServer);
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const [showStatusMenu, setShowStatusMenu] = useState(false);
|
||||
|
||||
const [dmMode, setDmMode] = useState(false);
|
||||
useEffect(() => {
|
||||
fetchMe();
|
||||
wsConnect();
|
||||
return () => { wsDisconnect(); };
|
||||
}, [fetchMe, wsConnect, wsDisconnect]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLoading && !isAuthenticated && location.pathname !== '/login') {
|
||||
navigate('/login', { replace: true });
|
||||
}
|
||||
}, [isLoading, isAuthenticated, location.pathname, navigate]);
|
||||
|
||||
const handleStatusChange = async (status: UserStatus) => {
|
||||
setShowStatusMenu(false);
|
||||
try {
|
||||
@@ -59,9 +56,7 @@ export function Layout() {
|
||||
// Error is surfaced via auth store; menu closes optimistically.
|
||||
}
|
||||
};
|
||||
|
||||
const currentStatus = user?.status ?? 'offline';
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="h-full w-full flex items-center justify-center bg-gb-bg text-gb-fg-f font-mono">
|
||||
@@ -69,11 +64,9 @@ export function Layout() {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!isAuthenticated) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="h-full w-full bg-gb-bg text-gb-fg font-mono flex flex-col p-2">
|
||||
<div className="flex-1 terminal-border bg-gb-bg-h flex flex-col min-h-0">
|
||||
@@ -114,8 +107,35 @@ export function Layout() {
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 flex min-h-0">
|
||||
<div className="flex flex-col items-center w-16 bg-gb-bg-h border-r border-gb-bg-t py-2 gap-2 shrink-0">
|
||||
<button
|
||||
onClick={() => setDmMode(false)}
|
||||
className={`w-11 h-11 flex items-center justify-center font-mono text-xs border rounded ${
|
||||
!dmMode
|
||||
? 'bg-gb-bg-t text-gb-orange border-gb-orange'
|
||||
: 'bg-gb-bg-s text-gb-fg border-gb-bg-t hover:border-gb-fg-t'
|
||||
}`}
|
||||
title="Servers"
|
||||
>
|
||||
[S]
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
setDmMode(true);
|
||||
setActiveServer(null);
|
||||
}}
|
||||
className={`w-11 h-11 flex items-center justify-center font-mono text-xs border rounded ${
|
||||
dmMode
|
||||
? 'bg-gb-bg-t text-gb-orange border-gb-orange'
|
||||
: 'bg-gb-bg-s text-gb-fg border-gb-bg-t hover:border-gb-fg-t'
|
||||
}`}
|
||||
title="Direct Messages"
|
||||
>
|
||||
[@]
|
||||
</button>
|
||||
</div>
|
||||
<ServerBar />
|
||||
<ChannelList />
|
||||
{dmMode ? <ConversationList /> : <ChannelList />}
|
||||
<div className="flex-1 min-w-0 flex flex-col">
|
||||
<div className="flex-1 min-h-0 flex flex-col overflow-hidden">
|
||||
<VoicePanel />
|
||||
@@ -124,7 +144,7 @@ export function Layout() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<MemberList />
|
||||
{!dmMode && <MemberList />}
|
||||
</div>
|
||||
<div className="px-3 py-1 border-t border-gb-bg-t text-xs text-gb-fg-f flex justify-between bg-gb-bg-s">
|
||||
<span>TERM v1.0</span>
|
||||
|
||||
Reference in New Issue
Block a user