"use client"; import { create } from "zustand"; import { LoginForm, RegisterForm, 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 APIError extends Error { response?: any; } interface AuthState { token: string | null; isLoading: boolean; hydrated: boolean; user: UserData | null; error: string | null; login: (form: LoginForm) => Promise; register: (form: RegisterForm) => Promise; setToken: (token: string | null) => void; logout: () => void; initializeAuth: () => Promise; } export const useAuthStore = create((set, get) => ({ token: null, isLoading: true, hydrated: false, error: null, user: null, setToken: (newToken) => { set({ token: newToken }); setCookie("authToken", newToken); }, login: async (form: LoginForm) => { set({ isLoading: true, error: null }); try { const response = await fetch(`${API_URL}/auth/login/`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(form), }); const data = await response.json(); if (!response.ok) { throw new Error(data.message || "Login failed"); } const token = data.token; setCookie("authToken", token); set({ token }); // Automatically fetch user info after login const userRes = await fetch(`${API_URL}/me/profile/`, { headers: { Authorization: `Bearer ${token}` }, }); if (!userRes.ok) { throw new Error("Failed to fetch user info after login"); } const userData: UserData = await userRes.json(); set({ user: userData, isLoading: false }); } catch (err: any) { console.error("Login error:", err); set({ error: err?.message || "Login failed", isLoading: false, }); throw err; } }, register: async (form: RegisterForm) => { set({ isLoading: true, error: null }); try { const response = await fetch(`${API_URL}/auth/register/`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(form), }); const data = await response.json(); if (!response.ok) { const error: APIError = new Error( data?.detail || "Registration failed" ); error.response = data; throw error; } setCookie("authToken", data.token); set({ token: data.token, isLoading: false }); } catch (err: any) { set({ error: err?.message || "Registration failed", isLoading: false, }); throw err; } }, logout: () => { set({ token: null, user: null }); setCookie("authToken", null); }, initializeAuth: async () => { const storedToken = getCookie("authToken"); if (storedToken) { set({ token: storedToken }); } set({ isLoading: false, hydrated: true }); }, }));