feat: add windows client UI

This commit is contained in:
2026-05-21 20:28:12 +03:00
parent 71e628fbde
commit 6e0d97b65b
6 changed files with 631 additions and 24 deletions

View File

@@ -7,6 +7,7 @@ import { Sidebar } from './components/Sidebar.jsx';
import { StatusPane } from './components/StatusPane.jsx';
import { OverviewPage } from './components/OverviewPage.jsx';
import { ClientOverviewPage } from './components/ClientOverviewPage.jsx';
import { WindowsOverviewPage } from './components/WindowsOverviewPage.jsx';
import { ServersPage } from './components/ServersPage.jsx';
import { RoutingPage } from './components/RoutingPage.jsx';
import { LogsPage } from './components/LogsPage.jsx';
@@ -97,6 +98,9 @@ function App() {
if (state?.mode === 'client' && page !== 'overview') {
navigate('overview');
}
if (state?.mode === 'windows' && (page === 'servers' || page === 'routing')) {
navigate('overview');
}
}, [state?.mode, page]);
useEffect(() => () => {
@@ -381,6 +385,7 @@ function App() {
[servers, state?.selectedTag],
);
const isClientMode = state?.mode === 'client';
const isWindowsMode = state?.mode === 'windows';
const dirtyRules = rulesSaveStatus === 'pending' || rulesSaveStatus === 'saving';
const dirtyDevices = Boolean(
@@ -409,11 +414,14 @@ function App() {
onTryApply={rollback}
/>
<div className={`app-body${isClientMode ? ' client-mode' : ''}`}>
<div className={`app-body${isClientMode ? ' client-mode' : ''}${isWindowsMode ? ' windows-mode' : ''}`}>
{!isClientMode && <Sidebar active={page} onChange={navigate} badges={sidebarBadges} mode={state?.mode} />}
<main className="app-main">
{(page === 'overview' || isClientMode) && (
{page === 'overview' && isWindowsMode && (
<WindowsOverviewPage pushToast={pushToast} />
)}
{(page === 'overview' || isClientMode) && !isWindowsMode && (
isClientMode ? (
<ClientOverviewPage
state={state}
@@ -447,7 +455,7 @@ function App() {
/>
)
)}
{page === 'servers' && !isClientMode && (
{page === 'servers' && !isClientMode && !isWindowsMode && (
<ServersPage
state={state}
servers={servers}
@@ -463,7 +471,7 @@ function App() {
pushToast={pushToast}
/>
)}
{page === 'routing' && !isClientMode && (
{page === 'routing' && !isClientMode && !isWindowsMode && (
<RoutingPage
rules={customRules}
saveStatus={rulesSaveStatus}
@@ -497,7 +505,7 @@ function App() {
)}
{/* Sticky bar — для routing/servers */}
{(page === 'routing' && dirtyRouting) && (
{(page === 'routing' && dirtyRouting && !isWindowsMode) && (
<div className="sticky-bar">
<div className="flex">
<span className={`dot ${rulesSaveStatus === 'error' ? 'danger' : 'warning'}`} />
@@ -522,7 +530,7 @@ function App() {
</div>
)}
{(page === 'servers' && dirtyServer) && (
{(page === 'servers' && dirtyServer && !isWindowsMode) && (
<div className="sticky-bar">
<div className="flex">
<span className="dot warning" />
@@ -539,7 +547,7 @@ function App() {
)}
</main>
{!isClientMode && (
{!isClientMode && !isWindowsMode && (
<StatusPane
state={state}
busy={busy}