diff --git a/e-commerce-app/src/api/taxApi.ts b/e-commerce-app/src/api/taxApi.ts index cee26f0..99e6735 100644 --- a/e-commerce-app/src/api/taxApi.ts +++ b/e-commerce-app/src/api/taxApi.ts @@ -16,9 +16,9 @@ export const taxApi = createApi({ Authorization: `Bearer ${token}`, }, }; - } - }) - }) + }, + }), + }), }); export const { useGetAllTaxesQuery } = taxApi; diff --git a/e-commerce-app/src/components/ProductCard/ProductCard.tsx b/e-commerce-app/src/components/ProductCard/ProductCard.tsx index a8bdd06..eb498c9 100644 --- a/e-commerce-app/src/components/ProductCard/ProductCard.tsx +++ b/e-commerce-app/src/components/ProductCard/ProductCard.tsx @@ -31,7 +31,6 @@ export const ProductCard: FC = ({ item }) => { }); }, [item]); - const imgPath = item.masterData.current.masterVariant.images[0].url; const imgDescription = item.masterData.current.name.en; diff --git a/e-commerce-app/src/components/ProductsList/EmptyProducts.tsx b/e-commerce-app/src/components/ProductsList/EmptyProducts.tsx index 29a17f3..f8b30ae 100644 --- a/e-commerce-app/src/components/ProductsList/EmptyProducts.tsx +++ b/e-commerce-app/src/components/ProductsList/EmptyProducts.tsx @@ -7,7 +7,7 @@ export const EmptyProducts: FC = () => { return ( This is an empty product list. There are no products available! - home-icon + home-icon ); }; diff --git a/e-commerce-app/src/components/UserRedirect/UserRedirect.tsx b/e-commerce-app/src/components/UserRedirect/UserRedirect.tsx new file mode 100644 index 0000000..2bce03e --- /dev/null +++ b/e-commerce-app/src/components/UserRedirect/UserRedirect.tsx @@ -0,0 +1,13 @@ +import { JSX } from 'react'; +import { useAppSelector } from '../../store/hooks'; +import { getMyCustomerId } from '../../store/slices/myCustomerSlice'; +import { Navigate } from 'react-router-dom'; +import LoadingProgress from '../LoadingProgress/LoadingProgress'; + +const UserRedirect = (): JSX.Element => { + const myCustomerId = useAppSelector(getMyCustomerId); + + if (!myCustomerId) return ; + return ; +}; +export default UserRedirect; diff --git a/e-commerce-app/src/pages/UserPage/UserForm1.tsx b/e-commerce-app/src/pages/UserPage/UserForm1.tsx index 76006c2..18da49b 100644 --- a/e-commerce-app/src/pages/UserPage/UserForm1.tsx +++ b/e-commerce-app/src/pages/UserPage/UserForm1.tsx @@ -1,15 +1,19 @@ import TextField from '@mui/material/TextField'; import Grid from '@mui/material/Grid'; -import { FC } from 'react'; +import { FC, useState } from 'react'; import Button from '@mui/material/Button'; import Box from '@mui/material/Box'; import EditIcon from '@mui/icons-material/Edit'; +import { useAppSelector } from '../../store/hooks'; +import { getMyCustomerFirstName } from '../../store/slices/myCustomerSlice'; export const UserForm1: FC = () => { + const firstName = useAppSelector(getMyCustomerFirstName); + const [changingFirstName, setChangingFirstName] = useState(firstName); return ( - + setChangingFirstName(e.target.value)} /> diff --git a/e-commerce-app/src/requestsComponents/UserQuery/UserQuery.tsx b/e-commerce-app/src/requestsComponents/UserQuery/UserQuery.tsx new file mode 100644 index 0000000..b52033d --- /dev/null +++ b/e-commerce-app/src/requestsComponents/UserQuery/UserQuery.tsx @@ -0,0 +1,36 @@ +import { JSX, useEffect } from 'react'; +import { useAppDispatch, useAppSelector } from '../../store/hooks'; +import { getAccessToken } from '../../store/slices/userSlice'; +import { Outlet } from 'react-router-dom'; +import { useGetMyCustomerDetailsMutation } from '../../api/myCustomerApi'; +import LoadingProgress from '../../components/LoadingProgress/LoadingProgress'; +import { clearMyCustomerData, setMyCustomerData } from '../../store/slices/myCustomerSlice'; + +const UserQuery = (): JSX.Element => { + const dispatch = useAppDispatch(); + const accessToken = useAppSelector(getAccessToken); + + const [getMyCustomerDetails, { data, isSuccess, isLoading }] = useGetMyCustomerDetailsMutation(); + + useEffect(() => { + console.log('Get details ---> ', accessToken); + dispatch(clearMyCustomerData()); + if (accessToken) { + getMyCustomerDetails(accessToken); + } + }, []); + + useEffect(() => { + if (!isSuccess) return; + if (data) { + console.log(data); + dispatch(setMyCustomerData(data)); + } + }, [isSuccess, data]); + + if (isLoading) { + return ; + } + return ; +}; +export default UserQuery; diff --git a/e-commerce-app/src/routes/AppRoutes.tsx b/e-commerce-app/src/routes/AppRoutes.tsx index 9841544..5e3b7d6 100644 --- a/e-commerce-app/src/routes/AppRoutes.tsx +++ b/e-commerce-app/src/routes/AppRoutes.tsx @@ -18,6 +18,8 @@ import { PrivateRoute } from './PrivateRoute'; import ProductsQuery from '../requestsComponents/ProductsQuery/ProductsQuery'; import CategoriesQuery from '../requestsComponents/CategoriesQuery/CategoriesQuery'; import TokenGuard from '../requestsComponents/TokenGuard/TokenGuard'; +import UserQuery from '../requestsComponents/UserQuery/UserQuery'; +import UserRedirect from '../components/UserRedirect/UserRedirect'; const router = createHashRouter( createRoutesFromElements( @@ -32,12 +34,12 @@ const router = createHashRouter( } /> } /> }> - }> - {/* TODO : add redirect to the user page */} - }> + }> + }/> + } /> - } path={'/products'}> + }> } /> } /> diff --git a/e-commerce-app/src/routes/navigation.ts b/e-commerce-app/src/routes/navigation.ts index de35e80..cb6e003 100644 --- a/e-commerce-app/src/routes/navigation.ts +++ b/e-commerce-app/src/routes/navigation.ts @@ -10,7 +10,6 @@ export const userLogoutRoutes = { export const navigationRoutes = { home: '/', - product: '/product', products: '/products', user: '/user', }; diff --git a/e-commerce-app/src/store/slices/myCustomerSlice.ts b/e-commerce-app/src/store/slices/myCustomerSlice.ts new file mode 100644 index 0000000..f9c7f0f --- /dev/null +++ b/e-commerce-app/src/store/slices/myCustomerSlice.ts @@ -0,0 +1,79 @@ +import { IMyCustomerBaseResponse } from '../../types/slicesTypes/myCustomerApiSliceTypes'; +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; +import { RootStateType } from '../store'; + +const initialState: IMyCustomerBaseResponse = { + addresses: [], + authenticationMode: 'Password', + billingAddressIds: [], + dateOfBirth: '', + email: '', + firstName: '', + id: '', + isEmailVerified: false, + lastName: '', + password: '', + shippingAddressIds: [], +}; + +const myCustomerSlice = createSlice({ + initialState, + name: 'myCustomerSlice', + reducers: { + clearMyCustomerData: (state) => { + state.addresses.length = 0; + state.authenticationMode = 'Password'; + state.billingAddressIds.length = 0; + state.dateOfBirth = ''; + state.email = ''; + state.firstName = ''; + state.id = ''; + state.isEmailVerified = false; + state.lastName = ''; + state.password = ''; + state.shippingAddressIds.length = 0; + if (state.defaultBillingAddressId) { + delete state.defaultBillingAddressId; + } + if (state.defaultShippingAddressId) { + delete state.defaultShippingAddressId; + } + }, + setMyCustomerData: (state, action: PayloadAction) => { + state.addresses = action.payload.addresses; + state.authenticationMode = action.payload.authenticationMode; + state.billingAddressIds = action.payload.billingAddressIds; + state.dateOfBirth = action.payload.dateOfBirth; + state.email = action.payload.email; + state.firstName = action.payload.firstName; + state.id = action.payload.id; + state.isEmailVerified = action.payload.isEmailVerified; + state.lastName = action.payload.lastName; + state.password = action.payload.password; + state.shippingAddressIds = action.payload.shippingAddressIds; + if (action.payload.defaultBillingAddressId) { + state.defaultBillingAddressId = action.payload.defaultBillingAddressId; + } + if (action.payload.defaultShippingAddressId) { + state.defaultShippingAddressId = action.payload.defaultShippingAddressId; + } + }, + } +}); + +export const getMyCustomerAddresses = (state: RootStateType) => state.myCustomer.addresses; +export const getMyCustomerBillingAddressIds = (state: RootStateType) => state.myCustomer.billingAddressIds; +export const getMyCustomerDateOfBirth = (state: RootStateType) => state.myCustomer.dateOfBirth; +export const getMyCustomerEmail = (state: RootStateType) => state.myCustomer.email; +export const getMyCustomerFirstName = (state: RootStateType) => state.myCustomer.firstName; +export const getMyCustomerId = (state: RootStateType) => state.myCustomer.id; +export const getMyCustomerIsEmailVerified = (state: RootStateType) => state.myCustomer.isEmailVerified; +export const getMyCustomerLastName = (state: RootStateType) => state.myCustomer.lastName; +export const getMyCustomerPassword = (state: RootStateType) => state.myCustomer.password; +export const getMyCustomerShippingAddressIds = (state: RootStateType) => state.myCustomer.shippingAddressIds; +export const getMyCustomerDefaultBillingAddressId = (state: RootStateType) => state.myCustomer.defaultBillingAddressId; +export const getMyCustomerDefaultShippingAddressId = (state: RootStateType) => state.myCustomer.defaultShippingAddressId; + + +export const MyCustomerReducer = myCustomerSlice.reducer; +export const { clearMyCustomerData, setMyCustomerData } = myCustomerSlice.actions; diff --git a/e-commerce-app/src/store/slices/taxesSlice.ts b/e-commerce-app/src/store/slices/taxesSlice.ts index 66c9be9..3b17d8c 100644 --- a/e-commerce-app/src/store/slices/taxesSlice.ts +++ b/e-commerce-app/src/store/slices/taxesSlice.ts @@ -26,11 +26,10 @@ export const taxesSlice = createSlice({ state.limit = action.payload.limit; state.taxes = action.payload.results; state.fetching = false; - } - } + }, + }, }); - export const getTaxes = (state: RootStateType) => state.taxes.taxes; export const TaxesReducer = taxesSlice.reducer; export const { startLoadingTaxes, setTaxes } = taxesSlice.actions; diff --git a/e-commerce-app/src/store/store.ts b/e-commerce-app/src/store/store.ts index 8aaf9d5..11c3f9c 100644 --- a/e-commerce-app/src/store/store.ts +++ b/e-commerce-app/src/store/store.ts @@ -10,7 +10,7 @@ import { productProjectionApi } from '../api/productProjectionApi'; import { QueryParamsReducer } from './slices/queryParamsSlice'; import { taxApi } from '../api/taxApi'; import { TaxesReducer } from './slices/taxesSlice'; - +import { MyCustomerReducer } from './slices/myCustomerSlice'; export const store = configureStore({ reducer: { @@ -25,6 +25,7 @@ export const store = configureStore({ products: ProductsReducer, queryParams: QueryParamsReducer, taxes: TaxesReducer, + myCustomer: MyCustomerReducer, }, middleware: (getDefaultMiddleware) => getDefaultMiddleware({}).concat([ diff --git a/e-commerce-app/src/types/searchProductsTypes/searchFormTypes.ts b/e-commerce-app/src/types/searchProductsTypes/searchFormTypes.ts index d350a41..0397778 100644 --- a/e-commerce-app/src/types/searchProductsTypes/searchFormTypes.ts +++ b/e-commerce-app/src/types/searchProductsTypes/searchFormTypes.ts @@ -1,3 +1,3 @@ export interface ISearchProductForm { - query: string + query: string; } diff --git a/e-commerce-app/src/types/slicesTypes/myCustomerApiSliceTypes.ts b/e-commerce-app/src/types/slicesTypes/myCustomerApiSliceTypes.ts index 2b6d5ea..f17b0be 100644 --- a/e-commerce-app/src/types/slicesTypes/myCustomerApiSliceTypes.ts +++ b/e-commerce-app/src/types/slicesTypes/myCustomerApiSliceTypes.ts @@ -8,19 +8,19 @@ export interface IMyCustomerLoginRequest { } export interface IMyCustomerBaseResponse { - id: string; + addresses: IMyCustomerApiAddressRequest[]; + authenticationMode: 'Password' | string; + billingAddressIds: string[]; + dateOfBirth: string; email: string; firstName: string; + id: string; + isEmailVerified: boolean; lastName: string; - dateOfBirth: string; password: string; - addresses: IMyCustomerApiAddressRequest[]; - billingAddressIds: string[]; shippingAddressIds: string[]; defaultBillingAddressId?: string; defaultShippingAddressId?: string; - isEmailVerified: boolean; - authenticationMode: 'Password' | string; } export interface IMyCustomerApiSignupRequest { diff --git a/e-commerce-app/src/types/slicesTypes/productProjectionsApiTypes.ts b/e-commerce-app/src/types/slicesTypes/productProjectionsApiTypes.ts index 2d9dca2..577640b 100644 --- a/e-commerce-app/src/types/slicesTypes/productProjectionsApiTypes.ts +++ b/e-commerce-app/src/types/slicesTypes/productProjectionsApiTypes.ts @@ -8,6 +8,6 @@ export interface ISearchApiResponse extends IProductApiDescriptionResponse { taxCategory: ICategoryTypeResponse; } -export interface ISearchProductsResponse extends IBaseGetAllQueryResponse{ +export interface ISearchProductsResponse extends IBaseGetAllQueryResponse { results: ISearchApiResponse[]; } diff --git a/e-commerce-app/src/utils/makeProductSliceObjectFromSearchApiRequest.ts b/e-commerce-app/src/utils/makeProductSliceObjectFromSearchApiRequest.ts index f77d180..b657458 100644 --- a/e-commerce-app/src/utils/makeProductSliceObjectFromSearchApiRequest.ts +++ b/e-commerce-app/src/utils/makeProductSliceObjectFromSearchApiRequest.ts @@ -1,9 +1,12 @@ -import { ISearchApiResponse, ISearchProductsResponse } from '../types/slicesTypes/productProjectionsApiTypes'; +import { + ISearchApiResponse, + ISearchProductsResponse, +} from '../types/slicesTypes/productProjectionsApiTypes'; import { IGetAllProductsResponse, IMasterDataProductApiResponse, IProductApiDescriptionResponse, - IProductApiResponse + IProductApiResponse, } from '../types/slicesTypes/productsApiTypes'; const makeFromSearchApiProductApiResponses = (el: ISearchApiResponse): IProductApiResponse => { @@ -15,7 +18,7 @@ const makeFromSearchApiProductApiResponses = (el: ISearchApiResponse): IProductA name: el.name, searchKeywords: el.searchKeywords, slug: el.slug, - variants: el.variants + variants: el.variants, }; const masterData: IMasterDataProductApiResponse = { current: current, @@ -28,13 +31,15 @@ const makeFromSearchApiProductApiResponses = (el: ISearchApiResponse): IProductA key: el.key, masterData: masterData, productType: el.productType, - taxCategory: el.taxCategory + taxCategory: el.taxCategory, }; return newProduct; }; -export const makeProductSliceObjectFromSearchApiRequest = (dataSearch: ISearchProductsResponse): IGetAllProductsResponse => { - const productsArray = dataSearch.results.map(el => makeFromSearchApiProductApiResponses(el)); +export const makeProductSliceObjectFromSearchApiRequest = ( + dataSearch: ISearchProductsResponse, +): IGetAllProductsResponse => { + const productsArray = dataSearch.results.map((el) => makeFromSearchApiProductApiResponses(el)); const pushingObject: IGetAllProductsResponse = { limit: dataSearch.limit, offset: dataSearch.offset,