diff --git a/src/app/admin/dashboard/page.tsx b/src/app/admin/dashboard/page.tsx index 0d92218..c7aecb2 100644 --- a/src/app/admin/dashboard/page.tsx +++ b/src/app/admin/dashboard/page.tsx @@ -3,14 +3,17 @@ import Background from '@/components/staff/qr/background'; import Top from './_components/top'; import Detail from './_components/detail'; +import Protect from '@/components/protect'; export default function Page() { return ( -
- - -
- -
+ +
+ + +
+ +
+
); } diff --git a/src/app/staff/qr/page.tsx b/src/app/staff/qr/page.tsx index 5e7b4b6..dba0abd 100644 --- a/src/app/staff/qr/page.tsx +++ b/src/app/staff/qr/page.tsx @@ -2,15 +2,18 @@ import Background from '@/components/staff/qr/background'; import TopPart from '@/components/staff/qr/toppart'; import Edit from '@/components/staff/qr/editbutton'; import QrButton from '@/components/staff/qr/qrbutton'; +import Protect from '@/components/protect'; export default function Home() { return (
- -
- - - -
+ + +
+ + + +
+
); } diff --git a/src/components/protect.tsx b/src/components/protect.tsx new file mode 100644 index 0000000..892889c --- /dev/null +++ b/src/components/protect.tsx @@ -0,0 +1,43 @@ +'use client'; + +import { Role } from '@/const/role'; +import { useAuth } from '@/contexts/auth'; +import { useRouter } from 'next/navigation'; +import React from 'react'; +import Load from './loading/loading'; +import toast from 'react-hot-toast'; + +interface ProtectProps { + roles: Role[]; + children: React.ReactNode; + callBack?: string; +} + +export default function Protect({ + roles, + children, + callBack = '/', +}: ProtectProps) { + const { user, isLoggingIn, isInitialized } = useAuth(); + const router = useRouter(); + + if (isLoggingIn || !isInitialized) { + return ; + } + + if (!user || !roles.includes(user.role)) { + toast.error('You cannot access this page'); + router.push(callBack); + return ; + } + + return children; +} + +function Loading() { + return ( +
+ +
+ ); +} diff --git a/src/components/staff/qr/editbutton.tsx b/src/components/staff/qr/editbutton.tsx index ecc7291..6d2d91e 100644 --- a/src/components/staff/qr/editbutton.tsx +++ b/src/components/staff/qr/editbutton.tsx @@ -5,7 +5,7 @@ import Link from 'next/link'; export default function Edit() { return (
diff --git a/src/contexts/auth.tsx b/src/contexts/auth.tsx index 62759b5..cb04290 100644 --- a/src/contexts/auth.tsx +++ b/src/contexts/auth.tsx @@ -34,6 +34,7 @@ interface AuthState { isLoggingIn: boolean; isRegistering: boolean; isEditing: boolean; + isInitialized: boolean; login(): Promise>; edit(req: EditReq): Promise>; register(req: RegisterReq): Promise>; @@ -54,6 +55,7 @@ export default function AuthProvider({ children }: { children: ReactNode }) { isLoggingIn: false, isRegistering: false, isEditing: false, + isInitialized: false, }); const { client } = useLiff(); @@ -71,15 +73,16 @@ export default function AuthProvider({ children }: { children: ReactNode }) { return { success: false, error: error }; } + console.log('start login'); set('isLoggingIn', true); const loginResp = await sendLogin(userId); if (loginResp.success) { set('token', loginResp.result); - set('isLoggedIn', true); } else { console.error('login failed:', loginResp.error); set('loginError', loginResp.error); + set('isLoggingIn', false); return loginResp; } @@ -89,10 +92,11 @@ export default function AuthProvider({ children }: { children: ReactNode }) { } else { console.error('get user failed:', UserResp.error); set('loginError', UserResp.error); + set('isLoggingIn', false); return UserResp; } - set('isLoggedIn', false); + set('isLoggingIn', false); return { success: true, @@ -136,6 +140,7 @@ export default function AuthProvider({ children }: { children: ReactNode }) { useEffect(() => { login(); + set('isInitialized', true); // eslint-disable-next-line react-hooks/exhaustive-deps }, []);