feat: add custom authen hooks and context

This commit is contained in:
Sosokker 2025-02-13 23:17:03 +07:00
parent ee434d4c5a
commit 8c5acc7921
4 changed files with 66 additions and 3 deletions

View File

@ -7,6 +7,7 @@ interface SessionContextType {
user: any | null; user: any | null;
setToken: (token: string | null) => void; setToken: (token: string | null) => void;
setUser: (user: any | null) => void; setUser: (user: any | null) => void;
loading: boolean;
} }
const SessionContext = createContext<SessionContextType | undefined>(undefined); const SessionContext = createContext<SessionContextType | undefined>(undefined);
@ -18,7 +19,9 @@ interface SessionProviderProps {
export function SessionProvider({ children }: SessionProviderProps) { export function SessionProvider({ children }: SessionProviderProps) {
const [token, setTokenState] = useState<string | null>(null); const [token, setTokenState] = useState<string | null>(null);
const [user, setUserState] = useState<any | null>(null); const [user, setUserState] = useState<any | null>(null);
const [loading, setLoading] = useState<boolean>(true);
// Save or remove token from localStorage accordingly
const setToken = (newToken: string | null) => { const setToken = (newToken: string | null) => {
if (newToken) { if (newToken) {
localStorage.setItem("token", newToken); localStorage.setItem("token", newToken);
@ -28,6 +31,7 @@ export function SessionProvider({ children }: SessionProviderProps) {
setTokenState(newToken); setTokenState(newToken);
}; };
// Save or remove user from localStorage accordingly
const setUser = (newUser: any | null) => { const setUser = (newUser: any | null) => {
if (newUser) { if (newUser) {
localStorage.setItem("user", JSON.stringify(newUser)); localStorage.setItem("user", JSON.stringify(newUser));
@ -37,6 +41,7 @@ export function SessionProvider({ children }: SessionProviderProps) {
setUserState(newUser); setUserState(newUser);
}; };
// On mount, check localStorage for token and user data
useEffect(() => { useEffect(() => {
const storedToken = localStorage.getItem("token"); const storedToken = localStorage.getItem("token");
const storedUser = localStorage.getItem("user"); const storedUser = localStorage.getItem("user");
@ -50,7 +55,12 @@ export function SessionProvider({ children }: SessionProviderProps) {
console.error("Failed to parse stored user.", error); console.error("Failed to parse stored user.", error);
} }
} }
setLoading(false);
}, []); }, []);
return <SessionContext.Provider value={{ token, user, setToken, setUser }}>{children}</SessionContext.Provider>; return (
<SessionContext.Provider value={{ token, user, setToken, setUser, loading }}>{children}</SessionContext.Provider>
);
} }
export { SessionContext };

View File

@ -0,0 +1,25 @@
"use client";
import { useContext } from "react";
import { useRouter } from "next/navigation";
import { SessionContext } from "@/context/SessionContext";
export function useLogout() {
const router = useRouter();
const context = useContext(SessionContext);
if (!context) {
throw new Error("useLogout must be used within a SessionProvider");
}
const { setToken, setUser } = context;
const logout = () => {
setToken(null);
setUser(null);
router.push("/");
};
return logout;
}

View File

@ -0,0 +1,18 @@
"use client";
import { useEffect } from "react";
import { useRouter } from "next/navigation";
import { useSession } from "./useSession";
export function useProtectedRoute() {
const { data: session } = useSession();
const router = useRouter();
useEffect(() => {
if (!session?.token) {
router.push("/signin");
}
}, [session?.token, router]);
return session?.token;
}

View File

@ -1,12 +1,22 @@
"use client"; "use client";
import { SessionContext } from "next-auth/react";
import { useContext } from "react"; import { useContext } from "react";
import { SessionContext } from "@/context/SessionContext";
export function useSession() { export function useSession() {
const context = useContext(SessionContext); const context = useContext(SessionContext);
if (!context) { if (!context) {
throw new Error("useSession must be used within a SessionProvider"); throw new Error("useSession must be used within a SessionProvider");
} }
return context;
const { token, user, loading } = context;
let status: "loading" | "authenticated" | "unauthenticated";
if (loading) status = "loading";
else if (token) status = "authenticated";
else status = "unauthenticated";
const session = token ? { token, user } : null;
return { data: session, status };
} }