|
|
@@ -1,85 +1,71 @@
|
|
|
+import { authService } from '@/services/auth.service'
|
|
|
+import { type AdminUser } from '@/types/auth.types'
|
|
|
import { create } from 'zustand'
|
|
|
import { persist } from 'zustand/middleware'
|
|
|
-import type { AdminUser, LoginResponse } from '@/types/auth'
|
|
|
-import { http } from '@/core/api/http'
|
|
|
-
|
|
|
-interface LoginPayload {
|
|
|
- username: string
|
|
|
- password: string
|
|
|
-}
|
|
|
|
|
|
interface AuthState {
|
|
|
user: AdminUser | null
|
|
|
token: string | null
|
|
|
isAuthenticated: boolean
|
|
|
- loading: boolean
|
|
|
- error: string | null
|
|
|
- login: (data: LoginPayload) => Promise<void>
|
|
|
- logout: () => void
|
|
|
- fetchProfile: () => Promise<void>
|
|
|
+ isHydrated: boolean
|
|
|
+ profileFetched: boolean
|
|
|
+ setToken: (token: string | null) => void
|
|
|
+ setUser: (user: AdminUser | null) => void
|
|
|
+ setHydrated: (state: boolean) => void
|
|
|
+ setProfileFetched: (state: boolean) => void
|
|
|
+ clearAuth: () => void
|
|
|
+ logout: () => Promise<void>
|
|
|
}
|
|
|
|
|
|
export const useAuthStore = create<AuthState>()(
|
|
|
persist(
|
|
|
(set) => ({
|
|
|
- user: null,
|
|
|
token: null,
|
|
|
- isAuthenticated: false,
|
|
|
- loading: false,
|
|
|
- error: null,
|
|
|
-
|
|
|
- login: async (data: LoginPayload) => {
|
|
|
- set({ loading: true, error: null })
|
|
|
+ user: null,
|
|
|
|
|
|
- try {
|
|
|
- const response = await http.post<LoginResponse>(
|
|
|
- '/admin/auth/login',
|
|
|
- data
|
|
|
- )
|
|
|
+ isAuthenticated: false,
|
|
|
+ isHydrated: false,
|
|
|
+ profileFetched: false,
|
|
|
|
|
|
- const { token, admin } = response.data
|
|
|
+ setToken: (token) =>
|
|
|
+ set({
|
|
|
+ token,
|
|
|
+ isAuthenticated: !!token,
|
|
|
+ }),
|
|
|
|
|
|
- set({
|
|
|
- token,
|
|
|
- user: admin,
|
|
|
- isAuthenticated: true,
|
|
|
- loading: false,
|
|
|
- error: null,
|
|
|
- })
|
|
|
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
- } catch (error: any) {
|
|
|
- const message = error?.response?.data?.message || 'Login failed'
|
|
|
+ setUser: (user) =>
|
|
|
+ set({
|
|
|
+ user,
|
|
|
+ }),
|
|
|
|
|
|
- set({
|
|
|
- loading: false,
|
|
|
- error: message,
|
|
|
- })
|
|
|
+ setHydrated: (state) =>
|
|
|
+ set({
|
|
|
+ isHydrated: state,
|
|
|
+ }),
|
|
|
|
|
|
- // eslint-disable-next-line preserve-caught-error
|
|
|
- throw new Error(message)
|
|
|
- }
|
|
|
- },
|
|
|
+ setProfileFetched: (state) =>
|
|
|
+ set({
|
|
|
+ profileFetched: state,
|
|
|
+ }),
|
|
|
|
|
|
- logout: () => {
|
|
|
+ clearAuth: () =>
|
|
|
set({
|
|
|
user: null,
|
|
|
token: null,
|
|
|
isAuthenticated: false,
|
|
|
- error: null,
|
|
|
- })
|
|
|
- },
|
|
|
+ profileFetched: false,
|
|
|
+ }),
|
|
|
|
|
|
- fetchProfile: async () => {
|
|
|
+ logout: async () => {
|
|
|
try {
|
|
|
- const res = await http.get<{ data: AdminUser }>('/admin/auth/profile')
|
|
|
-
|
|
|
+ await authService.logout()
|
|
|
+ } finally {
|
|
|
set({
|
|
|
- user: res.data,
|
|
|
- isAuthenticated: true,
|
|
|
+ user: null,
|
|
|
+ token: null,
|
|
|
+ isAuthenticated: false,
|
|
|
+ profileFetched: false,
|
|
|
})
|
|
|
- } catch (error) {
|
|
|
- // eslint-disable-next-line no-console
|
|
|
- console.log('Profile fetch failed', error)
|
|
|
}
|
|
|
},
|
|
|
}),
|
|
|
@@ -91,6 +77,10 @@ export const useAuthStore = create<AuthState>()(
|
|
|
token: state.token,
|
|
|
isAuthenticated: state.isAuthenticated,
|
|
|
}),
|
|
|
+
|
|
|
+ onRehydrateStorage: () => (state) => {
|
|
|
+ state?.setHydrated(true)
|
|
|
+ },
|
|
|
}
|
|
|
)
|
|
|
)
|