generated from muhtadeetaron/nextjs-template
feat(zustand): add zustand stores for exam, timer and auth
This commit is contained in:
90
stores/authStore.ts
Normal file
90
stores/authStore.ts
Normal file
@ -0,0 +1,90 @@
|
||||
"use client";
|
||||
|
||||
import { create } from "zustand";
|
||||
import { UserData } from "@/types/auth";
|
||||
import { API_URL } from "@/lib/auth";
|
||||
|
||||
// Cookie utilities
|
||||
const getCookie = (name: string): string | null => {
|
||||
if (typeof document === "undefined") return null;
|
||||
|
||||
const value = `; ${document.cookie}`;
|
||||
const parts = value.split(`; ${name}=`);
|
||||
if (parts.length === 2) {
|
||||
return parts.pop()?.split(";").shift() || null;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const setCookie = (
|
||||
name: string,
|
||||
value: string | null,
|
||||
days: number = 7
|
||||
): void => {
|
||||
if (typeof document === "undefined") return;
|
||||
|
||||
if (value === null) {
|
||||
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; SameSite=Strict; Secure`;
|
||||
} else {
|
||||
const expires = new Date();
|
||||
expires.setTime(expires.getTime() + days * 24 * 60 * 60 * 1000);
|
||||
document.cookie = `${name}=${value}; expires=${expires.toUTCString()}; path=/; SameSite=Strict; Secure`;
|
||||
}
|
||||
};
|
||||
|
||||
interface AuthState {
|
||||
token: string | null;
|
||||
isLoading: boolean;
|
||||
user: UserData | null;
|
||||
|
||||
setToken: (token: string | null) => void;
|
||||
fetchUser: () => Promise<void>;
|
||||
logout: () => void;
|
||||
initializeAuth: () => Promise<void>;
|
||||
}
|
||||
|
||||
export const useAuthStore = create<AuthState>((set, get) => ({
|
||||
token: null,
|
||||
isLoading: true,
|
||||
user: null,
|
||||
|
||||
setToken: (newToken) => {
|
||||
set({ token: newToken });
|
||||
setCookie("authToken", newToken);
|
||||
},
|
||||
|
||||
fetchUser: async () => {
|
||||
const token = get().token;
|
||||
if (!token) return;
|
||||
|
||||
try {
|
||||
const res = await fetch(`${API_URL}/me/profile/`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
|
||||
if (!res.ok) throw new Error("Failed to fetch user info");
|
||||
|
||||
const data: UserData = await res.json();
|
||||
set({ user: data });
|
||||
} catch (err) {
|
||||
console.error("Error fetching user:", err);
|
||||
get().logout();
|
||||
}
|
||||
},
|
||||
|
||||
logout: () => {
|
||||
set({ token: null, user: null });
|
||||
setCookie("authToken", null);
|
||||
},
|
||||
|
||||
initializeAuth: async () => {
|
||||
const storedToken = getCookie("authToken");
|
||||
if (storedToken) {
|
||||
set({ token: storedToken });
|
||||
await get().fetchUser();
|
||||
}
|
||||
set({ isLoading: false });
|
||||
},
|
||||
}));
|
||||
Reference in New Issue
Block a user