meatloaf-config/src/app/App.tsx
2026-04-13 23:55:36 -04:00

172 lines
6.8 KiB
TypeScript

import { useState } from 'react';
import { Cpu, Settings, Wifi, Network, HardDrive, Activity, MoreHorizontal, Search, Wrench, User, LogOut, Bell, FileText } from 'lucide-react';
import { Toaster } from 'sonner';
import StatusPage from './components/StatusPage';
import DevicesPage from './components/DevicesPage';
import GeneralPage from './components/GeneralPage';
import NetworkPage from './components/NetworkPage';
import IECPage from './components/IECPage';
import OtherPage from './components/OtherPage';
import ToolsPage from './components/ToolsPage';
import SearchOverlay from './components/SearchOverlay';
import logoSvg from '../imports/logo.svg';
import configData from '../imports/config.json';
type Page = 'status' | 'devices' | 'iec' | 'network' | 'other' | 'general' | 'tools';
export default function App() {
const [currentPage, setCurrentPage] = useState<Page>('status');
const [config, setConfig] = useState(configData);
const [showSearch, setShowSearch] = useState(false);
const [showProfileMenu, setShowProfileMenu] = useState(false);
const pages = {
status: <StatusPage config={config} setConfig={setConfig} />,
devices: <DevicesPage config={config} setConfig={setConfig} />,
iec: <IECPage config={config} setConfig={setConfig} />,
network: <NetworkPage config={config} setConfig={setConfig} />,
other: <OtherPage config={config} setConfig={setConfig} />,
general: <GeneralPage config={config} setConfig={setConfig} />,
tools: <ToolsPage config={config} setConfig={setConfig} />
};
return (
<div className="size-full flex flex-col bg-neutral-50">
<Toaster position="top-center" />
<header className="bg-white border-b border-neutral-200 px-4 py-3 flex-shrink-0">
<div className="flex items-center justify-between">
<img src={logoSvg} alt="Meatloaf" className="h-8" />
<div className="flex items-center gap-3">
<button
onClick={() => setShowSearch(true)}
className="p-2 hover:bg-neutral-100 rounded-lg"
>
<Search className="w-5 h-5" />
</button>
<button
onClick={() => setCurrentPage('tools')}
className="p-2 hover:bg-neutral-100 rounded-lg"
>
<Wrench className="w-5 h-5" />
</button>
<div className="relative">
<button
onClick={() => setShowProfileMenu(!showProfileMenu)}
className="p-2 hover:bg-neutral-100 rounded-lg"
>
<User className="w-5 h-5" />
</button>
{showProfileMenu && (
<div className="absolute right-0 top-12 bg-white rounded-lg shadow-lg border border-neutral-200 py-2 min-w-[200px] z-20">
<button
onClick={() => {
setShowProfileMenu(false);
setCurrentPage('general');
}}
className="w-full px-4 py-2 text-left hover:bg-neutral-50 flex items-center gap-2"
>
<Settings className="w-4 h-4" />
Settings
</button>
<button
onClick={() => setShowProfileMenu(false)}
className="w-full px-4 py-2 text-left hover:bg-neutral-50 flex items-center gap-2"
>
<Bell className="w-4 h-4" />
Notifications
</button>
<button
onClick={() => setShowProfileMenu(false)}
className="w-full px-4 py-2 text-left hover:bg-neutral-50 flex items-center gap-2"
>
<FileText className="w-4 h-4" />
Documentation
</button>
<div className="border-t border-neutral-200 my-2" />
<button
onClick={() => setShowProfileMenu(false)}
className="w-full px-4 py-2 text-left hover:bg-neutral-50 flex items-center gap-2 text-red-600"
>
<LogOut className="w-4 h-4" />
Logout
</button>
</div>
)}
</div>
</div>
</div>
</header>
<main className="flex-1 overflow-y-auto">
{pages[currentPage]}
</main>
<nav className="bg-white border-t border-neutral-200 flex-shrink-0">
<div className="flex">
<button
onClick={() => setCurrentPage('status')}
className={`flex-1 flex flex-col items-center gap-1 py-2 ${
currentPage === 'status' ? 'text-blue-600' : 'text-neutral-600'
}`}
>
<Activity className="w-5 h-5" />
<span className="text-xs">Status</span>
</button>
<button
onClick={() => setCurrentPage('devices')}
className={`flex-1 flex flex-col items-center gap-1 py-2 ${
currentPage === 'devices' ? 'text-blue-600' : 'text-neutral-600'
}`}
>
<HardDrive className="w-5 h-5" />
<span className="text-xs">Devices</span>
</button>
<button
onClick={() => setCurrentPage('iec')}
className={`flex-1 flex flex-col items-center gap-1 py-2 ${
currentPage === 'iec' ? 'text-blue-600' : 'text-neutral-600'
}`}
>
<Cpu className="w-5 h-5" />
<span className="text-xs">IEC</span>
</button>
<button
onClick={() => setCurrentPage('network')}
className={`flex-1 flex flex-col items-center gap-1 py-2 ${
currentPage === 'network' ? 'text-blue-600' : 'text-neutral-600'
}`}
>
<Network className="w-5 h-5" />
<span className="text-xs">Network</span>
</button>
<button
onClick={() => setCurrentPage('other')}
className={`flex-1 flex flex-col items-center gap-1 py-2 ${
currentPage === 'other' ? 'text-blue-600' : 'text-neutral-600'
}`}
>
<MoreHorizontal className="w-5 h-5" />
<span className="text-xs">More</span>
</button>
<button
onClick={() => setCurrentPage('general')}
className={`flex-1 flex flex-col items-center gap-1 py-2 ${
currentPage === 'general' ? 'text-blue-600' : 'text-neutral-600'
}`}
>
<Settings className="w-5 h-5" />
<span className="text-xs">General</span>
</button>
</div>
</nav>
{showSearch && (
<SearchOverlay
config={config}
setConfig={setConfig}
onClose={() => setShowSearch(false)}
/>
)}
</div>
);
}