Skip to content

Commit

Permalink
Merge branch 'master' into enhancement_310_fix_routing_to_form_return…
Browse files Browse the repository at this point in the history
…_page
  • Loading branch information
AlexanderMorugin authored Apr 22, 2024
2 parents 2758ada + 61ab6b8 commit c890877
Show file tree
Hide file tree
Showing 36 changed files with 328 additions and 148 deletions.
2 changes: 2 additions & 0 deletions src/app/providers/StoreProvider/config/StateSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { ICategoryFiltersSchema } from '@/components/Dropdown/types/types'
import type { IFeedbackFormSchema } from '@/widgets/FeedbackForm/model/scheme/feedbackFormSliceSchema'
import { IAboutUsSchema } from '@/pages/AboutUsPage/model/types/types'
import { ICartSchema } from '@/pages/CartPage/model/types'
import { IProductAmountStateSchema } from '@/features/CartEdit/model/types'

export interface StateSchema {
aboutUs: IAboutUsSchema
Expand All @@ -42,6 +43,7 @@ export interface StateSchema {
getCategories: IMainCategorySchema
cart: ICartSchema
categoryFilters: ICategoryFiltersSchema
productAmount: IProductAmountStateSchema
}

export interface ThunkExtraArg {
Expand Down
4 changes: 3 additions & 1 deletion src/app/providers/StoreProvider/config/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { categoryFiltersSliceReducer } from '@/components/Dropdown/slice/filters
import { feedbackFormReducer } from '@/widgets/FeedbackForm/model/slice/feedbackFormSlice'
import { aboutUsReducer } from '@/pages/AboutUsPage/model/slice/aboutUsSlice'
import { cartReducer } from '@/pages/CartPage/model/slice'
import { productAmountReducer } from '@/features/CartEdit/model/slice/productAmountSlice'

export type RootState = StateSchema

Expand All @@ -48,7 +49,8 @@ const rootReducer: ReducersMapObject<RootState> = {
categoryBranches: categoryBranchesReducer,
getCategories: getCategoriesReducer,
cart: cartReducer,
categoryFilters: categoryFiltersSliceReducer
categoryFilters: categoryFiltersSliceReducer,
productAmount: productAmountReducer
}

export function createReduxStore(initialState: RootState) {
Expand Down
3 changes: 2 additions & 1 deletion src/app/router/AppRouter/ui/AppRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import CartPage from '@/pages/CartPage/CartPage'
import { CategoryPage } from '@/pages/CategoryPage/CategoryPage'
import ComparePage from '@/pages/ComparePage/ComparePage'
import ContactsPage from '@/pages/ContactsPage/ContactsPage'
import DeliveryPage from '@/pages/DeliveryPage/DeliveryPage'
import ErrorPage from '@/pages/ErrorPage/ErrorPage'
import FavoritesPage from '@/pages/FavoritesPage/FavoritesPage'
import { FeedbackPage } from '@/pages/FeedbackPage/FeedbackPage'
Expand Down Expand Up @@ -60,7 +61,7 @@ export const AppRouter = createBrowserRouter([
},
{
path: Routes.DELIVERY,
element: <ProductsPage /> // временная заглушка нужна страница с информацией о доставке
element: <DeliveryPage />
},
{
path: Routes.FAVORITES,
Expand Down
2 changes: 0 additions & 2 deletions src/entities/AboutUs/ui/AboutUs.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,4 @@
font-size: 16px;
font-weight: 400;
color: var.$body-color;
margin: 0;
padding: 30px 0 56px;
}
8 changes: 5 additions & 3 deletions src/entities/ProductEntity/ui/ProductEntity/ProductEntity.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type FC } from 'react'

import { IProductData } from '@/pages/CartPage/model/types'
import { IProduct } from '@/models/ProductModel'
import Subheading from '@/shared/ui/Subheading/Subheading'

import styles from './ProductEntity.module.scss'
Expand All @@ -14,11 +14,13 @@ import styles from './ProductEntity.module.scss'
* @param {string} currency - валюта, в которой обозначена стоимость;
*/

export const ProductEntity: FC<IProductData> = product => {
export const ProductEntity: FC<IProduct> = product => {
return (
<div className={`${styles.description}`}>
<div className={`${styles.frame}`}>
<img src={product.images[0].image} alt={'product'} className={styles.image} />
{product.images.length > 0 && (
<img src={product.images[0].image} alt={'product'} className={styles.image} />
)}
</div>
<div className={`${styles.description_wrapper}`}>
<Subheading>{product.id}</Subheading>
Expand Down
9 changes: 9 additions & 0 deletions src/features/CartEdit/model/selectors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { StateSchema } from '@/app/providers/StoreProvider'

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

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

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

export const putIncreaseProductAmount = createAsyncThunk<IProductCartList, number, ThunkConfig<ApiError>>(
'cart-increase-product-amount',
async (productId, thunkAPI) => {
const { rejectWithValue, extra } = thunkAPI
try {
const { data } = await extra.api.put(
`api/${ApiRoutes.INCREASE_PRODUCT_AMOUNT}`,
{ product: productId },
{
withCredentials: true
}
)
return data
} catch (error) {
return rejectWithValue(apiErrorIdentify(error, ApiErrorTypes.DATA_EMPTY_ERROR))
}
}
)
52 changes: 52 additions & 0 deletions src/features/CartEdit/model/slice/productAmountSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { createSlice } from '@reduxjs/toolkit'

import { rejectedPayloadHandle } from '@/shared/api/rejectedPayloadHandle'

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

const initialState: IProductAmountStateSchema = {
isIncreaseSuccessful: false,
productList: {
amount: 0,
product: {
id: 0,
category: 'string',
brand: 'string',
images: [],
price: '',
name: '',
slug: '',
description: '',
code: 2147483647,
wb_urls: ''
},
full_price: 0
}
}

export const productAmountSlice = createSlice({
name: 'cart/product/amount',
initialState,
reducers: {
setProductList: (state, { payload }) => {
state.productList = payload
}
},
extraReducers: builder => {
builder
.addCase(putIncreaseProductAmount.pending, state => {
state.isIncreaseSuccessful = false
})
.addCase(putIncreaseProductAmount.fulfilled, (state, { payload }) => {
state.isIncreaseSuccessful = true
state.productList = payload
})
.addCase(putIncreaseProductAmount.rejected, (state, { payload }) => {
state.isIncreaseSuccessful = false
state.error = rejectedPayloadHandle(payload)
})
}
})

export const { actions: productAmountActions, reducer: productAmountReducer } = productAmountSlice
7 changes: 7 additions & 0 deletions src/features/CartEdit/model/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { IProductCartList } from '@/models/ProductCartListModel'

export interface IProductAmountStateSchema {
isIncreaseSuccessful: boolean
productList: IProductCartList
error?: string | string[]
}
35 changes: 19 additions & 16 deletions src/features/CartEdit/ui/CartEdit/CartEdit.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,25 @@ type Story = StoryObj<typeof meta>
export const Default: Story = {
args: {
cartId: 85,
amount: 2,
product: {
id: 1,
category: 'техника',
brand: 'Tefal',
images: [
{
image: image1
}
],
price: '1000',
name: 'Tefal Iron',
slug: '1hfjnfjkf',
description: 'Functional',
code: 108290,
wb_urls: 'jnfne'
productList: {
amount: 1,
product: {
id: 1,
category: 'техника',
brand: 'Tefal',
images: [
{
image: image1
}
],
price: '1000',
name: 'Tefal Iron',
slug: '1hfjnfjkf',
description: 'Functional',
code: 108290,
wb_urls: 'jnfne'
},
full_price: 0
}
}
}
36 changes: 24 additions & 12 deletions src/features/CartEdit/ui/CartEdit/CartEdit.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,39 @@
import { useState } from 'react'
import { useEffect, useState } from 'react'
import { useSelector } from 'react-redux'

import ArrowIcon from '@/assets/images/cart/arrow-right.svg'
import { ProductEntity } from '@/entities/ProductEntity/ui/ProductEntity/ProductEntity'
import { IProductData } from '@/pages/CartPage/model/types'
import { IProductCartList } from '@/models/ProductCartListModel'
import { useAppDispatch } from '@/shared/libs/hooks/store'
import { Button } from '@/shared/ui/Button/Button'
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 { putIncreaseProductAmount } from '../../model/services/putIncreaseProductAmount'
import { productAmountActions } from '../../model/slice/productAmountSlice'

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

export type TCartEditProps = {
cartId: number
amount: number
product: IProductData
productList: IProductCartList
}

/**
* Компонент используется для отображения добавленных в корзину продуктов, изменения кол-ва продуктов в корзине,
* для удаления продуктов из корзины, для добавления продуктов в закладки
* @param {number} cartId - id корзины
* @param {number} amount - количество товаров в корзине
* @param {IProductData} product - это продукт для определения состояния
* @param {IProductCartList} productList - это продукт для определения состояния
*/

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

const productListState: IProductCartList = useSelector(getProductListSelector)

function deleteProductHandler() {
setNeedToOpen(false)
Expand All @@ -37,7 +44,7 @@ export const CartEdit: React.FC<TCartEditProps> = ({ cartId, amount, product }:
}

function increaseAmountHandler() {
// tbd https://github.com/Studio-Yandex-Practicum/maxboom_frontend/issues/317
dispatch(putIncreaseProductAmount(productListState.product.id))
}

function decreaseAmountHandler() {
Expand All @@ -48,20 +55,25 @@ export const CartEdit: React.FC<TCartEditProps> = ({ cartId, amount, product }:
//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 {...product} />
<ProductEntity {...productListState.product} />
<div className={`${styles.sum_wrapper}`}>
<Paragraph className={`${styles.sum}`}>
{' '}
{amount * Number(product.price)} {product.brand}
{productListState.amount * Number(productListState.product.price)}{' '}
{productListState.product.brand}
{/* currency, not brand, c Number непонятно пока*/}
</Paragraph>
<Subheading className={`${styles.price}`}>
{' '}
{product.price} {product.brand}/шт
{productListState.product.price} {productListState.product.brand}/шт
{/* currency, not brand */}
</Subheading>
</div>
Expand All @@ -74,7 +86,7 @@ export const CartEdit: React.FC<TCartEditProps> = ({ cartId, amount, product }:
<ArrowIcon className={styles.arrowIcon} />
</Button>
<input
value={amount}
value={productListState.amount}
min="1"
max="99"
type="text"
Expand Down
8 changes: 8 additions & 0 deletions src/models/CartModel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { IProductCartList } from './ProductCartListModel'

export interface ICart {
id: number
products: IProductCartList[]
user: number
cart_full_price: number
}
3 changes: 3 additions & 0 deletions src/models/ImageModel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface IImage {
image: string
}
7 changes: 7 additions & 0 deletions src/models/ProductCartListModel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { IProduct } from './ProductModel'

export interface IProductCartList {
amount: number
product: IProduct
full_price: number
}
19 changes: 19 additions & 0 deletions src/models/ProductModel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { IImage } from './ImageModel'

export interface IProduct {
id: number
category: string
brand: string
images: IImage[]
price: string
name: string
slug: string
description: string
code: number
wb_urls: string
quantity?: number
is_deleted?: boolean
wholesale?: number
label_hit?: boolean
label_popular?: boolean
}
22 changes: 9 additions & 13 deletions src/pages/AboutUsPage/AboutUsPage.module.scss
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
@use '@/shared/styles/utils/variables' as var;

.title {
.aboutUs {
display: flex;
flex-direction: column;
gap: 30px;
width: 100%;
margin: 0 0 10px;
padding: 0;
}

.link {
text-decoration: none;
color: var.$subtitle-color;
font-size: 13.5px;
font-weight: 400;
line-height: 16.2px;
padding: 0 0 56px;

&:hover {
color: var.$theme-primary-color;
&__titleBox {
display: flex;
flex-direction: column;
gap: 10px;
}
}
Loading

0 comments on commit c890877

Please sign in to comment.