--Added Initial steps
This commit is contained in:
george committed 2026-09-08 14:49:30 +05:30
commit 50e424bc22
19 files changed
+2148

No files matched your search

+182
View File
@@ -0,0 +1,182 @@
import { useState } from 'react'
import './App.css'
const navItems = [
{ id: 'dashboard', label: 'Dashboard' },
{ id: 'nodes', label: 'Nodes' },
]
type Theme = 'light' | 'dark'
const getSavedTheme = (): Theme => {
try {
return localStorage.getItem('theme') === 'dark' ? 'dark' : 'light'
} catch {
return 'light'
}
}
const saveTheme = (theme: Theme) => {
try {
localStorage.setItem('theme', theme)
} catch {
return
}
}
function App() {
const [isCollapsed, setIsCollapsed] = useState(false)
const [activePage, setActivePage] = useState('dashboard')
const [theme, setTheme] = useState<Theme>(getSavedTheme)
const [isRegisterFormOpen, setIsRegisterFormOpen] = useState(false)
const nextTheme = theme === 'light' ? 'dark' : 'light'
const toggleTheme = () => {
setTheme((currentTheme) => {
const updatedTheme = currentTheme === 'light' ? 'dark' : 'light'
saveTheme(updatedTheme)
return updatedTheme
})
}
return (
<div
className={`app-shell theme-${theme} ${isCollapsed ? 'nav-collapsed' : ''}`}
>
<aside className="side-nav" aria-label="Primary navigation">
<div className="nav-header">
<span className="nav-title">PG Multi Master</span>
<button
type="button"
className="nav-toggle"
onClick={() => setIsCollapsed((collapsed) => !collapsed)}
aria-label={isCollapsed ? 'Expand navigation' : 'Collapse navigation'}
aria-expanded={!isCollapsed}
>
<span aria-hidden="true">{isCollapsed ? '>' : '<'}</span>
</button>
</div>
<nav className="nav-list">
{navItems.map((item) => (
<button
key={item.id}
type="button"
className={`nav-link ${activePage === item.id ? 'active' : ''}`}
title={isCollapsed ? item.label : undefined}
onClick={() => setActivePage(item.id)}
aria-current={activePage === item.id ? 'page' : undefined}
>
<span className="nav-icon" aria-hidden="true">
{item.label.charAt(0)}
</span>
<span className="nav-label">{item.label}</span>
</button>
))}
</nav>
<button
type="button"
className="theme-toggle"
onClick={toggleTheme}
title={isCollapsed ? `Switch to ${nextTheme} theme` : undefined}
aria-label={`Switch to ${nextTheme} theme`}
>
<span className="theme-icon" aria-hidden="true">
{theme === 'light' ? 'D' : 'L'}
</span>
<span className="theme-label">
{theme === 'light' ? 'Dark mode' : 'Light mode'}
</span>
</button>
</aside>
<main className="main-content">
{activePage === 'dashboard' ? (
<section className="content-panel" id="dashboard">
<p className="eyebrow">Dashboard</p>
<h1>Welcome back</h1>
<p>
Your main workspace is ready. The left navigation can collapse
now, and more sections can be added to the nav list as the app
grows.
</p>
</section>
) : (
<section className="content-panel nodes-page" id="nodes">
<div className="page-header">
<h1>Nodes</h1>
<button
type="button"
className="primary-button"
onClick={() => setIsRegisterFormOpen(true)}
>
Register Nodes
</button>
</div>
{isRegisterFormOpen ? (
<form className="register-form">
<div className="form-grid">
<label className="form-field">
<span>Node Name</span>
<input name="node_name" type="text" required />
</label>
<label className="form-field">
<span>Host</span>
<input
name="host"
type="text"
inputMode="decimal"
pattern="^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$"
placeholder="192.168.1.10"
required
/>
</label>
<label className="form-field">
<span>Port</span>
<input name="port" type="number" min="1" max="65535" required />
</label>
<label className="form-field">
<span>Database Name</span>
<input name="dbname" type="text" required />
</label>
<label className="form-field">
<span>User</span>
<input name="user" type="text" required />
</label>
<label className="form-field">
<span>Password</span>
<input name="password" type="password" required />
</label>
</div>
<div className="form-actions">
<button
type="button"
className="secondary-button"
onClick={() => setIsRegisterFormOpen(false)}
>
Cancel
</button>
<button type="submit" className="primary-button">
Register
</button>
</div>
</form>
) : null}
</section>
)}
</main>
</div>
)
}
export default App