feat: add TypeScript definitions and utility functions for date formatting
- Created a global TypeScript declaration for the txadmin interface on the Window object. - Implemented date formatting utilities using date-fns with Spanish locale support. - Added TypeScript configuration files for app, Electron, and Node environments. - Set up Vite configuration for React application.
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { HashRouter, Routes, Route } from 'react-router-dom';
|
||||
import { Minus, Square, X } from 'lucide-react';
|
||||
import { DashboardLayout } from './components/layout/DashboardLayout';
|
||||
import { DashboardPage } from './pages/DashboardPage';
|
||||
import { UsersPage } from './pages/UsersPage';
|
||||
import { WapServersPage } from './pages/WapServersPage';
|
||||
import { CompaniesPage } from './pages/CompaniesPage';
|
||||
import { PlansPage } from './pages/PlansPage';
|
||||
import txadminIcon from './assets/txadmin-icon.png';
|
||||
|
||||
const TitleBar = () => (
|
||||
<header className="app-titlebar">
|
||||
<div className="app-titlebar-brand">
|
||||
<img className="app-titlebar-logo" src={txadminIcon} alt="txadmin" />
|
||||
<span>txadmin</span>
|
||||
</div>
|
||||
<div className="app-titlebar-actions">
|
||||
<button type="button" aria-label="Minimize window" onClick={() => void window.txadmin.minimizeWindow()}>
|
||||
<Minus size={16} />
|
||||
</button>
|
||||
<button type="button" aria-label="Maximize window" onClick={() => void window.txadmin.toggleMaximizeWindow()}>
|
||||
<Square size={13} />
|
||||
</button>
|
||||
<button type="button" className="close" aria-label="Close window" onClick={() => void window.txadmin.closeWindow()}>
|
||||
<X size={16} />
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
|
||||
function App() {
|
||||
const [keyStatus, setKeyStatus] = useState<{ loaded: boolean; path: string | null }>({ loaded: false, path: null });
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
if (!window.txadmin) {
|
||||
setError('Desktop bridge is not available. Restart txadmin and try again.');
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
window.txadmin.getKeyStatus()
|
||||
.then(setKeyStatus)
|
||||
.catch(() => setError('Could not read private key status.'))
|
||||
.finally(() => setLoading(false));
|
||||
}, []);
|
||||
|
||||
const selectPrivateKey = async () => {
|
||||
setError(null);
|
||||
try {
|
||||
setKeyStatus(await window.txadmin.selectPrivateKey());
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Could not load the private key.');
|
||||
}
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return <div className="app-shell"><TitleBar /><div className="key-gate">Loading txadmin...</div></div>;
|
||||
}
|
||||
|
||||
if (!keyStatus.loaded) {
|
||||
return (
|
||||
<div className="app-shell">
|
||||
<TitleBar />
|
||||
<div className="key-gate">
|
||||
<div className="glass-panel key-gate-card">
|
||||
<img className="key-gate-logo" src={txadminIcon} alt="txadmin" />
|
||||
<h1>txadmin</h1>
|
||||
<p>Load the sysadmin private key to unlock admin functions.</p>
|
||||
<button className="primary-button" onClick={selectPrivateKey}>Select Private Key</button>
|
||||
<p className="key-gate-hint">Expected equivalent: sysadmin/keys/tx-sysadmin-private.key</p>
|
||||
{error && <p className="key-gate-error">{error}</p>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="app-shell">
|
||||
<TitleBar />
|
||||
<HashRouter>
|
||||
<Routes>
|
||||
<Route path="/" element={<DashboardLayout keyPath={keyStatus.path} onSelectPrivateKey={selectPrivateKey} />}>
|
||||
<Route index element={<DashboardPage />} />
|
||||
<Route path="users" element={<UsersPage />} />
|
||||
<Route path="companies" element={<CompaniesPage />} />
|
||||
<Route path="plans" element={<PlansPage />} />
|
||||
<Route path="wapservers" element={<WapServersPage />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</HashRouter>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
Reference in New Issue
Block a user