/** * Auth store — manages JWT tokens, user session, login/logout. */ import { create } from "zustand"; import { persist } from "zustand/middleware"; import { authApi, tokenStore, LoginResponse } from "@/lib/api"; interface User { user_id: string; email: string; name: string; financial_personality?: string; } interface AuthState { user: User | null; isAuthenticated: boolean; isLoading: boolean; error: string | null; login: (email: string, password: string) => Promise; register: (email: string, password: string, name: string) => Promise; logout: () => void; restoreSession: () => Promise; clearError: () => void; } export const useAuthStore = create()( persist( (set) => ({ user: null, isAuthenticated: false, isLoading: false, error: null, login: async (email, password) => { set({ isLoading: true, error: null }); try { const res: LoginResponse = await authApi.login(email, password); tokenStore.setTokens(res.access_token, res.refresh_token); set({ user: { user_id: res.user_id, email: res.email, name: res.name }, isAuthenticated: true, isLoading: false, }); } catch (err) { set({ error: (err as Error).message, isLoading: false }); throw err; } }, register: async (email, password, name) => { set({ isLoading: true, error: null }); try { const res: LoginResponse = await authApi.register(email, password, name); tokenStore.setTokens(res.access_token, res.refresh_token); set({ user: { user_id: res.user_id, email: res.email, name: res.name }, isAuthenticated: true, isLoading: false, }); } catch (err) { set({ error: (err as Error).message, isLoading: false }); throw err; } }, logout: () => { tokenStore.clear(); set({ user: null, isAuthenticated: false, error: null }); }, restoreSession: async () => { const token = tokenStore.getAccess(); if (!token) return; try { const me = await authApi.me(); set({ user: me, isAuthenticated: true }); } catch { tokenStore.clear(); set({ user: null, isAuthenticated: false }); } }, clearError: () => set({ error: null }), }), { name: "bb_auth", partialize: (state) => ({ user: state.user, isAuthenticated: state.isAuthenticated }), } ) );