Skip to content

Commit 8eca25c

Browse files
committed
feat: migrate tanstac-router -> react-router-dom
1 parent c6f8144 commit 8eca25c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+2100
-1823
lines changed

client/.eslintrc.cjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,6 @@ module.exports = {
2323
caughtErrorsIgnorePattern: '^_',
2424
},
2525
],
26+
'@typescript-eslint/ban-ts-comment': 'off',
2627
},
2728
};

client/package-lock.json

Lines changed: 59 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,11 @@
6565
"react-hook-form": "^7.50.1",
6666
"react-i18next": "^14.0.5",
6767
"react-resizable-panels": "^2.0.9",
68+
"react-router-dom": "^6.22.2",
6869
"sonner": "^1.4.0",
6970
"tailwind-merge": "^2.2.1",
7071
"tailwindcss-animate": "^1.0.7",
72+
"usehooks-ts": "^2.15.1",
7173
"vaul": "^0.9.0",
7274
"zod": "^3.22.4",
7375
"zustand": "^4.5.1"

client/src/app.tsx

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
import { createBrowserRouter, redirect } from 'react-router-dom';
2+
import { queryClient } from '@/lib/query-client';
3+
import i18n from './i18n';
4+
import {
5+
Channels,
6+
ForgotPassword,
7+
Login,
8+
Mail,
9+
Profiles,
10+
Register,
11+
SetPassword,
12+
} from '@/pages';
13+
import { useAppLayoutStore, useSettingStore, useUserStore } from '@/store';
14+
import {
15+
currentUserQueryOptions,
16+
settingQueryOption,
17+
} from '@/lib/query-options';
18+
import { AppLayout, AuthLayout, SettingLayout } from '@/components/layouts';
19+
import { TChannelQuery } from './types/channel';
20+
import { queryStringToObject } from './utils';
21+
import { queryChannelsOption } from './lib/query-options/channel';
22+
23+
export const router = createBrowserRouter([
24+
{
25+
children: [
26+
{
27+
loader: async ({ request }) => {
28+
const redirectUrl = new URL(request.url).searchParams.get(
29+
'redirect'
30+
);
31+
const user = await queryClient.ensureQueryData(
32+
currentUserQueryOptions()
33+
);
34+
35+
if (user) {
36+
return redirect(redirectUrl || '/chatbots');
37+
}
38+
39+
return null;
40+
},
41+
Component: AuthLayout,
42+
children: [
43+
{
44+
path: '/login',
45+
Component: Login,
46+
index: true,
47+
},
48+
{
49+
path: '/register',
50+
Component: Register,
51+
},
52+
{
53+
path: '/forgot-password',
54+
Component: ForgotPassword,
55+
},
56+
{
57+
path: '/set-password',
58+
Component: SetPassword,
59+
},
60+
],
61+
},
62+
{
63+
Component: AppLayout,
64+
loader: async () => {
65+
const user = await queryClient.ensureQueryData(
66+
currentUserQueryOptions()
67+
);
68+
69+
const url = new URLSearchParams({
70+
redirect: location.href,
71+
});
72+
73+
if (!user) {
74+
return redirect(`/login?${url.toString()}`);
75+
}
76+
77+
useUserStore.getState().setUser(user);
78+
79+
return null;
80+
},
81+
children: [
82+
{
83+
path: '/dashboard',
84+
index: true,
85+
loader: async () => {
86+
return redirect('/chatbots');
87+
},
88+
},
89+
{
90+
path: '/chatbots',
91+
element: <div>a</div>,
92+
loader: () => {
93+
useAppLayoutStore
94+
.getState()
95+
.setTitle(i18n.t('common:chatbots'));
96+
97+
return null;
98+
},
99+
},
100+
{
101+
path: '/channels',
102+
Component: Channels,
103+
loader: async ({ request }) => {
104+
const query: TChannelQuery = queryStringToObject(
105+
request.url
106+
);
107+
108+
await queryClient.ensureQueryData(
109+
queryChannelsOption(query)
110+
);
111+
112+
useAppLayoutStore
113+
.getState()
114+
.setTitle(i18n.t('common:channels'));
115+
116+
return null;
117+
},
118+
},
119+
{
120+
path: '/settings',
121+
Component: SettingLayout,
122+
loader: async () => {
123+
const data =
124+
await queryClient.ensureQueryData(settingQueryOption());
125+
126+
useSettingStore.getState().setSetting(data);
127+
useAppLayoutStore
128+
.getState()
129+
.setTitle(i18n.t('common:settings'));
130+
131+
return null;
132+
},
133+
children: [
134+
{
135+
path: 'mail',
136+
Component: Mail,
137+
},
138+
{
139+
path: 'profiles',
140+
Component: Profiles,
141+
},
142+
{
143+
index: true,
144+
loader: async () => {
145+
return redirect('/settings/profiles');
146+
},
147+
},
148+
],
149+
},
150+
],
151+
},
152+
{
153+
path: '/',
154+
element: <div>Hi</div>,
155+
},
156+
],
157+
},
158+
]);

client/src/components/forms/login.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { useErrorsLngChange } from '@/hooks/use-errors-lng-change';
22
import { TLogin, useLoginSchema } from '@/lib/schema/login';
33
import { zodResolver } from '@hookform/resolvers/zod';
4-
import { Link } from '@tanstack/react-router';
54
import { useForm } from 'react-hook-form';
65
import { useTranslation } from 'react-i18next';
76
import {
@@ -14,6 +13,7 @@ import {
1413
FormMessage,
1514
Input,
1615
} from '../ui';
16+
import { Link } from 'react-router-dom';
1717

1818
type Props = {
1919
loading?: boolean;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { useAppLayoutStore } from '@/store/use-app-layout';
2+
3+
export const Header = () => {
4+
const { title } = useAppLayoutStore();
5+
return (
6+
<header className="fixed h-header left-sidebar top-0 right-0 bg-background border-b border-border shadow-sm px-6 flex items-center">
7+
<span className="text-lg font-semibold">{title}</span>
8+
</header>
9+
);
10+
};

client/src/components/layouts/app/layout.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
import { Outlet } from '@tanstack/react-router';
21
import Sidebar from './sidebar';
2+
import { Header } from './header';
3+
import { Outlet } from 'react-router-dom';
4+
35
export const Layout = () => {
46
return (
57
<div className="flex min-h-svh ">
8+
<Header />
69
<Sidebar />
7-
<div className="ml-sidebar w-full">
10+
<div className="ml-sidebar w-full mt-header">
811
<Outlet />
912
</div>
1013
</div>

client/src/components/layouts/app/sidebar.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
TooltipTrigger,
99
} from '@/components/ui';
1010
import { useUserStore } from '@/store/use-user';
11-
import { Link, LinkProps } from '@tanstack/react-router';
1211
import {
1312
Bot,
1413
BrainCircuit,
@@ -17,11 +16,12 @@ import {
1716
Settings,
1817
} from 'lucide-react';
1918
import { useTranslation } from 'react-i18next';
19+
import { Link } from 'react-router-dom';
2020

2121
const SIDEBAR_ITEMS: Array<{
2222
Icon: JSX.Element;
2323
i18n: string;
24-
to: LinkProps['to'];
24+
to: string;
2525
}> = [
2626
{
2727
Icon: (
@@ -41,8 +41,8 @@ const SIDEBAR_ITEMS: Array<{
4141
Icon: (
4242
<Cable className="w-5 h-5 text-white group-hover:opacity-85 transition-all" />
4343
),
44-
i18n: 'integrations',
45-
to: '/chatbots',
44+
i18n: 'channels',
45+
to: '/channels',
4646
},
4747
];
4848

@@ -66,7 +66,6 @@ const Sidebar = () => {
6666
<TooltipTrigger>
6767
<li className="h-12 w-full flex items-center justify-center group">
6868
<Link
69-
search
7069
to={item.to}
7170
className="w-full h-full flex items-center justify-center"
7271
>
@@ -87,7 +86,6 @@ const Sidebar = () => {
8786
<Tooltip>
8887
<TooltipTrigger className="h-12 w-full flex items-center justify-center group">
8988
<Link
90-
search
9189
to="/settings"
9290
className="w-full h-full flex items-center justify-center"
9391
>

client/src/components/layouts/auth/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import banner from '@/assets/login-banner.png';
22
import ButtonLang from '@/components/btn-lang';
33
import { LogoText } from '@/components/ui';
4-
import { Link, Outlet } from '@tanstack/react-router';
54
import { Bot } from 'lucide-react';
65
import { useTranslation } from 'react-i18next';
6+
import { Link, Outlet } from 'react-router-dom';
77

88
export const Layout = () => {
99
const { t } = useTranslation('layout');
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export { Layout as AppLayout } from './app';
2+
export { Layout as AuthLayout } from './auth';
3+
export { Layout as SettingLayout } from './setting';

0 commit comments

Comments
 (0)