webserver-framework-frontend/src/App.tsx

166 lines
6.3 KiB
TypeScript

import React, { useEffect, useState, lazy, Suspense } from 'react';
import { Navigate, Route, Routes, useNavigate } from 'react-router-dom';
import './css/App.css';
import Home from './pages/home/Home';
import ErrorBoundary from './util/ErrorBoundary';
import Sidebar, { SidebarMenu } from './components/Sidebar';
import UserControls from './components/UserControls';
import { useLoginContext } from './structures/UserContext';
import Login from './pages/Login';
import { get, setSession, setSettings } from './util/Util';
import { PrivateRoute } from './structures/PrivateRoute';
import { UnauthedRoute } from './structures/UnauthedRoute';
import TitledPage from './components/TitledPage';
import Register from './pages/Register';
import { ClientSettings, SidebarMenuItem } from './@types/Other';
import { User } from './@types/ApiStructures';
import { PermissionBarrier } from './structures/PermissionBarrier';
import Recover from './pages/Recover';
// import OnlineList from './components/OnlineList';
// import socket, { updateState } from './util/Socket';
const Admin = lazy(() => import(/* webpackChunkName: "admin" */'./pages/admin/Admin'));
// const Moderation = lazy(() => import(/* webpackChunkName: "moderation" */'./pages/moderation/Moderation'));
// const Logs = lazy(() => import(/* webpackChunkName: "logs" */'./pages/logs/Logs'));
// const Servers = lazy(() => import(/* webpackChunkName: "servers" */'./pages/Servers'));
const Loading = () =>
{
return (<div>Loading...</div>);
};
const ErrorFallback = () =>
{
return <h3>
Failed to load major component.
</h3>;
};
const App = () =>
{
const [ user, updateUser ] = useLoginContext();
const [ loading, setLoading ] = useState(true);
const navigate = useNavigate();
useEffect(() =>
{
(async () =>
{
const result = await get<{twoFactor: boolean}>('/api/user');
if (result.status === 200)
{
setSession(result.data as User);
updateUser();
}
setLoading(false);
if (result.status === 401 && result.data?.twoFactor)
return navigate('/login/verify');
})();
}, []);
useEffect(() =>
{
// socket.connect();
(async () =>
{
const settings = await get('/api/settings');
setSettings(settings.data as ClientSettings);
// updateState();
})();
return () =>
{
// socket.disconnect();
};
}, [ user ]);
const menuItems: SidebarMenuItem[] = [
{
to: '/home', label: 'Home', items: [
{ to: '/profile', label: 'Profile', relative: true },
{ to: '/applications', label: 'Applications', relative: true, permission: [ 'applications:*', 1 ] }
]
},
{
to: '/admin', label: 'Admin', permission: [ 'administrator:*', 1 ], items: [
{ to: '/users', label: 'Users', relative: true, permission: [ 'administrator:users:*', 1 ] },
{ to: '/roles', label: 'Roles', relative: true, permission: [ 'administrator:roles:*', 1 ] },
{ to: '/flags', label: 'Flags', relative: true, permission: [ 'administrator:flags:*', 1 ] },
// { to: '/crs', label: 'Canned Responses', relative: true, permission: [ 'administrator:crs:*', 1 ] },
]
}
];
if (loading)
return null;
return (
<div className='app'>
<div className='background'>
{user ?
<div>
<header className="">
{/* <OnlineList /> */}
<UserControls />
</header>
<Sidebar>
<SidebarMenu menuItems={menuItems} />
</Sidebar>
</div>
: null}
<div className={`main-content ${user ? '' : 'login'}`}>
<ErrorBoundary fallback={<ErrorFallback />}>
<Routes>
<Route path='/home/*' element={<PrivateRoute>
<TitledPage title='Home'>
<Home />
</TitledPage>
</PrivateRoute >} />
<Route path='/admin/*' element={<PrivateRoute>
<TitledPage title='Admin'>
<PermissionBarrier permission='administrator:*' level={1}>
<Suspense fallback={<Loading />}>
<Admin />
</Suspense>
</PermissionBarrier>
</TitledPage>
</PrivateRoute >} />
<Route path='/login/*' element={<UnauthedRoute>
<Login title='Log In'/>
</UnauthedRoute>} />
<Route path='/register/*' element={<UnauthedRoute>
<Register title='Register'/>
</UnauthedRoute>} />
<Route path='/recover/*' element={
<UnauthedRoute>
<Recover title='Recover your password'/>
</UnauthedRoute>
} />
<Route path='*' element={<Navigate to='/home' />} />
</Routes>
</ErrorBoundary>
<div className={`footer ${user ? '' : 'login'}`}>
<p className='m-0 text-center'>Made with <i className="icon corgi transparent"></i> by <a href="https://corgi.wtf" target="_blank" rel="noreferrer">Navy.gif</a> &nbsp;|&nbsp; Front-end magic by <a href="https://d3vision.dev" target="_blank" rel="noreferrer">D3vision</a></p>
</div>
</div>
</div>
</div>
);
};
export default App;