Files
game-marathon/frontend/src/store/auth.ts

104 lines
2.8 KiB
TypeScript
Raw Normal View History

2025-12-14 02:38:35 +07:00
import { create } from 'zustand'
import { persist } from 'zustand/middleware'
import type { User } from '@/types'
import { authApi, type RegisterData, type LoginData } from '@/api/auth'
interface AuthState {
user: User | null
token: string | null
isAuthenticated: boolean
isLoading: boolean
error: string | null
2025-12-14 20:39:26 +07:00
pendingInviteCode: string | null
2025-12-14 02:38:35 +07:00
login: (data: LoginData) => Promise<void>
register: (data: RegisterData) => Promise<void>
logout: () => void
clearError: () => void
2025-12-14 20:39:26 +07:00
setPendingInviteCode: (code: string | null) => void
consumePendingInviteCode: () => string | null
2025-12-14 02:38:35 +07:00
}
export const useAuthStore = create<AuthState>()(
persist(
2025-12-14 20:39:26 +07:00
(set, get) => ({
2025-12-14 02:38:35 +07:00
user: null,
token: null,
isAuthenticated: false,
isLoading: false,
error: null,
2025-12-14 20:39:26 +07:00
pendingInviteCode: null,
2025-12-14 02:38:35 +07:00
login: async (data) => {
set({ isLoading: true, error: null })
try {
const response = await authApi.login(data)
localStorage.setItem('token', response.access_token)
set({
user: response.user,
token: response.access_token,
isAuthenticated: true,
isLoading: false,
})
} catch (err: unknown) {
const error = err as { response?: { data?: { detail?: string } } }
set({
error: error.response?.data?.detail || 'Login failed',
isLoading: false,
})
throw err
}
},
register: async (data) => {
set({ isLoading: true, error: null })
try {
const response = await authApi.register(data)
localStorage.setItem('token', response.access_token)
set({
user: response.user,
token: response.access_token,
isAuthenticated: true,
isLoading: false,
})
} catch (err: unknown) {
const error = err as { response?: { data?: { detail?: string } } }
set({
error: error.response?.data?.detail || 'Registration failed',
isLoading: false,
})
throw err
}
},
logout: () => {
localStorage.removeItem('token')
set({
user: null,
token: null,
isAuthenticated: false,
})
},
clearError: () => set({ error: null }),
2025-12-14 20:39:26 +07:00
setPendingInviteCode: (code) => set({ pendingInviteCode: code }),
consumePendingInviteCode: () => {
const code = get().pendingInviteCode
set({ pendingInviteCode: null })
return code
},
2025-12-14 02:38:35 +07:00
}),
{
name: 'auth-storage',
partialize: (state) => ({
user: state.user,
token: state.token,
isAuthenticated: state.isAuthenticated,
2025-12-14 20:39:26 +07:00
pendingInviteCode: state.pendingInviteCode,
2025-12-14 02:38:35 +07:00
}),
}
)
)