Initial commit for new panel

This commit is contained in:
AmirReza Jamali
2025-09-09 11:20:26 +03:30
commit 1d4ccb3575
343 changed files with 20031 additions and 0 deletions
+29
View File
@@ -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;
+26
View File
@@ -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;
+103
View File
@@ -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;
};
+3
View File
@@ -0,0 +1,3 @@
export { default as AuthGuard } from "./Auth-guard.ctx";
export { default as LoginGuard } from "./Login-guard.ctx";
export * from "./User.ctx";