Skip to content

Commit

Permalink
#319-remove-product-from-cart
Browse files Browse the repository at this point in the history
  • Loading branch information
JuliaAvramenko committed May 4, 2024
1 parent 6a46e34 commit 7b51d39
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 37 deletions.
8 changes: 6 additions & 2 deletions src/features/CartEdit/model/selectors.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { StateSchema } from '@/app/providers/StoreProvider'

export const putIncreaseProductAmountSelector = (state: StateSchema) => {
return state.productAmount.isIncreaseSuccessful
export const isSuccessfulRequest = (state: StateSchema) => {
return (
state.productAmount.isIncreaseSuccessful ||
state.productAmount.isDecreaseSuccessful ||
state.productAmount.isRemoveSuccessful
)
}

export const getProductListSelector = (state: StateSchema) => {
Expand Down
26 changes: 26 additions & 0 deletions src/features/CartEdit/model/services/putRemoveProduct.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { createAsyncThunk } from '@reduxjs/toolkit'

import { ThunkConfig } from '@/app/providers/StoreProvider/config/StateSchema'
import { apiErrorIdentify } from '@/shared/api/apiErrorIdentify'
import { ApiError, ApiErrorTypes, ApiRoutes } from '@/shared/api/types'

export const putRemoveProduct = createAsyncThunk<void, number, ThunkConfig<ApiError>>(
'cart-remove-product',
async (productId, thunkAPI) => {
const { rejectWithValue, extra } = thunkAPI
try {
const { data } = await extra.api.put(
`api/${ApiRoutes.REMOVE_PRODUCT}`,
{
product: productId
},
{
withCredentials: true
}
)
return data
} catch (error) {
return rejectWithValue(apiErrorIdentify(error, ApiErrorTypes.DATA_EMPTY_ERROR))
}
}
)
33 changes: 24 additions & 9 deletions src/features/CartEdit/model/slice/productAmountSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { rejectedPayloadHandle } from '@/shared/api/rejectedPayloadHandle'

import { putDecreaseProductAmount } from '../services/putDecreaseProductAmount'
import { putIncreaseProductAmount } from '../services/putIncreaseProductAmount'
import { putRemoveProduct } from '../services/putRemoveProduct'
import { IProductAmountStateSchema } from '../types'

const initialState: IProductAmountStateSchema = {
isIncreaseSuccessful: false,
productList: {
amount: 0,
product: {
Expand All @@ -25,7 +25,15 @@ const initialState: IProductAmountStateSchema = {
full_price: 0,
full_weight: 0
},
isDecreaseSuccessful: false
isIncreaseSuccessful: false,
isDecreaseSuccessful: false,
isRemoveSuccessful: false
}

function resetStatuses(state: IProductAmountStateSchema) {
state.isIncreaseSuccessful = false
state.isDecreaseSuccessful = false
state.isRemoveSuccessful = false
}

export const productAmountSlice = createSlice({
Expand All @@ -39,29 +47,36 @@ export const productAmountSlice = createSlice({
extraReducers: builder => {
builder
.addCase(putIncreaseProductAmount.pending, state => {
state.isIncreaseSuccessful = false
state.isDecreaseSuccessful = false
resetStatuses(state)
})
.addCase(putIncreaseProductAmount.fulfilled, (state, { payload }) => {
.addCase(putIncreaseProductAmount.fulfilled, state => {
state.isIncreaseSuccessful = true
state.productList = payload
})
.addCase(putIncreaseProductAmount.rejected, (state, { payload }) => {
state.isIncreaseSuccessful = false
state.error = rejectedPayloadHandle(payload)
})

.addCase(putDecreaseProductAmount.pending, state => {
state.isDecreaseSuccessful = false
resetStatuses(state)
})
.addCase(putDecreaseProductAmount.fulfilled, (state, { payload }) => {
.addCase(putDecreaseProductAmount.fulfilled, state => {
state.isDecreaseSuccessful = true
state.productList = payload
})
.addCase(putDecreaseProductAmount.rejected, (state, { payload }) => {
state.isDecreaseSuccessful = false
state.error = rejectedPayloadHandle(payload)
})

.addCase(putRemoveProduct.pending, state => {
resetStatuses(state)
})
.addCase(putRemoveProduct.fulfilled, state => {
state.isRemoveSuccessful = true
})
.addCase(putRemoveProduct.rejected, state => {
state.isRemoveSuccessful = false
})
}
})

Expand Down
1 change: 1 addition & 0 deletions src/features/CartEdit/model/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { IProductCartList } from '@/shared/model/types/ProductCartListModel'
export interface IProductAmountStateSchema {
isIncreaseSuccessful: boolean
isDecreaseSuccessful: boolean
isRemoveSuccessful: boolean
productList: IProductCartList
error?: string | string[]
}
5 changes: 3 additions & 2 deletions src/features/CartEdit/ui/CartEdit/CartEdit.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type Story = StoryObj<typeof meta>
export const Default: Story = {
args: {
cartId: 85,
productList: {
productWithInfo: {
amount: 1,
product: {
id: 1,
Expand All @@ -48,6 +48,7 @@ export const Default: Story = {
},
full_price: 0,
full_weight: 0
}
},
updateCart: () => {}
}
}
54 changes: 32 additions & 22 deletions src/features/CartEdit/ui/CartEdit/CartEdit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,72 +10,82 @@ import ButtonDots from '@/shared/ui/ButtonDots/ButtonDots'
import Paragraph from '@/shared/ui/Paragraph/Paragraph'
import Subheading from '@/shared/ui/Subheading/Subheading'

import { getProductListSelector } from '../../model/selectors'
import { isSuccessfulRequest } from '../../model/selectors'
import { putDecreaseProductAmount } from '../../model/services/putDecreaseProductAmount'
import { putIncreaseProductAmount } from '../../model/services/putIncreaseProductAmount'
import { productAmountActions } from '../../model/slice/productAmountSlice'
import { putRemoveProduct } from '../../model/services/putRemoveProduct'

import styles from './CartEdit.module.scss'

export type TCartEditProps = {
cartId: number
productList: IProductCartList
productWithInfo: IProductCartList
updateCart: () => void
}

/**
* Компонент используется для отображения добавленных в корзину продуктов, изменения кол-ва продуктов в корзине,
* для удаления продуктов из корзины, для добавления продуктов в закладки
* @param {number} cartId - id корзины
* @param {IProductCartList} productList - это продукт для определения состояния
* @param {IProductCartList} productList - это корзина с количеством товара, общей стоимостью и весом
* @param {function} updateCart - это функция для обновления корзины
*/

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const CartEdit: React.FC<TCartEditProps> = ({ cartId, productList }: TCartEditProps) => {
export const CartEdit: React.FC<TCartEditProps> = ({
// eslint-disable-next-line @typescript-eslint/no-unused-vars
cartId,
productWithInfo,
updateCart
}: TCartEditProps) => {
const MIN_AMOUNT = 1
const MAX_AMOUNT = 99
const [needToOpenContextMenuButtonDots, setNeedToOpen] = useState(false)
const dispatch = useAppDispatch()

const productListState: IProductCartList = useSelector(getProductListSelector)
const isSuccessful: boolean = useSelector(isSuccessfulRequest)

function deleteProductHandler() {
setNeedToOpen(false)
// removeProduct(product.id) переделать на вызов action https://github.com/Studio-Yandex-Practicum/maxboom_frontend/issues/319
dispatch(putRemoveProduct(productWithInfo.product.id))
}
useEffect(() => {
updateCart()
}, [isSuccessful])

function addToFavoritesHandler() {
setNeedToOpen(false)
}

function increaseAmountHandler() {
dispatch(putIncreaseProductAmount(productListState.product.id))
if (productWithInfo.amount < MAX_AMOUNT) {
dispatch(putIncreaseProductAmount(productWithInfo.product.id))
}
}

function decreaseAmountHandler() {
dispatch(putDecreaseProductAmount(productListState.product.id))
// tbd https://github.com/Studio-Yandex-Practicum/maxboom_frontend/issues/318
if (productWithInfo.amount > MIN_AMOUNT) {
dispatch(putDecreaseProductAmount(productWithInfo.product.id))
}
}

function setAmountHandler() {
//tbd https://github.com/Studio-Yandex-Practicum/maxboom_frontend/issues/316
}

useEffect(() => {
dispatch(productAmountActions.setProductList(productList))
}, [productList])

return (
<>
<div className={styles.container}>
<div className={styles.product}>
<ProductEntity {...productListState.product} />
<ProductEntity {...productWithInfo.product} />
<div className={`${styles.sum_wrapper}`}>
<Paragraph className={`${styles.sum}`}>
{' '}
{productListState.amount * Number(productListState.product.price)}{' '}
{productListState.product.brand}
{productWithInfo.amount * Number(productWithInfo.product.price)} {productWithInfo.product.brand}
{/* currency, not brand, c Number непонятно пока*/}
</Paragraph>
<Subheading className={`${styles.price}`}>
{' '}
{productListState.product.price} {productListState.product.brand}/шт
{productWithInfo.product.price} {productWithInfo.product.brand}/шт
{/* currency, not brand */}
</Subheading>
</div>
Expand All @@ -88,9 +98,9 @@ export const CartEdit: React.FC<TCartEditProps> = ({ cartId, productList }: TCar
<ArrowIcon className={styles.arrowIcon} />
</Button>
<input
value={productListState.amount}
min="1"
max="99"
value={productWithInfo.amount}
min={MIN_AMOUNT}
max={MAX_AMOUNT}
type="text"
className={`${styles.input}`}
onChange={setAmountHandler}></input>
Expand Down
13 changes: 12 additions & 1 deletion src/pages/CartPage/CartPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ const CartPage = () => {
dispatch(getCartList())
}, [])

function updateCart() {
dispatch(getCartList())
}

return (
<WrapperForMainContent>
<div className={styles.titles}>
Expand All @@ -48,7 +52,14 @@ const CartPage = () => {
<div className={styles.container}>
<div className={styles.cards}>
{cart.products.map(item => {
return <CartEdit key={item.product.id} cartId={cart.id} productList={item} />
return (
<CartEdit
key={item.product.id}
cartId={cart.id}
productWithInfo={item}
updateCart={updateCart}
/>
)
})}
</div>
<div className={styles.wrapper}>
Expand Down
3 changes: 2 additions & 1 deletion src/shared/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ export enum ApiRoutes {
PRODUCT = 'catalogue',
CART_LIST = 'cart',
INCREASE_PRODUCT_AMOUNT = 'cart/add/',
DECREASE_PRODUCT_AMOUNT = 'cart/subtract/'
DECREASE_PRODUCT_AMOUNT = 'cart/subtract/',
REMOVE_PRODUCT = 'cart/delete/'
}

export enum ApiErrorTypes {
Expand Down

0 comments on commit 7b51d39

Please sign in to comment.