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.

78 lines
2.4 KiB
TypeScript

import { createAsyncThunk, createSlice, type PayloadAction, createSelector } from '@reduxjs/toolkit'
import type { RootState, ThunkApi } from '../store'
import type { Product } from '../types'
import type { ResponseData } from '../network'
interface AddBasketAction {
id: number
count: number
}
interface ShopState {
products: Product[]
loading: boolean
error?: string
}
const initialState: ShopState = {
products: [],
loading: false,
error: undefined,
}
export const shopSlice = createSlice({
name: 'shop',
initialState,
reducers: {
// TODO: дописать action.payload.id
addToBasket: (state, action: PayloadAction<AddBasketAction>) => {
state.products[0].count -= action.payload.count
state.products[0].reserved += action.payload.count
},
},
extraReducers: builder => {
builder
.addCase(fetchProducts.pending, state => {
state.loading = true
state.error = undefined
})
.addCase(fetchProducts.fulfilled, (state, action) => {
state.products = action.payload.success as Product[]
state.loading = false
})
.addCase(fetchProducts.rejected, (state, action) => {
state.loading = false
if (action.payload) {
state.error = (action.payload as ResponseData).error
} else {
state.error = action.error.message
}
})
},
})
export const { addToBasket } = shopSlice.actions
export const selectShopLoading = (state: RootState) => state.shop.loading
export const selectShopError = (state: RootState) => state.shop.error
export const selectProducts = (state: RootState) => state.shop.products
export const selectProduct = (productId: number) =>
createSelector([selectProducts], products => {
return products.find(product => product.id === productId)
})
export const shopReducer = shopSlice.reducer
export const fetchProducts = createAsyncThunk<ResponseData, void, ThunkApi>(
'products/fetchProducts',
async (_, { fulfillWithValue, rejectWithValue, extra: networkApi }) => {
try {
const data = await networkApi.request<ResponseData>('/shop/')
return fulfillWithValue(data)
} catch (error) {
return rejectWithValue(error)
}
}
)