Initial commit for new panel
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
"use client";
|
||||
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useEffect, ReactNode } from "react";
|
||||
import { useUser } from "./";
|
||||
import Loading from "@/app/loading";
|
||||
|
||||
interface AuthGuardProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
const AuthGuard = ({ children }: AuthGuardProps): React.ReactNode => {
|
||||
const { isAuthenticated, isLoading } = useUser();
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLoading && !isAuthenticated) {
|
||||
router.push("/auth/sign-in");
|
||||
}
|
||||
}, [isLoading, isAuthenticated, router]);
|
||||
|
||||
if (isLoading || !isAuthenticated) {
|
||||
return <Loading />;
|
||||
}
|
||||
|
||||
return children;
|
||||
};
|
||||
|
||||
export default AuthGuard;
|
||||
@@ -0,0 +1,26 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect } from "react";
|
||||
import { useUser } from "./";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Loading from "../app/loading";
|
||||
|
||||
interface LoginGuardProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
const LoginGuard = ({ children }: LoginGuardProps): React.ReactNode => {
|
||||
const { isAuthenticated, isLoading } = useUser();
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLoading && isAuthenticated) {
|
||||
router.push("/design-system");
|
||||
}
|
||||
}, [isLoading, isAuthenticated, router]);
|
||||
|
||||
if (isLoading || isAuthenticated) {
|
||||
return <Loading />;
|
||||
}
|
||||
return children;
|
||||
};
|
||||
export default LoginGuard;
|
||||
@@ -0,0 +1,103 @@
|
||||
// src/contexts/UserContext.tsx
|
||||
"use client";
|
||||
|
||||
import React, {
|
||||
createContext,
|
||||
useState,
|
||||
useContext,
|
||||
useEffect,
|
||||
useCallback,
|
||||
useMemo,
|
||||
ReactNode,
|
||||
} from "react";
|
||||
import Cookies from "js-cookie";
|
||||
|
||||
import { z } from "zod";
|
||||
import { UserSchema, ILoginResponse } from "../lib/api/types";
|
||||
import { COOKIE_KEYS } from "../lib/shared/cookies";
|
||||
|
||||
type User = z.infer<typeof UserSchema>;
|
||||
|
||||
interface UserContextType {
|
||||
user: User | null;
|
||||
accessToken: string | null;
|
||||
isAuthenticated: boolean;
|
||||
isLoading: boolean;
|
||||
setAuthState: (data: ILoginResponse) => void;
|
||||
logout: () => void;
|
||||
}
|
||||
|
||||
const UserContext = createContext<UserContextType | undefined>(undefined);
|
||||
|
||||
interface UserProviderProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export const UserProvider: React.FC<UserProviderProps> = ({ children }) => {
|
||||
const [user, setUser] = useState<User | null>(null);
|
||||
const [accessToken, setAccessToken] = useState<string | null>(null);
|
||||
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||
|
||||
useEffect(() => {
|
||||
try {
|
||||
const tokenFromCookie = Cookies.get(COOKIE_KEYS.access_token);
|
||||
const userJson = Cookies.get(COOKIE_KEYS.user);
|
||||
|
||||
if (tokenFromCookie && userJson) {
|
||||
const userFromCookie = JSON.parse(userJson);
|
||||
const validation = UserSchema.safeParse(userFromCookie);
|
||||
if (validation.success) {
|
||||
setUser(validation.data);
|
||||
setAccessToken(tokenFromCookie);
|
||||
} else {
|
||||
console.warn("Invalid user data in cookie:", validation.error);
|
||||
logout();
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Failed to parse user data from cookies", e);
|
||||
logout();
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const setAuthState = useCallback((data: ILoginResponse) => {
|
||||
setAccessToken(data.access_token);
|
||||
setUser(data.user);
|
||||
|
||||
Cookies.set(COOKIE_KEYS.access_token, data.access_token);
|
||||
Cookies.set(COOKIE_KEYS.refresh_token, data.refresh_token);
|
||||
Cookies.set(COOKIE_KEYS.user, JSON.stringify(data.user));
|
||||
}, []);
|
||||
|
||||
const logout = useCallback(() => {
|
||||
setUser(null);
|
||||
setAccessToken(null);
|
||||
Cookies.remove(COOKIE_KEYS.access_token);
|
||||
Cookies.remove(COOKIE_KEYS.refresh_token);
|
||||
Cookies.remove(COOKIE_KEYS.user);
|
||||
}, []);
|
||||
|
||||
const value = useMemo(
|
||||
() => ({
|
||||
user,
|
||||
accessToken,
|
||||
isAuthenticated: !!accessToken,
|
||||
isLoading,
|
||||
setAuthState,
|
||||
logout,
|
||||
}),
|
||||
[user, accessToken, isLoading, setAuthState, logout]
|
||||
);
|
||||
|
||||
return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
|
||||
};
|
||||
|
||||
export const useUser = (): UserContextType => {
|
||||
const context = useContext(UserContext);
|
||||
if (context === undefined) {
|
||||
throw new Error("useUser must be used within a UserProvider");
|
||||
}
|
||||
return context;
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
export { default as AuthGuard } from "./Auth-guard.ctx";
|
||||
export { default as LoginGuard } from "./Login-guard.ctx";
|
||||
export * from "./User.ctx";
|
||||
Reference in New Issue
Block a user