base commit
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
import { createEffect, createEvent, createStore, sample } from 'effector'
|
||||
import { apiClient } from '@/shared/api/client'
|
||||
|
||||
export type AuthUser = { id: string; email: string; name?: string | null }
|
||||
|
||||
const TOKEN_KEY = 'craftshop_auth_token'
|
||||
|
||||
export const tokenSet = createEvent<string | null>()
|
||||
export const logout = createEvent()
|
||||
|
||||
export const $token = createStore<string | null>(null)
|
||||
.on(tokenSet, (_, t) => t)
|
||||
.reset(logout)
|
||||
|
||||
export const $user = createStore<AuthUser | null>(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 const updateProfileFx = createEffect(async (params: { name: string | null }) => {
|
||||
const { data } = await apiClient.patch<{ user: AuthUser }>('me/profile', params)
|
||||
return data.user
|
||||
})
|
||||
|
||||
export const $changePasswordError = createStore<unknown | null>(null)
|
||||
.on(changePasswordFx.failData, (_, e) => e)
|
||||
.reset(changePasswordFx, logout)
|
||||
|
||||
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}` },
|
||||
})
|
||||
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,
|
||||
})
|
||||
|
||||
$token.watch((t) => {
|
||||
try {
|
||||
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