166 lines
6.3 KiB
TypeScript
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> | Front-end magic by <a href="https://d3vision.dev" target="_blank" rel="noreferrer">D3vision</a></p>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default App;
|