import { create } from 'zustand'; import { persist } from 'zustand/middleware'; const API_BASE = 'http://localhost:8000'; interface UserInfo { id: number; username: string; email: string; created_at: string; } interface AuthState { token: string | null; user: UserInfo | null; isAuthenticated: boolean; isLoading: boolean; error: string | null; // Actions login: (username: string, password: string) => Promise; register: (username: string, email: string, password: string) => Promise; logout: () => void; checkAuth: () => Promise; clearError: () => void; getAuthHeader: () => { Authorization: string } | {}; } export const useAuthStore = create()( persist( (set, get) => ({ token: null, user: null, isAuthenticated: false, isLoading: false, error: null, login: async (username: string, password: string) => { set({ isLoading: true, error: null }); try { // Use JSON login endpoint const res = await fetch(`${API_BASE}/api/auth/login/json`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }), }); if (!res.ok) { const errorData = await res.json().catch(() => ({})); throw new Error(errorData.detail || 'Login failed'); } const data = await res.json(); set({ token: data.access_token, isAuthenticated: true, isLoading: false }); // Fetch user info await get().checkAuth(); } catch (err) { set({ isLoading: false, error: (err as Error).message, isAuthenticated: false, token: null, user: null }); throw err; } }, register: async (username: string, email: string, password: string) => { set({ isLoading: true, error: null }); try { const res = await fetch(`${API_BASE}/api/auth/register`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, email, password }), }); if (!res.ok) { const errorData = await res.json().catch(() => ({})); throw new Error(errorData.detail || 'Registration failed'); } set({ isLoading: false }); } catch (err) { set({ isLoading: false, error: (err as Error).message }); throw err; } }, logout: () => { set({ token: null, user: null, isAuthenticated: false, error: null }); }, checkAuth: async () => { const token = get().token; if (!token) { set({ isAuthenticated: false, user: null }); return false; } try { const res = await fetch(`${API_BASE}/api/auth/me`, { headers: { Authorization: `Bearer ${token}` }, }); if (res.ok) { const user = await res.json(); set({ user, isAuthenticated: true }); return true; } else { // Token is invalid set({ token: null, user: null, isAuthenticated: false }); return false; } } catch { set({ token: null, user: null, isAuthenticated: false }); return false; } }, clearError: () => { set({ error: null }); }, getAuthHeader: () => { const token = get().token; if (token) { return { Authorization: `Bearer ${token}` }; } return {}; }, }), { name: 'contextflow-auth', partialize: (state) => ({ token: state.token, user: state.user, isAuthenticated: state.isAuthenticated }), } ) ); export default useAuthStore;