* Initial plan * fix: add loading state to AuthContext to prevent premature route resolution Agent-Logs-Url: https://github.com/RMCampos/tasknote/sessions/8b02c4fd-b37e-4d34-8910-6d075bde6b4b Co-authored-by: RMCampos <2219519+RMCampos@users.noreply.github.com> * restore: revert package-lock.json to original state Co-authored-by: RMCampos <2219519+RMCampos@users.noreply.github.com> * fix: add catch before finally in initial auth check useEffect Agent-Logs-Url: https://github.com/RMCampos/tasknote/sessions/8b02c4fd-b37e-4d34-8910-6d075bde6b4b Co-authored-by: RMCampos <2219519+RMCampos@users.noreply.github.com> * test: address test warning missing act --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: RMCampos <2219519+RMCampos@users.noreply.github.com> Co-authored-by: Ricardo Campos <ricardompcampos@gmail.com>
143 lines
3.3 KiB
TypeScript
143 lines
3.3 KiB
TypeScript
import React, { useContext, useEffect, useState } from 'react';
|
|
import {
|
|
createBrowserRouter,
|
|
Navigate,
|
|
RouteObject,
|
|
RouterProvider
|
|
} from 'react-router';
|
|
import AuthContext from './context/AuthContext';
|
|
import BrowserRoutes from './routes';
|
|
import ProtectedRoute from './routes/ProtectedRoute';
|
|
import PrivateLayout from './layout/PrivateLayout';
|
|
import Landing from './views/Landing';
|
|
import Login from './views/Login';
|
|
import NotFound from './views/NotFound';
|
|
import Register from './views/Register';
|
|
import EmailConfirmation from './views/EmailConfirmation';
|
|
import ResetPassword from './views/ResetPassword';
|
|
import CompleteResetPassword from './views/CompleteResetPassword';
|
|
import SharedNote from './views/SharedNote';
|
|
import './styles/custom.scss';
|
|
|
|
/**
|
|
* The main application component that sets up routing based on the
|
|
* user's authentication status.
|
|
*
|
|
* @component
|
|
* @returns {React.ReactNode} The rendered component.
|
|
*/
|
|
function App(): React.ReactNode {
|
|
const { signed, loading } = useContext(AuthContext);
|
|
const [theme, setTheme] = useState(() => {
|
|
return localStorage.getItem('theme') ?? 'light';
|
|
});
|
|
|
|
/**
|
|
* Routes for the users who are not signed in.
|
|
* @type {RouteObject[]}
|
|
*/
|
|
const notSignedRouter: RouteObject[] = [
|
|
{
|
|
path: '/',
|
|
element: <Landing />
|
|
},
|
|
{
|
|
path: '/login',
|
|
element: <Login />
|
|
},
|
|
{
|
|
path: '/register',
|
|
element: <Register />
|
|
},
|
|
{
|
|
path: '/home',
|
|
element: <Navigate to="/login" replace />
|
|
},
|
|
{
|
|
path: '/email-confirmation',
|
|
element: <EmailConfirmation />
|
|
},
|
|
{
|
|
// The reset-password is where the password reset workflow starts
|
|
path: '/reset-password',
|
|
element: <ResetPassword />
|
|
},
|
|
{
|
|
path: '/finish-reset-password',
|
|
element: <CompleteResetPassword />
|
|
},
|
|
{
|
|
path: '/public/notes/:token',
|
|
element: <SharedNote />
|
|
},
|
|
{
|
|
path: '*',
|
|
element: <Navigate to="/" replace />
|
|
}
|
|
];
|
|
|
|
/**
|
|
* Routes for users who are signed in.
|
|
* @type {RouteObject[]}
|
|
*/
|
|
const signedRouter: RouteObject[] = [
|
|
{
|
|
path: '/',
|
|
element: <ProtectedRoute />,
|
|
children: [
|
|
{
|
|
element: <PrivateLayout />,
|
|
children: BrowserRoutes
|
|
}
|
|
]
|
|
},
|
|
{
|
|
path: '/public/notes/:token',
|
|
element: <SharedNote />
|
|
},
|
|
{
|
|
path: '*',
|
|
element: <NotFound />
|
|
}
|
|
];
|
|
|
|
/**
|
|
* Determines the appropriate router based on the user's authentication status.
|
|
* @returns {Router} The configured router.
|
|
*/
|
|
const getBrowserRouter = () => {
|
|
if (signed) {
|
|
return createBrowserRouter(signedRouter);
|
|
}
|
|
return createBrowserRouter(notSignedRouter);
|
|
};
|
|
|
|
const browserRouter = getBrowserRouter();
|
|
|
|
useEffect(() => {
|
|
document.body.setAttribute('data-bs-theme', theme);
|
|
localStorage.setItem('theme', theme);
|
|
}, [theme]);
|
|
|
|
const toggleTheme = () => {
|
|
setTheme(prev => (prev === 'light' ? 'dark' : 'light'));
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<button
|
|
type="button"
|
|
className="btn btn-dark"
|
|
onClick={toggleTheme}
|
|
>
|
|
{theme === 'dark' ? '☀ Light Mode' : '🌙 Dark Mode'}
|
|
</button>
|
|
|
|
{/* Your routes or content here */}
|
|
{!loading && <RouterProvider router={browserRouter} />}
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default App;
|