Spaces:
Running
Running
| /** | |
| * 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<void>; | |
| register: (email: string, password: string, name: string) => Promise<void>; | |
| logout: () => void; | |
| restoreSession: () => Promise<void>; | |
| clearError: () => void; | |
| } | |
| export const useAuthStore = create<AuthState>()( | |
| 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 }), | |
| } | |
| ) | |
| ); | |