Skip to content

Commit 8f1a92c

Browse files
committed
added private routes
1 parent 34b8c75 commit 8f1a92c

10 files changed

Lines changed: 136 additions & 75 deletions

File tree

src/app/providers/auth-context.tsx

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
1-
import {
2-
createContext,
3-
useContext,
4-
useEffect,
5-
useState,
6-
ReactNode,
7-
} from 'react';
8-
import { authAdapter } from '@/shared/api/auth';
1+
// src/app/providers/auth-context.tsx
2+
import { createContext, useContext } from 'react';
93

10-
interface AuthContextType {
4+
export interface AuthContextType {
115
user: any | null;
126
isLoading: boolean;
137
setIsLoading: (loading: boolean) => void;
@@ -17,30 +11,10 @@ export const AuthContext = createContext<AuthContextType | undefined>(
1711
undefined
1812
);
1913

20-
export const AuthProvider = ({ children }: { children: ReactNode }) => {
21-
const [user, setUser] = useState<any | null>(null);
22-
const [isLoading, setIsLoading] = useState(true);
23-
useEffect(() => {
24-
const unsubscribe = authAdapter.onAuthStateChange((currentUser) => {
25-
setUser(currentUser);
26-
setIsLoading(false);
27-
if (window.location.href.endsWith('#')) {
28-
window.history.replaceState(null, '', window.location.pathname);
29-
}
30-
});
31-
return () => unsubscribe();
32-
}, []);
33-
34-
return (
35-
<AuthContext.Provider value={{ user, isLoading, setIsLoading }}>
36-
{children}
37-
</AuthContext.Provider>
38-
);
39-
};
40-
4114
export const useAuth = () => {
4215
const context = useContext(AuthContext);
43-
if (context === undefined)
16+
if (context === undefined) {
4417
throw new Error('useAuth must be used within an AuthProvider');
18+
}
4519
return context;
4620
};
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { useState, useEffect, ReactNode } from 'react';
2+
import { authAdapter } from '@/shared/api/auth';
3+
import { AuthContext } from './auth-context';
4+
5+
export const AuthProvider = ({ children }: { children: ReactNode }) => {
6+
const [user, setUser] = useState<any | null>(null);
7+
const [isLoading, setIsLoading] = useState(true);
8+
9+
useEffect(() => {
10+
const unsubscribe = authAdapter.onAuthStateChange((currentUser) => {
11+
setUser(currentUser);
12+
setIsLoading(false);
13+
if (window.location.href.endsWith('#')) {
14+
window.history.replaceState(null, '', window.location.pathname);
15+
}
16+
});
17+
return () => unsubscribe();
18+
}, []);
19+
20+
return (
21+
<AuthContext.Provider value={{ user, isLoading, setIsLoading }}>
22+
{children}
23+
</AuthContext.Provider>
24+
);
25+
};

src/app/providers/with-auth.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ComponentType } from 'react';
2-
import { AuthProvider } from './auth-context';
2+
import { AuthProvider } from './auth-provider';
33

44
export const withAuth = (Component: ComponentType) => {
55
const WrappedComponent = (props: any) => (

src/app/providers/with-router.tsx

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1-
// src/app/providers/with-router.tsx
2-
import { RouterProvider, createRouter } from '@tanstack/react-router';
3-
import { routeTree } from '../../routeTree.gen';
4-
import { ComponentType } from 'react';
5-
import { NotFoundPage } from '@/pages/not-found';
6-
7-
const router = createRouter({
8-
routeTree,
9-
defaultNotFoundComponent: () => {
10-
return <NotFoundPage />;
11-
},
12-
});
13-
14-
export const withRouter = (_Component: ComponentType) => {
15-
return () => <RouterProvider router={router} />;
1+
import { RouterProvider } from '@tanstack/react-router';
2+
import { router } from '../router';
3+
import { useAuth } from './auth-context';
4+
export const withRouter = (_Component: React.ComponentType) => {
5+
return function WithRouterWrapper() {
6+
const auth = useAuth();
7+
if (auth.isLoading) {
8+
return null;
9+
}
10+
return (
11+
<RouterProvider
12+
router={router}
13+
context={{ auth }} // This passes auth to all routes
14+
/>
15+
);
16+
};
1617
};

src/app/router.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { createRouter } from '@tanstack/react-router';
2+
import { routeTree } from '../routeTree.gen';
3+
import { NotFoundPage } from '@/pages/not-found';
4+
5+
export interface MyRouterContext {
6+
auth: {
7+
user: any | null;
8+
isLoading: boolean;
9+
};
10+
}
11+
12+
export const router = createRouter({
13+
routeTree,
14+
defaultNotFoundComponent: () => <NotFoundPage />,
15+
context: {
16+
auth: undefined!,
17+
},
18+
});
19+
20+
declare module '@tanstack/react-router' {
21+
interface Register {
22+
router: typeof router;
23+
}
24+
}

src/app/routes/__root.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Header } from '@/widgets/header';
2-
import { createRootRoute, Outlet } from '@tanstack/react-router';
2+
import { createRootRouteWithContext, Outlet } from '@tanstack/react-router';
3+
import { MyRouterContext } from '../router';
34
// import { TanStackRouterDevtools } from '@tanstack/react-router-devtools';
45

56
const RootLayout = () => (
@@ -10,4 +11,6 @@ const RootLayout = () => (
1011
</>
1112
);
1213

13-
export const Route = createRootRoute({ component: RootLayout });
14+
export const Route = createRootRouteWithContext<MyRouterContext>()({
15+
component: RootLayout,
16+
});

src/app/routes/_auth.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { createFileRoute, Outlet, redirect } from '@tanstack/react-router';
2+
3+
export const Route = createFileRoute('/_auth')({
4+
beforeLoad: ({ context, location }) => {
5+
if (context.auth.isLoading) {
6+
return;
7+
}
8+
9+
if (!context.auth.user) {
10+
throw redirect({
11+
to: '/',
12+
search: {
13+
redirect: location.pathname === '/' ? undefined : location.href,
14+
},
15+
});
16+
}
17+
},
18+
component: () => <Outlet />,
19+
});
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { DashboardPage } from '@/pages/dashboard';
22
import { createFileRoute } from '@tanstack/react-router';
33

4-
export const Route = createFileRoute('/dashboard')({
4+
export const Route = createFileRoute('/_auth/dashboard')({
55
component: DashboardPage,
66
});

src/pages/not-found/ui/NotFoundPage.tsx

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,27 +31,22 @@ export function NotFoundPage() {
3131
}}
3232
>
3333
<Box style={{ position: 'relative' }}>
34-
{/* Background Illustration */}
3534
<Illustration
3635
style={{
3736
position: 'absolute',
3837
inset: 0,
3938
opacity: 0.75,
40-
// Uses Mantine's CSS variables for light/dark mode compatibility
39+
4140
color:
4241
'light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-6))',
4342
}}
4443
/>
4544

46-
{/* Foreground Content */}
4745
<Box
48-
style={(theme) => ({
46+
style={() => ({
4947
paddingTop: rem(220),
5048
position: 'relative',
5149
zIndex: 1,
52-
[`@media (max-width: ${theme.breakpoints.sm})`]: {
53-
paddingTop: rem(120),
54-
},
5550
})}
5651
>
5752
<Title
@@ -60,9 +55,6 @@ export function NotFoundPage() {
6055
textAlign: 'center',
6156
fontWeight: 500,
6257
fontSize: rem(38),
63-
[`@media (max-width: ${theme.breakpoints.sm})`]: {
64-
fontSize: rem(32),
65-
},
6658
})}
6759
>
6860
Nothing to see here

src/routeTree.gen.ts

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,53 +9,59 @@
99
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
1010

1111
import { Route as rootRouteImport } from './app/routes/__root'
12-
import { Route as DashboardRouteImport } from './app/routes/dashboard'
12+
import { Route as AuthRouteImport } from './app/routes/_auth'
1313
import { Route as IndexRouteImport } from './app/routes/index'
14+
import { Route as AuthDashboardRouteImport } from './app/routes/_auth/dashboard'
1415

15-
const DashboardRoute = DashboardRouteImport.update({
16-
id: '/dashboard',
17-
path: '/dashboard',
16+
const AuthRoute = AuthRouteImport.update({
17+
id: '/_auth',
1818
getParentRoute: () => rootRouteImport,
1919
} as any)
2020
const IndexRoute = IndexRouteImport.update({
2121
id: '/',
2222
path: '/',
2323
getParentRoute: () => rootRouteImport,
2424
} as any)
25+
const AuthDashboardRoute = AuthDashboardRouteImport.update({
26+
id: '/dashboard',
27+
path: '/dashboard',
28+
getParentRoute: () => AuthRoute,
29+
} as any)
2530

2631
export interface FileRoutesByFullPath {
2732
'/': typeof IndexRoute
28-
'/dashboard': typeof DashboardRoute
33+
'/dashboard': typeof AuthDashboardRoute
2934
}
3035
export interface FileRoutesByTo {
3136
'/': typeof IndexRoute
32-
'/dashboard': typeof DashboardRoute
37+
'/dashboard': typeof AuthDashboardRoute
3338
}
3439
export interface FileRoutesById {
3540
__root__: typeof rootRouteImport
3641
'/': typeof IndexRoute
37-
'/dashboard': typeof DashboardRoute
42+
'/_auth': typeof AuthRouteWithChildren
43+
'/_auth/dashboard': typeof AuthDashboardRoute
3844
}
3945
export interface FileRouteTypes {
4046
fileRoutesByFullPath: FileRoutesByFullPath
4147
fullPaths: '/' | '/dashboard'
4248
fileRoutesByTo: FileRoutesByTo
4349
to: '/' | '/dashboard'
44-
id: '__root__' | '/' | '/dashboard'
50+
id: '__root__' | '/' | '/_auth' | '/_auth/dashboard'
4551
fileRoutesById: FileRoutesById
4652
}
4753
export interface RootRouteChildren {
4854
IndexRoute: typeof IndexRoute
49-
DashboardRoute: typeof DashboardRoute
55+
AuthRoute: typeof AuthRouteWithChildren
5056
}
5157

5258
declare module '@tanstack/react-router' {
5359
interface FileRoutesByPath {
54-
'/dashboard': {
55-
id: '/dashboard'
56-
path: '/dashboard'
57-
fullPath: '/dashboard'
58-
preLoaderRoute: typeof DashboardRouteImport
60+
'/_auth': {
61+
id: '/_auth'
62+
path: ''
63+
fullPath: ''
64+
preLoaderRoute: typeof AuthRouteImport
5965
parentRoute: typeof rootRouteImport
6066
}
6167
'/': {
@@ -65,12 +71,29 @@ declare module '@tanstack/react-router' {
6571
preLoaderRoute: typeof IndexRouteImport
6672
parentRoute: typeof rootRouteImport
6773
}
74+
'/_auth/dashboard': {
75+
id: '/_auth/dashboard'
76+
path: '/dashboard'
77+
fullPath: '/dashboard'
78+
preLoaderRoute: typeof AuthDashboardRouteImport
79+
parentRoute: typeof AuthRoute
80+
}
6881
}
6982
}
7083

84+
interface AuthRouteChildren {
85+
AuthDashboardRoute: typeof AuthDashboardRoute
86+
}
87+
88+
const AuthRouteChildren: AuthRouteChildren = {
89+
AuthDashboardRoute: AuthDashboardRoute,
90+
}
91+
92+
const AuthRouteWithChildren = AuthRoute._addFileChildren(AuthRouteChildren)
93+
7194
const rootRouteChildren: RootRouteChildren = {
7295
IndexRoute: IndexRoute,
73-
DashboardRoute: DashboardRoute,
96+
AuthRoute: AuthRouteWithChildren,
7497
}
7598
export const routeTree = rootRouteImport
7699
._addFileChildren(rootRouteChildren)

0 commit comments

Comments
 (0)