Keep App component loaded while navigating (#247)
* Make /settings not throw away App component * Make App not reload for Onboarding * Close sidebar when navigating to /settings * Use centralized constants for route pathnames * Clean up a few stray raw path literals
This commit is contained in:
@ -1,52 +1,84 @@
|
||||
import { App } from './App'
|
||||
import { createBrowserRouter, redirect, RouterProvider } from 'react-router-dom'
|
||||
import {
|
||||
createBrowserRouter,
|
||||
Outlet,
|
||||
redirect,
|
||||
RouterProvider,
|
||||
} from 'react-router-dom'
|
||||
import { ErrorPage } from './components/ErrorPage'
|
||||
import { Settings } from './routes/Settings'
|
||||
import Onboarding, { onboardingRoutes } from './routes/Onboarding'
|
||||
import Onboarding, {
|
||||
onboardingRoutes,
|
||||
onboardingPaths,
|
||||
} from './routes/Onboarding'
|
||||
import SignIn from './routes/SignIn'
|
||||
import { Auth } from './Auth'
|
||||
|
||||
const prependRoutes =
|
||||
(routesObject: Record<string, string>) => (prepend: string) => {
|
||||
return Object.fromEntries(
|
||||
Object.entries(routesObject).map(([constName, path]) => [
|
||||
constName,
|
||||
prepend + path,
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
export const paths = {
|
||||
INDEX: '/',
|
||||
SETTINGS: '/settings',
|
||||
SIGN_IN: '/signin',
|
||||
ONBOARDING: prependRoutes(onboardingPaths)(
|
||||
'/onboarding/'
|
||||
) as typeof onboardingPaths,
|
||||
}
|
||||
|
||||
const router = createBrowserRouter([
|
||||
{
|
||||
path: '/',
|
||||
path: paths.INDEX,
|
||||
element: (
|
||||
<Auth>
|
||||
<Outlet />
|
||||
<App />
|
||||
</Auth>
|
||||
),
|
||||
errorElement: <ErrorPage />,
|
||||
loader: () => {
|
||||
loader: ({ request }) => {
|
||||
const store = localStorage.getItem('store')
|
||||
if (store === null) {
|
||||
return redirect('/onboarding')
|
||||
return redirect(paths.ONBOARDING.INDEX)
|
||||
} else {
|
||||
const status = JSON.parse(store).state.onboardingStatus
|
||||
if (status !== 'done' && status !== 'dismissed') {
|
||||
return redirect('/onboarding/' + status)
|
||||
const status = JSON.parse(store).state.onboardingStatus || ''
|
||||
const notEnRouteToOnboarding =
|
||||
!request.url.includes(paths.ONBOARDING.INDEX) &&
|
||||
request.method === 'GET'
|
||||
// '' is the initial state, 'done' and 'dismissed' are the final states
|
||||
const hasValidOnboardingStatus =
|
||||
(status !== undefined && status.length === 0) ||
|
||||
!(status === 'done' || status === 'dismissed')
|
||||
const shouldRedirectToOnboarding =
|
||||
notEnRouteToOnboarding && hasValidOnboardingStatus
|
||||
|
||||
if (shouldRedirectToOnboarding) {
|
||||
return redirect(paths.ONBOARDING.INDEX + status)
|
||||
}
|
||||
}
|
||||
return null
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: paths.SETTINGS,
|
||||
element: <Settings />,
|
||||
},
|
||||
{
|
||||
path: paths.ONBOARDING.INDEX,
|
||||
element: <Onboarding />,
|
||||
children: onboardingRoutes,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/settings',
|
||||
element: (
|
||||
<Auth>
|
||||
<Settings />
|
||||
</Auth>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: '/onboarding',
|
||||
element: (
|
||||
<Auth>
|
||||
<Onboarding />
|
||||
</Auth>
|
||||
),
|
||||
children: onboardingRoutes,
|
||||
},
|
||||
{
|
||||
path: '/signin',
|
||||
path: paths.SIGN_IN,
|
||||
element: <SignIn />,
|
||||
},
|
||||
])
|
||||
|
Reference in New Issue
Block a user