Merge branch 'refactor'

This commit is contained in:
@kirill.komarov
2026-05-13 22:07:46 +05:00
parent 3c9797af4a
commit a06f9cf2c4
85 changed files with 3762 additions and 2072 deletions
+47 -60
View File
@@ -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
}
}