import { createEffect, createEvent, createStore, sample } from 'effector' import { apiClient } from '@/shared/api/client' export type AuthUser = { id: string; email: string; name?: string | null; phone?: string | null } const TOKEN_KEY = 'craftshop_auth_token' export const tokenSet = createEvent() export const logout = createEvent() export const $token = createStore(null) .on(tokenSet, (_, t) => t) .reset(logout) export const $user = createStore(null).reset(logout) export const changePasswordFx = createEffect(async (params: { currentPassword?: string; newPassword: string }) => { const { data } = await apiClient.patch<{ user: AuthUser }>('me/password', params) return data.user }) 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 $changePasswordError = createStore(null) .on(changePasswordFx.failData, (_, e) => e) .reset(changePasswordFx, logout) export const $requestEmailChangeCodeError = createStore(null) .on(requestEmailChangeCodeFx.failData, (_, e) => e) .reset(requestEmailChangeCodeFx, logout) export const $verifyEmailChangeError = createStore(null) .on(verifyEmailChangeFx.failData, (_, e) => e) .reset(verifyEmailChangeFx, logout) export const $updateProfileError = createStore(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}` }, }) return data.user }) sample({ clock: tokenSet, filter: (t): t is string => Boolean(t), target: meFx, }) sample({ clock: meFx.doneData, target: $user, }) sample({ clock: [changePasswordFx.doneData, 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 } }