You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
233 lines
6.9 KiB
TypeScript
233 lines
6.9 KiB
TypeScript
import { type PayloadAction, createSlice } from '@reduxjs/toolkit'
|
|
import { type UserType } from '../types'
|
|
import { createAppAsyncThunk } from './hooks'
|
|
import type { ResponseData } from '../network'
|
|
import {
|
|
isActionPending,
|
|
isActionRejected,
|
|
token,
|
|
type PendingAction,
|
|
type RejectedAction,
|
|
} from '../utils'
|
|
|
|
type UserState = {
|
|
user: UserType
|
|
loading: boolean
|
|
error?: string
|
|
}
|
|
|
|
const defaultUser = (): UserType => {
|
|
return {
|
|
id: -1,
|
|
nickname: '',
|
|
email: '',
|
|
token: token.load(),
|
|
token_expiry_date: '',
|
|
money: '',
|
|
histories_id: [],
|
|
}
|
|
}
|
|
|
|
const initialState = (): UserState => {
|
|
return {
|
|
user: defaultUser(),
|
|
loading: false,
|
|
error: undefined,
|
|
}
|
|
}
|
|
|
|
const userSlice = createSlice({
|
|
name: 'user',
|
|
initialState: initialState(),
|
|
reducers: {
|
|
setUser: (state, action: PayloadAction<UserType>) => {
|
|
state.user = action.payload
|
|
},
|
|
clearUser() {
|
|
token.save('')
|
|
return initialState()
|
|
},
|
|
clearError: state => {
|
|
state.error = ''
|
|
},
|
|
},
|
|
extraReducers: builder => {
|
|
builder
|
|
.addCase(fetchUser.fulfilled, (state, action) => {
|
|
state.user = action.payload.success?.[0] as UserType
|
|
state.loading = false
|
|
})
|
|
.addCase(fetchLogin.fulfilled, (state, action) => {
|
|
state.user = action.payload.success?.[0] as UserType
|
|
state.loading = false
|
|
state.error = undefined
|
|
token.save(state.user.token)
|
|
})
|
|
.addCase(fetchLogout.fulfilled, state => {
|
|
if (state.user?.token) {
|
|
state.user.token = ''
|
|
}
|
|
state.loading = false
|
|
state.error = undefined
|
|
token.save('')
|
|
})
|
|
.addCase(fetchRegister.fulfilled, (state, action) => {
|
|
state.user = action.payload.success?.[0] as UserType
|
|
state.loading = false
|
|
state.error = undefined
|
|
token.save(state.user.token)
|
|
})
|
|
.addCase(fetchUnregister.fulfilled, (state, action) => {
|
|
state.user = action.payload.success?.[0] as UserType
|
|
state.loading = false
|
|
state.error = undefined
|
|
token.save(state.user.token)
|
|
})
|
|
.addCase(fetchAddMoney.fulfilled, (state, action) => {
|
|
state.user = action.payload.success?.[0] as UserType
|
|
state.loading = false
|
|
state.error = undefined
|
|
token.save(state.user.token)
|
|
})
|
|
.addMatcher<PendingAction>(isActionPending('user'), state => {
|
|
state.loading = true
|
|
state.error = undefined
|
|
})
|
|
.addMatcher<RejectedAction>(isActionRejected('user'), (state, action) => {
|
|
state.loading = false
|
|
if (action.payload) {
|
|
state.error = (action.payload as ResponseData).error
|
|
} else {
|
|
state.error = action.error.message
|
|
}
|
|
})
|
|
},
|
|
selectors: {
|
|
accessToken: (state: UserState) => state.user?.token,
|
|
user: (state: UserState) => state.user,
|
|
loading: (state: UserState) => state.loading,
|
|
error: (state: UserState) => state.error,
|
|
},
|
|
})
|
|
|
|
const fetchUser = createAppAsyncThunk<ResponseData>(
|
|
`${userSlice.name}/fetchUser`,
|
|
async (_, { fulfillWithValue, rejectWithValue, extra: networkApi }) => {
|
|
try {
|
|
const data = await networkApi.request<ResponseData>('/user/', {
|
|
method: 'POST',
|
|
})
|
|
return fulfillWithValue(data)
|
|
} catch (error) {
|
|
return rejectWithValue(error)
|
|
}
|
|
}
|
|
)
|
|
|
|
type RegisterProps = {
|
|
email: string
|
|
nickname: string
|
|
password: string
|
|
}
|
|
|
|
const fetchRegister = createAppAsyncThunk<ResponseData, RegisterProps>(
|
|
`${userSlice.name}/fetchRegister`,
|
|
async (props, { fulfillWithValue, rejectWithValue, extra: networkApi }) => {
|
|
try {
|
|
const data = await networkApi.request<ResponseData>('/user/', {
|
|
method: 'POST',
|
|
body: JSON.stringify({ register: props }),
|
|
})
|
|
return fulfillWithValue(data)
|
|
} catch (error) {
|
|
return rejectWithValue(error)
|
|
}
|
|
}
|
|
)
|
|
|
|
const fetchUnregister = createAppAsyncThunk<ResponseData>(
|
|
`${userSlice.name}/fetchUnregister`,
|
|
async (_, { fulfillWithValue, rejectWithValue, extra: networkApi }) => {
|
|
try {
|
|
const data = await networkApi.request<ResponseData>('/user/', {
|
|
method: 'POST',
|
|
body: JSON.stringify({ unregister: {} }),
|
|
})
|
|
return fulfillWithValue(data)
|
|
} catch (error) {
|
|
return rejectWithValue(error)
|
|
}
|
|
}
|
|
)
|
|
|
|
type LoginProps = {
|
|
email: string
|
|
password: string
|
|
}
|
|
|
|
const fetchLogin = createAppAsyncThunk<ResponseData, LoginProps>(
|
|
`${userSlice.name}/fetchLogin`,
|
|
async (props, { fulfillWithValue, rejectWithValue, extra: networkApi }) => {
|
|
try {
|
|
const data = await networkApi.request<ResponseData>('/user/', {
|
|
method: 'POST',
|
|
body: JSON.stringify({ login: props }),
|
|
})
|
|
return fulfillWithValue(data)
|
|
} catch (error) {
|
|
return rejectWithValue(error)
|
|
}
|
|
}
|
|
)
|
|
|
|
const fetchLogout = createAppAsyncThunk<ResponseData>(
|
|
`${userSlice.name}/fetchLogout`,
|
|
async (_, { fulfillWithValue, rejectWithValue, extra: networkApi }) => {
|
|
try {
|
|
const data = await networkApi.request<ResponseData>('/user/', {
|
|
method: 'POST',
|
|
body: JSON.stringify({ logout: {} }),
|
|
})
|
|
return fulfillWithValue(data)
|
|
} catch (error) {
|
|
return rejectWithValue(error)
|
|
}
|
|
}
|
|
)
|
|
|
|
type AddMoneyProps = {
|
|
money: string
|
|
}
|
|
|
|
const fetchAddMoney = createAppAsyncThunk<ResponseData, AddMoneyProps>(
|
|
`${userSlice.name}/fetchAddMoney`,
|
|
async (props, { fulfillWithValue, rejectWithValue, extra: networkApi }) => {
|
|
try {
|
|
const data = await networkApi.request<ResponseData>('/user/', {
|
|
method: 'POST',
|
|
body: JSON.stringify({ add_money: props }),
|
|
})
|
|
return fulfillWithValue(data)
|
|
} catch (error) {
|
|
return rejectWithValue(error)
|
|
}
|
|
}
|
|
)
|
|
|
|
class User {
|
|
selector = { ...userSlice.selectors }
|
|
action = userSlice.actions
|
|
reducer = userSlice.reducer
|
|
name = userSlice.name
|
|
fetch = {
|
|
user: fetchUser,
|
|
login: fetchLogin,
|
|
logout: fetchLogout,
|
|
register: fetchRegister,
|
|
unregister: fetchUnregister,
|
|
addMoney: fetchAddMoney,
|
|
}
|
|
}
|
|
|
|
export const user = new User()
|