From 99c165a69d12a4478cb18f3d24bbdd6c865f1370 Mon Sep 17 00:00:00 2001 From: Ilya Shcherbakov <86749581+LikeKugi@users.noreply.github.com> Date: Thu, 7 Sep 2023 21:10:17 +0300 Subject: [PATCH 1/3] fix: return in useEffect filter params and move types to types folder --- e-commerce-app/src/api/myCustomerApi.ts | 2 +- .../UserPersonalAddAddress/UserPersonalAddAddress.tsx | 4 ++-- e-commerce-app/src/pages/UserPage/UserPage.tsx | 2 +- e-commerce-app/src/pages/UserPage/UserPassword.tsx | 10 +++++----- .../requestsComponents/ProductsQuery/ProductsQuery.tsx | 1 + .../updateMyCustomerActionTypes.ts | 2 +- .../updateMyCustomerTypes/updateMyCustomerTypes.ts | 0 .../IMakeUpdateMyCustomerPersonalQueryActions.ts | 2 +- .../makeUpdateMyCustomerPersonalQueryActions.ts | 2 +- 9 files changed, 13 insertions(+), 12 deletions(-) rename e-commerce-app/src/{store/slices => types}/updateMyCustomerTypes/updateMyCustomerActionTypes.ts (96%) rename e-commerce-app/src/{store/slices => types}/updateMyCustomerTypes/updateMyCustomerTypes.ts (100%) diff --git a/e-commerce-app/src/api/myCustomerApi.ts b/e-commerce-app/src/api/myCustomerApi.ts index c416070..b54d1da 100644 --- a/e-commerce-app/src/api/myCustomerApi.ts +++ b/e-commerce-app/src/api/myCustomerApi.ts @@ -7,7 +7,7 @@ import { import { IChangePasswordMyCustomerRequest, IUpdateMyCustomerRequest, -} from '../store/slices/updateMyCustomerTypes/updateMyCustomerTypes'; +} from '../types/updateMyCustomerTypes/updateMyCustomerTypes'; export const myCustomerApi = createApi({ reducerPath: 'myCustomerApi', diff --git a/e-commerce-app/src/components/UserPersonalAddAddress/UserPersonalAddAddress.tsx b/e-commerce-app/src/components/UserPersonalAddAddress/UserPersonalAddAddress.tsx index ee65600..9947179 100644 --- a/e-commerce-app/src/components/UserPersonalAddAddress/UserPersonalAddAddress.tsx +++ b/e-commerce-app/src/components/UserPersonalAddAddress/UserPersonalAddAddress.tsx @@ -7,11 +7,11 @@ import countries from '../../data/countries.json'; import { useValidate } from '../../hooks/useValidate'; import { validatePostalCode } from '../../validators/validatePostalCode'; import { validateStrictCity } from '../../validators/validateCity'; -import { IUpdateMyCustomerActionAddAddress } from '../../store/slices/updateMyCustomerTypes/updateMyCustomerActionTypes'; +import { IUpdateMyCustomerActionAddAddress } from '../../types/updateMyCustomerTypes/updateMyCustomerActionTypes'; import { useAppSelector } from '../../store/hooks'; import { getAccessToken } from '../../store/slices/userSlice'; import { useUpdateMyCustomerMutation } from '../../api/myCustomerApi'; -import { IUpdateMyCustomer } from '../../store/slices/updateMyCustomerTypes/updateMyCustomerTypes'; +import { IUpdateMyCustomer } from '../../types/updateMyCustomerTypes/updateMyCustomerTypes'; import { getMyCustomerVersion } from '../../store/slices/myCustomerSlice'; interface IAddAddressForm { diff --git a/e-commerce-app/src/pages/UserPage/UserPage.tsx b/e-commerce-app/src/pages/UserPage/UserPage.tsx index 33dad6c..3d5e101 100644 --- a/e-commerce-app/src/pages/UserPage/UserPage.tsx +++ b/e-commerce-app/src/pages/UserPage/UserPage.tsx @@ -44,7 +44,7 @@ import { } from '../../store/slices/myCustomerSlice'; import { useUpdateMyCustomerMutation } from '../../api/myCustomerApi'; import { getAccessToken } from '../../store/slices/userSlice'; -import { IUpdateMyCustomer } from '../../store/slices/updateMyCustomerTypes/updateMyCustomerTypes'; +import { IUpdateMyCustomer } from '../../types/updateMyCustomerTypes/updateMyCustomerTypes'; import { IMakeUpdateMyCustomerPersonalQueryObject } from '../../types/utilsTypes/IMakeUpdateMyCustomerPersonalQueryActions'; import { makeUpdateMyCustomerPersonalQueryActions } from '../../utils/updateMyCustomerUtils/makeUpdateMyCustomerPersonalQueryActions'; import { capitalizeString } from '../../utils/capitalizeString'; diff --git a/e-commerce-app/src/pages/UserPage/UserPassword.tsx b/e-commerce-app/src/pages/UserPage/UserPassword.tsx index 43e7614..2c4940b 100644 --- a/e-commerce-app/src/pages/UserPage/UserPassword.tsx +++ b/e-commerce-app/src/pages/UserPage/UserPassword.tsx @@ -1,4 +1,4 @@ -import React, { ChangeEvent, useEffect, useState } from 'react'; +import React, { ChangeEvent, useState } from 'react'; import TextField from '@mui/material/TextField'; import Grid from '@mui/material/Grid'; import Button from '@mui/material/Button'; @@ -9,10 +9,10 @@ import { validateConfirmPassword } from '../../validators/validateConfirmPasswor import { IChangePasswordMyCustomer, IChangePasswordMyCustomerRequest, -} from '../../store/slices/updateMyCustomerTypes/updateMyCustomerTypes'; +} from '../../types/updateMyCustomerTypes/updateMyCustomerTypes'; import { useAppSelector } from '../../store/hooks'; -import { clearMyCustomerData, getMyCustomerVersion } from '../../store/slices/myCustomerSlice'; -import { getAccessToken, getUserEmail, setAuth, setLogOut } from '../../store/slices/userSlice'; +import { getMyCustomerVersion } from '../../store/slices/myCustomerSlice'; +import { getAccessToken, getUserEmail, setAuth } from '../../store/slices/userSlice'; import { useChangePasswordMyCustomerMutation } from '../../api/myCustomerApi'; import { useDispatch } from 'react-redux'; import { useLoginUserMutation } from '../../api/authApi'; @@ -85,7 +85,7 @@ export const UserPassword = () => { } }; - const submitNewPasswordHandler: SubmitHandler = (data) => { + const submitNewPasswordHandler: SubmitHandler = () => { if ( [ validateStrictPassword(currentPassword), diff --git a/e-commerce-app/src/requestsComponents/ProductsQuery/ProductsQuery.tsx b/e-commerce-app/src/requestsComponents/ProductsQuery/ProductsQuery.tsx index 35d0b4a..b1df4c2 100644 --- a/e-commerce-app/src/requestsComponents/ProductsQuery/ProductsQuery.tsx +++ b/e-commerce-app/src/requestsComponents/ProductsQuery/ProductsQuery.tsx @@ -84,6 +84,7 @@ const ProductsQuery = (): JSX.Element => { delete newState.filter; return newState; }); + return; } setParams((prevState) => ({ ...prevState, diff --git a/e-commerce-app/src/store/slices/updateMyCustomerTypes/updateMyCustomerActionTypes.ts b/e-commerce-app/src/types/updateMyCustomerTypes/updateMyCustomerActionTypes.ts similarity index 96% rename from e-commerce-app/src/store/slices/updateMyCustomerTypes/updateMyCustomerActionTypes.ts rename to e-commerce-app/src/types/updateMyCustomerTypes/updateMyCustomerActionTypes.ts index d53b856..77060a0 100644 --- a/e-commerce-app/src/store/slices/updateMyCustomerTypes/updateMyCustomerActionTypes.ts +++ b/e-commerce-app/src/types/updateMyCustomerTypes/updateMyCustomerActionTypes.ts @@ -1,6 +1,6 @@ // IUpdateMyCustomerAction -import { IMyCustomerApiAddressRequest } from '../../../types/addressesTypes'; +import { IMyCustomerApiAddressRequest } from '../addressesTypes'; export interface IUpdateMyCustomerActionChangeEmail { action: 'changeEmail'; diff --git a/e-commerce-app/src/store/slices/updateMyCustomerTypes/updateMyCustomerTypes.ts b/e-commerce-app/src/types/updateMyCustomerTypes/updateMyCustomerTypes.ts similarity index 100% rename from e-commerce-app/src/store/slices/updateMyCustomerTypes/updateMyCustomerTypes.ts rename to e-commerce-app/src/types/updateMyCustomerTypes/updateMyCustomerTypes.ts diff --git a/e-commerce-app/src/types/utilsTypes/IMakeUpdateMyCustomerPersonalQueryActions.ts b/e-commerce-app/src/types/utilsTypes/IMakeUpdateMyCustomerPersonalQueryActions.ts index d7b1504..72d55fe 100644 --- a/e-commerce-app/src/types/utilsTypes/IMakeUpdateMyCustomerPersonalQueryActions.ts +++ b/e-commerce-app/src/types/utilsTypes/IMakeUpdateMyCustomerPersonalQueryActions.ts @@ -1,4 +1,4 @@ -import { UpdateMyCustomerActionsType } from '../../store/slices/updateMyCustomerTypes/updateMyCustomerActionTypes'; +import { UpdateMyCustomerActionsType } from '../updateMyCustomerTypes/updateMyCustomerActionTypes'; export interface IMakeUpdateMyCustomerPersonalQueryObject { firstName: string; diff --git a/e-commerce-app/src/utils/updateMyCustomerUtils/makeUpdateMyCustomerPersonalQueryActions.ts b/e-commerce-app/src/utils/updateMyCustomerUtils/makeUpdateMyCustomerPersonalQueryActions.ts index 850647e..fc31e90 100644 --- a/e-commerce-app/src/utils/updateMyCustomerUtils/makeUpdateMyCustomerPersonalQueryActions.ts +++ b/e-commerce-app/src/utils/updateMyCustomerUtils/makeUpdateMyCustomerPersonalQueryActions.ts @@ -5,7 +5,7 @@ import { IUpdateMyCustomerActionSetFirstName, IUpdateMyCustomerActionSetLastName, UpdateMyCustomerActionsType, -} from '../../store/slices/updateMyCustomerTypes/updateMyCustomerActionTypes'; +} from '../../types/updateMyCustomerTypes/updateMyCustomerActionTypes'; export const makeUpdateMyCustomerPersonalQueryActions: MakeUpdateMyCustomerPersonalQueryActionsType = (initial, current) => { From 5546f31adca82413c912826fed9af19b903008c8 Mon Sep 17 00:00:00 2001 From: Ilya Shcherbakov <86749581+LikeKugi@users.noreply.github.com> Date: Thu, 7 Sep 2023 23:30:54 +0300 Subject: [PATCH 2/3] feat: add pagination for lazy loading implementation --- .../components/ProductCard/ProductCard.tsx | 41 +++++++---------- .../ProductsPagination/ProductsPagination.tsx | 44 +++++++++++++++++++ .../src/pages/ProductsPage/ProductsPage.tsx | 2 + .../src/store/slices/productsSlice.ts | 1 + .../src/store/slices/queryParamsSlice.ts | 7 ++- 5 files changed, 68 insertions(+), 27 deletions(-) create mode 100644 e-commerce-app/src/components/ProductsPagination/ProductsPagination.tsx diff --git a/e-commerce-app/src/components/ProductCard/ProductCard.tsx b/e-commerce-app/src/components/ProductCard/ProductCard.tsx index ecf0160..77dcadc 100644 --- a/e-commerce-app/src/components/ProductCard/ProductCard.tsx +++ b/e-commerce-app/src/components/ProductCard/ProductCard.tsx @@ -66,61 +66,50 @@ export const ProductCard: FC = ({ item }) => { return ( - - + + - - + + {item.masterData.current.name.en} {tax !== 0 ? ( <> - + {salePriceEUR} - + {priceEUR} ) : ( - + {priceEUR} )} {tax !== 0 ? ( <> - + {salePriceUSD} - + {priceUSD} ) : ( - + {priceUSD} )} - diff --git a/e-commerce-app/src/components/ProductsPagination/ProductsPagination.tsx b/e-commerce-app/src/components/ProductsPagination/ProductsPagination.tsx new file mode 100644 index 0000000..1ac2575 --- /dev/null +++ b/e-commerce-app/src/components/ProductsPagination/ProductsPagination.tsx @@ -0,0 +1,44 @@ +import { Pagination } from '@mui/material'; +import { JSX, useEffect, useState } from 'react'; +import Box from '@mui/material/Box'; +import { useAppDispatch, useAppSelector } from '../../store/hooks'; +import { getProductsTotal } from '../../store/slices/productsSlice'; +import { getQueryLimit, getQueryOffset, setQueryOffset } from '../../store/slices/queryParamsSlice'; + +const ProductsPagination = (): JSX.Element => { + const totalProductsCount = useAppSelector(getProductsTotal); + const queryLimit = useAppSelector(getQueryLimit); + const queryOffset = useAppSelector(getQueryOffset); + const dispatch = useAppDispatch(); + + const [page, setPage] = useState(queryOffset / queryLimit + 1); + const [maxPages, setMaxPages] = useState(0); + + useEffect(() => { + const totalPagesCount = Math.ceil(totalProductsCount / queryLimit); + setMaxPages(totalPagesCount); + }, [totalProductsCount]); + + useEffect(() => { + const newOffset = (page - 1) * queryLimit; + if (newOffset < totalProductsCount) { + dispatch(setQueryOffset(newOffset)); + } + }, [page]); + const handleChange = (event: React.ChangeEvent, value: number) => { + setPage(value); + }; + + return ( + + + + ); +}; +export default ProductsPagination; diff --git a/e-commerce-app/src/pages/ProductsPage/ProductsPage.tsx b/e-commerce-app/src/pages/ProductsPage/ProductsPage.tsx index f36408e..c11fc05 100644 --- a/e-commerce-app/src/pages/ProductsPage/ProductsPage.tsx +++ b/e-commerce-app/src/pages/ProductsPage/ProductsPage.tsx @@ -10,6 +10,7 @@ import { SubmitHandler, useForm } from 'react-hook-form'; import { ISearchProductForm } from '../../types/searchProductsTypes/searchFormTypes'; import { getQueryText, setQueryText } from '../../store/slices/queryParamsSlice'; import { useAppSelector } from '../../store/hooks'; +import ProductsPagination from '../../components/ProductsPagination/ProductsPagination'; export const ProductsPage: React.FC = () => { const dispatch = useDispatch(); @@ -62,6 +63,7 @@ export const ProductsPage: React.FC = () => { + ); diff --git a/e-commerce-app/src/store/slices/productsSlice.ts b/e-commerce-app/src/store/slices/productsSlice.ts index e3cbaf2..98e74d6 100644 --- a/e-commerce-app/src/store/slices/productsSlice.ts +++ b/e-commerce-app/src/store/slices/productsSlice.ts @@ -39,6 +39,7 @@ export const productsSlice = createSlice({ }); export const getProducts = (state: RootStateType) => state.products.products; +export const getProductsTotal = (state: RootStateType) => state.products.total; export const isFetchingProducts = (state: RootStateType) => state.products.fetching; export const ProductsReducer = productsSlice.reducer; export const { startLoadingProducts, setProducts, resetProducts } = productsSlice.actions; diff --git a/e-commerce-app/src/store/slices/queryParamsSlice.ts b/e-commerce-app/src/store/slices/queryParamsSlice.ts index d0ed2eb..0671559 100644 --- a/e-commerce-app/src/store/slices/queryParamsSlice.ts +++ b/e-commerce-app/src/store/slices/queryParamsSlice.ts @@ -4,7 +4,7 @@ import { RootStateType } from '../store'; import { SortFormType } from '../../types/searchProductsTypes/filterFormTypes'; const initialState: IQueryParamsFromSlice = { - limit: 500, + limit: 12, offset: 0, sort: '', text: '', @@ -21,20 +21,25 @@ export const queryParamsSlice = createSlice({ }, setQuerySort: (state, action: PayloadAction) => { state.sort = action.payload; + state.offset = 0; }, setQueryText: (state, action: PayloadAction) => { state.text = action.payload; + state.offset = 0; }, setEmptySort: (state) => { state.sort = ''; state.categories = ''; state.centAmount = [0, 100]; + state.offset = 0; }, setQueryCentAmount: (state, action: PayloadAction) => { state.centAmount = [...action.payload]; + state.offset = 0; }, setQueryCategories: (state, action: PayloadAction) => { state.categories = action.payload; + state.offset = 0; }, }, }); From 5cdfc02639b07c48d055ac34328c7c93508b6552 Mon Sep 17 00:00:00 2001 From: Ilya Shcherbakov <86749581+LikeKugi@users.noreply.github.com> Date: Thu, 7 Sep 2023 23:58:55 +0300 Subject: [PATCH 3/3] feat: add pagination state in ProductsQuery --- .../ProductsPagination/ProductsPagination.tsx | 19 +++++---- .../ProductsQuery/ProductsQuery.tsx | 39 +++++++++++++++++++ .../src/store/slices/productsSlice.ts | 2 + 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/e-commerce-app/src/components/ProductsPagination/ProductsPagination.tsx b/e-commerce-app/src/components/ProductsPagination/ProductsPagination.tsx index 1ac2575..680fb6c 100644 --- a/e-commerce-app/src/components/ProductsPagination/ProductsPagination.tsx +++ b/e-commerce-app/src/components/ProductsPagination/ProductsPagination.tsx @@ -30,14 +30,17 @@ const ProductsPagination = (): JSX.Element => { }; return ( - - + + ); }; diff --git a/e-commerce-app/src/requestsComponents/ProductsQuery/ProductsQuery.tsx b/e-commerce-app/src/requestsComponents/ProductsQuery/ProductsQuery.tsx index b1df4c2..e877281 100644 --- a/e-commerce-app/src/requestsComponents/ProductsQuery/ProductsQuery.tsx +++ b/e-commerce-app/src/requestsComponents/ProductsQuery/ProductsQuery.tsx @@ -8,6 +8,8 @@ import { setProducts, startLoadingProducts } from '../../store/slices/productsSl import { getQueryCategories, getQueryCentAmount, + getQueryLimit, + getQueryOffset, getQuerySort, getQueryText, } from '../../store/slices/queryParamsSlice'; @@ -23,6 +25,9 @@ const ProductsQuery = (): JSX.Element => { const searchQueryText = useAppSelector(getQueryText); const searchQueryCentAmount = useAppSelector(getQueryCentAmount); const searchQueryCategories = useAppSelector(getQueryCategories); + const searchQueryLimit = useAppSelector(getQueryLimit); + const searchQueryOffset = useAppSelector(getQueryOffset); + const [params, setParams] = useState({}); @@ -92,6 +97,40 @@ const ProductsQuery = (): JSX.Element => { })); }, [searchQueryCentAmount, searchQueryCategories]); + useEffect(() => { + if (searchQueryLimit) { + setParams((prevState) => ({ + ...prevState, + limit: searchQueryLimit, + })); + return; + } + setParams((prevState) => { + const newState = { + ...prevState, + }; + delete newState.limit; + return newState; + }); + }, [searchQueryLimit]); + + useEffect(() => { + if (searchQueryOffset) { + setParams((prevState) => ({ + ...prevState, + offset: searchQueryOffset, + })); + return; + } + setParams((prevState) => { + const newState = { + ...prevState, + }; + delete newState.offset; + return newState; + }); + }, [searchQueryOffset]); + const [ getAllProducts, { diff --git a/e-commerce-app/src/store/slices/productsSlice.ts b/e-commerce-app/src/store/slices/productsSlice.ts index 98e74d6..6332410 100644 --- a/e-commerce-app/src/store/slices/productsSlice.ts +++ b/e-commerce-app/src/store/slices/productsSlice.ts @@ -40,6 +40,8 @@ export const productsSlice = createSlice({ export const getProducts = (state: RootStateType) => state.products.products; export const getProductsTotal = (state: RootStateType) => state.products.total; +export const getProductsLimit = (state: RootStateType) => state.products.limit; +export const getProductsOffset = (state: RootStateType) => state.products.offset; export const isFetchingProducts = (state: RootStateType) => state.products.fetching; export const ProductsReducer = productsSlice.reducer; export const { startLoadingProducts, setProducts, resetProducts } = productsSlice.actions;