Merge branch 'refactor'
This commit is contained in:
@@ -1,47 +1,32 @@
|
||||
import { createEffect, createEvent, createStore, sample } from 'effector'
|
||||
import { apiClient } from '@/shared/api/client'
|
||||
import { createErrorStore } from '@/shared/lib/create-error-store'
|
||||
import { persistToken } from '@/shared/lib/persist-token'
|
||||
|
||||
export type AuthUser = { id: string; email: string; name?: string | null; phone?: string | null; isAdmin?: boolean }
|
||||
|
||||
const TOKEN_KEY = 'craftshop_auth_token'
|
||||
|
||||
export const tokenSet = createEvent<string | null>()
|
||||
export const logout = createEvent()
|
||||
|
||||
// ----- Token persistence -----
|
||||
|
||||
const persistTokenFx = createEffect<string | null, void>({
|
||||
handler: (token) => persistToken(token),
|
||||
})
|
||||
|
||||
export const $token = createStore<string | null>(null)
|
||||
.on(tokenSet, (_, t) => t)
|
||||
.reset(logout)
|
||||
|
||||
sample({
|
||||
clock: $token,
|
||||
target: persistTokenFx,
|
||||
})
|
||||
|
||||
// ----- User -----
|
||||
|
||||
export const $user = createStore<AuthUser | null>(null).reset(logout)
|
||||
|
||||
export const requestEmailChangeCodeFx = createEffect(async (newEmail: string) => {
|
||||
await apiClient.post('me/change-email/request-code', { newEmail })
|
||||
})
|
||||
|
||||
export const verifyEmailChangeFx = createEffect(async (params: { newEmail: string; code: string }) => {
|
||||
const { data } = await apiClient.post<{ user: AuthUser }>('me/change-email/verify', params)
|
||||
return data.user
|
||||
})
|
||||
|
||||
export type UpdateProfileParams = { name: string | null; phone?: string | null }
|
||||
|
||||
export const updateProfileFx = createEffect(async (params: UpdateProfileParams) => {
|
||||
const { data } = await apiClient.patch<{ user: AuthUser }>('me/profile', params)
|
||||
return data.user
|
||||
})
|
||||
|
||||
export const $requestEmailChangeCodeError = createStore<unknown | null>(null)
|
||||
.on(requestEmailChangeCodeFx.failData, (_, e) => e)
|
||||
.reset(requestEmailChangeCodeFx, logout)
|
||||
|
||||
export const $verifyEmailChangeError = createStore<unknown | null>(null)
|
||||
.on(verifyEmailChangeFx.failData, (_, e) => e)
|
||||
.reset(verifyEmailChangeFx, logout)
|
||||
|
||||
export const $updateProfileError = createStore<unknown | null>(null)
|
||||
.on(updateProfileFx.failData, (_, e) => e)
|
||||
.reset(updateProfileFx, logout)
|
||||
|
||||
export const meFx = createEffect(async (token: string) => {
|
||||
const { data } = await apiClient.get<{ user: AuthUser | null }>('me', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
@@ -60,37 +45,39 @@ sample({
|
||||
target: $user,
|
||||
})
|
||||
|
||||
// ----- Email change -----
|
||||
|
||||
export const requestEmailChangeCodeFx = createEffect(async (newEmail: string) => {
|
||||
await apiClient.post('me/change-email/request-code', { newEmail })
|
||||
})
|
||||
|
||||
export const verifyEmailChangeFx = createEffect(async (params: { newEmail: string; code: string }) => {
|
||||
const { data } = await apiClient.post<{ user: AuthUser }>('me/change-email/verify', params)
|
||||
return data.user
|
||||
})
|
||||
|
||||
// ----- Profile update -----
|
||||
|
||||
export type UpdateProfileParams = { name: string | null; phone?: string | null }
|
||||
|
||||
export const updateProfileFx = createEffect(async (params: UpdateProfileParams) => {
|
||||
const { data } = await apiClient.patch<{ user: AuthUser }>('me/profile', params)
|
||||
return data.user
|
||||
})
|
||||
|
||||
// ----- Error stores -----
|
||||
|
||||
export const $requestEmailChangeCodeError = createErrorStore(requestEmailChangeCodeFx).$error
|
||||
export const $verifyEmailChangeError = createErrorStore(verifyEmailChangeFx).$error
|
||||
export const $updateProfileError = createErrorStore(updateProfileFx).$error
|
||||
|
||||
// ----- Re-exports -----
|
||||
|
||||
export { readStoredToken } from '@/shared/lib/persist-token'
|
||||
|
||||
// ----- Sync user from profile/email changes -----
|
||||
|
||||
sample({
|
||||
clock: [verifyEmailChangeFx.doneData, updateProfileFx.doneData],
|
||||
target: $user,
|
||||
})
|
||||
|
||||
let tokenPersistInitialized = false
|
||||
$token.watch((t) => {
|
||||
try {
|
||||
if (!tokenPersistInitialized) {
|
||||
tokenPersistInitialized = true
|
||||
return
|
||||
}
|
||||
if (!t) localStorage.removeItem(TOKEN_KEY)
|
||||
else localStorage.setItem(TOKEN_KEY, t)
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
})
|
||||
|
||||
logout.watch(() => {
|
||||
try {
|
||||
localStorage.removeItem(TOKEN_KEY)
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
})
|
||||
|
||||
export function readStoredToken(): string | null {
|
||||
try {
|
||||
return localStorage.getItem(TOKEN_KEY)
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user