Skip to content

Commit 43585fd

Browse files
committed
feat: ui dashboard
1 parent 6b35546 commit 43585fd

File tree

21 files changed

+324
-22
lines changed

21 files changed

+324
-22
lines changed

client/src/apis/auth.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { TLogin } from '@/lib/schema/login';
55
import { TRegister } from '@/lib/schema/register';
66
import { TSetPass } from '@/lib/schema/set-pass';
77
import { TBaseResponse, TToken } from '@/types/share';
8+
import { TUser } from '@/types/user';
89

910
class Auth {
1011
login(data: TLogin): Promise<TBaseResponse<TToken>> {
@@ -25,7 +26,7 @@ class Auth {
2526
}
2627

2728
// TODO: SHOULD BE CHANGE TYPE ANY TO TYPE USER
28-
getCurrentUser(): Promise<TBaseResponse<any>> {
29+
getCurrentUser(): Promise<TBaseResponse<TUser>> {
2930
return http_client.get(ENDPOINTS.AUTH.CURRENT_USER);
3031
}
3132

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './layout';
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Outlet } from '@tanstack/react-router';
2+
import Sidebar from './sidebar';
3+
export const Layout = () => {
4+
return (
5+
<div className="flex min-h-svh ">
6+
<Sidebar />
7+
<div className="ml-sidebar w-full">
8+
<Outlet />
9+
</div>
10+
</div>
11+
);
12+
};
13+
14+
export default Layout;
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import {
2+
Avatar,
3+
AvatarFallback,
4+
AvatarImage,
5+
Tooltip,
6+
TooltipContent,
7+
TooltipProvider,
8+
TooltipTrigger,
9+
} from '@/components/ui';
10+
import { useUserStore } from '@/store/use-user';
11+
import { Link, LinkProps } from '@tanstack/react-router';
12+
import {
13+
Bot,
14+
BrainCircuit,
15+
Cable,
16+
MessageSquareCode,
17+
Settings,
18+
} from 'lucide-react';
19+
import { useTranslation } from 'react-i18next';
20+
21+
const SIDEBAR_ITEMS: Array<{
22+
Icon: JSX.Element;
23+
i18n: string;
24+
to: LinkProps['to'];
25+
}> = [
26+
{
27+
Icon: (
28+
<MessageSquareCode className="w-5 h-5 text-white group-hover:opacity-85 transition-all" />
29+
),
30+
i18n: 'chatbots',
31+
to: '/chatbots',
32+
},
33+
{
34+
Icon: (
35+
<BrainCircuit className="w-5 h-5 text-white group-hover:opacity-85 transition-all" />
36+
),
37+
i18n: 'training',
38+
to: '/chatbots',
39+
},
40+
{
41+
Icon: (
42+
<Cable className="w-5 h-5 text-white group-hover:opacity-85 transition-all" />
43+
),
44+
i18n: 'integrations',
45+
to: '/chatbots',
46+
},
47+
];
48+
49+
const Sidebar = () => {
50+
const { t } = useTranslation('common');
51+
const { user } = useUserStore();
52+
53+
return (
54+
<aside className="w-sidebar bg-stone-800 min-h-svh flex flex-col fixed left-0 top-0 bottom-0">
55+
<Link
56+
className="bg-primary w-sidebar h-sidebar flex items-center justify-center"
57+
to="/dashboard"
58+
>
59+
<Bot size={32} className="text-white" />
60+
</Link>
61+
<nav className="flex flex-col flex-1">
62+
<ul className="flex flex-col">
63+
{SIDEBAR_ITEMS.map((item, index) => (
64+
<TooltipProvider key={item.i18n + index}>
65+
<Tooltip>
66+
<TooltipTrigger>
67+
<li className="h-12 w-full flex items-center justify-center group">
68+
<Link
69+
search
70+
to={item.to}
71+
className="w-full h-full flex items-center justify-center"
72+
>
73+
{item.Icon}
74+
</Link>
75+
</li>
76+
</TooltipTrigger>
77+
<TooltipContent side="right">
78+
<p>{t(item.i18n as any)}</p>
79+
</TooltipContent>
80+
</Tooltip>
81+
</TooltipProvider>
82+
))}
83+
</ul>
84+
85+
<div className="mt-auto">
86+
<TooltipProvider>
87+
<Tooltip>
88+
<TooltipTrigger className="h-12 w-full flex items-center justify-center group">
89+
<Link
90+
search
91+
to="/settings"
92+
className="w-full h-full flex items-center justify-center"
93+
>
94+
<Settings className="w-5 h-5 text-white group-hover:opacity-85 transition-all" />
95+
</Link>
96+
</TooltipTrigger>
97+
<TooltipContent side="right">
98+
<p>{t('settings')}</p>
99+
</TooltipContent>
100+
</Tooltip>
101+
</TooltipProvider>
102+
<div className="flex items-center justify-center cursor-pointer w-sidebar h-sidebar">
103+
<Avatar className="w-9 h-9">
104+
<AvatarImage
105+
src={user?.avatar as string}
106+
alt={user?.name}
107+
/>
108+
<AvatarFallback>
109+
<span>{user?.name?.[0]}</span>
110+
</AvatarFallback>
111+
</Avatar>
112+
</div>
113+
</div>
114+
</nav>
115+
</aside>
116+
);
117+
};
118+
119+
export default Sidebar;

client/src/constants/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export const ENDPOINTS = {
44
LOGIN: '/auth/login',
55
LOGIN_ADMIN: '/auth/login-admin',
66
REGISTER: '/auth/register',
7-
CURRENT_USER: '/auth/current-user',
7+
CURRENT_USER: '/auth/me',
88
REFRESH_TOKEN: '/auth/refresh-token',
99
FORGOT_PASSWORD: '/auth/forgot-password',
1010
RESET_PASSWORD: '/auth/reset-password',

client/src/hooks/auth/use-login-with-provider.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
import { auth } from '@/apis/auth';
22
import { auth as fAuth } from '@/lib/firebase';
33
import { useMutation } from '@tanstack/react-query';
4+
import { useSearch } from '@tanstack/react-router';
45
import { AuthProvider, getIdToken, signInWithPopup } from 'firebase/auth';
56
import { useTranslation } from 'react-i18next';
67
import { toast } from 'sonner';
78

89
export const useLoginWithProvider = (provider: AuthProvider) => {
910
const { t } = useTranslation('common');
11+
const search = useSearch({
12+
from: '/_auth/login',
13+
});
14+
1015
return useMutation({
1116
mutationFn: async () => {
1217
const user = await signInWithPopup(fAuth, provider);
@@ -17,8 +22,11 @@ export const useLoginWithProvider = (provider: AuthProvider) => {
1722
},
1823
onSuccess(data) {
1924
toast.success(data.message);
25+
26+
window.location.href = search.redirect || '/dashboard';
2027
},
2128
onError(err: any) {
29+
console.log(err);
2230
toast.error(err?.response?.data?.message || t('api_error'));
2331
},
2432
});

client/src/hooks/auth/use-login.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
11
import { auth } from '@/apis/auth';
22
import { TLogin } from '@/lib/schema/login';
33
import { useMutation } from '@tanstack/react-query';
4+
import { useSearch } from '@tanstack/react-router';
45
import { useTranslation } from 'react-i18next';
56
import { toast } from 'sonner';
67

78
export const useLogin = () => {
89
const { t } = useTranslation('common');
10+
const search = useSearch({
11+
from: '/_auth/login',
12+
});
13+
914
return useMutation({
1015
mutationFn: (data: TLogin) => {
1116
return auth.login(data);
1217
},
1318
onSuccess(data) {
1419
toast.success(data.message);
20+
21+
window.location.href = search.redirect || '/dashboard';
1522
},
1623
onError(err: any) {
24+
console.log(err);
1725
toast.error(err?.response?.data?.message || t('api_error'));
1826
},
1927
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { auth } from '@/apis/auth';
2+
import { queryOptions } from '@tanstack/react-query';
3+
4+
export const currentUserQueryOptions = () =>
5+
queryOptions({
6+
queryKey: ['currentUser'],
7+
queryFn: () =>
8+
auth
9+
.getCurrentUser()
10+
.then((res) => res.data)
11+
.catch(() => null),
12+
});

client/src/locales/en/common.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,9 @@
66
"term": "By continuing, you agree to our <term>Terms of Service</term> and <privacy>Privacy Policy</privacy>.",
77
"register": "Register",
88
"back_to_login": "Back to login",
9-
"login_with": "Login with {{provider}}"
9+
"login_with": "Login with {{provider}}",
10+
"chatbots": "Chatbots",
11+
"training": "Training",
12+
"integrations": "Integrations",
13+
"settings": "Settings"
1014
}

client/src/locales/vi/common.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,9 @@
55
"api_error": "Đã xảy ra lỗi trong khi xử lý yêu cầu của bạn. Vui lòng thử lại sau.",
66
"register": "Đăng ký",
77
"back_to_login": "Quay lại đăng nhập",
8-
"login_with": "Đăng nhập với {{provider}}"
8+
"login_with": "Đăng nhập với {{provider}}",
9+
"chatbots": "Chatbots",
10+
"training": "Đào tạo",
11+
"integrations": "Tích hợp",
12+
"settings": "Cài đặt"
913
}

0 commit comments

Comments
 (0)