diff --git a/e-commerce-app/src/App.tsx b/e-commerce-app/src/App.tsx index 39af6ea..bab03eb 100644 --- a/e-commerce-app/src/App.tsx +++ b/e-commerce-app/src/App.tsx @@ -10,7 +10,14 @@ import LoadingProgress from './components/LoadingProgress/LoadingProgress'; export const App = () => { const [getAnonymousToken] = useGetAnonymousTokenMutation(); - const { isTokenInStorage, getTokenFromStorage, delTokenFromStorage } = useLocalToken(); + const { + isTokenInStorage, + getTokenFromStorage, + delTokenFromStorage, + setTokenInSessionStorage, + getTokenFromSessionStorage, + isTokenInLocalStorage, + } = useLocalToken(); const [getAccessTokenApi, { data, isSuccess, isError, isLoading }] = useGetAccessTokenFromRefreshMutation(); const [getDetails] = useGetMyCustomerDetailsMutation(); @@ -37,21 +44,34 @@ export const App = () => { }, [isError]); useEffect(() => { - if (accessToken) return; + if (accessToken) { + return; + } + + if (isTokenInLocalStorage()) { + const token = getTokenFromSessionStorage(); + if (token) { + getAccessTokenApi(token); + } + return; + } + if (isTokenInStorage()) { const token = getTokenFromStorage(); if (token) { getAccessTokenApi(token); } - } else { - getAnonymousToken().then((res) => { - if ('data' in res) { - dispatch( - setAuth({ access_token: res.data.access_token, refresh_token: res.data.refresh_token }), - ); - } - }); + return; } + + getAnonymousToken().then((res) => { + if ('data' in res) { + dispatch( + setAuth({ access_token: res.data.access_token, refresh_token: res.data.refresh_token }), + ); + setTokenInSessionStorage(res.data.refresh_token); + } + }); }, [accessToken]); if (isLoading) { diff --git a/e-commerce-app/src/components/ProductCard/ProductCard.module.scss b/e-commerce-app/src/components/ProductCard/ProductCard.module.scss index 78aabcc..764ec12 100644 --- a/e-commerce-app/src/components/ProductCard/ProductCard.module.scss +++ b/e-commerce-app/src/components/ProductCard/ProductCard.module.scss @@ -7,15 +7,13 @@ padding: 1rem; border: 2px green double; transition: box-shadow .3s ease-in-out; + cursor: pointer; &:hover { box-shadow: 8px 10px 5px 2px #14763033; transition: box-shadow .3s ease-in-out; } - &__pointer { - cursor: pointer; - } &__text { diff --git a/e-commerce-app/src/components/ProductCard/ProductCard.tsx b/e-commerce-app/src/components/ProductCard/ProductCard.tsx index 77dcadc..c4eba6e 100644 --- a/e-commerce-app/src/components/ProductCard/ProductCard.tsx +++ b/e-commerce-app/src/components/ProductCard/ProductCard.tsx @@ -13,12 +13,14 @@ interface ICardProps { export const ProductCard: FC = ({ item }) => { const navigate = useNavigate(); - const handlerNavigation = () => { - navigate(`/products/${item.id}`); - }; - const handlerAddToCart = () => { - console.log('here, add to cart'); + const clickOnCardHandler = (e: React.MouseEvent) => { + console.log(e.target instanceof HTMLButtonElement); + if (e.target instanceof HTMLButtonElement) { + console.log(`here, add to cart ${item.id}`); + } else { + navigate(`/products/${item.id}`); + } }; const taxesArray = useAppSelector(getTaxes); @@ -65,15 +67,11 @@ export const ProductCard: FC = ({ item }) => { }).format(numberUSD - numberUSD * tax); return ( - - + clickOnCardHandler(e)}> + - + {item.masterData.current.name.en} @@ -109,7 +107,7 @@ export const ProductCard: FC = ({ item }) => { )} - diff --git a/e-commerce-app/src/components/ProductsFilterForm/ProductsFilterForm.tsx b/e-commerce-app/src/components/ProductsFilterForm/ProductsFilterForm.tsx index 5a661a6..fe542d8 100644 --- a/e-commerce-app/src/components/ProductsFilterForm/ProductsFilterForm.tsx +++ b/e-commerce-app/src/components/ProductsFilterForm/ProductsFilterForm.tsx @@ -1,4 +1,4 @@ -import React, { JSX, useState } from 'react'; +import React, { JSX, useId, useState } from 'react'; import { Box, Button, @@ -38,6 +38,9 @@ const ProductsFilterForm = (): JSX.Element => { const [sortRate, setSortRate] = useState(searchQuerySort); const [sortCategories, setSortCategories] = useState(searchQueryCategories); + const categoriesId = useId(); + const sortById = useId(); + const handleChange2 = (event: Event, newValue: number | number[], activeThumb: number) => { if (!Array.isArray(newValue)) { return; @@ -92,11 +95,11 @@ const ProductsFilterForm = (): JSX.Element => { Catalog - Categories + Categories { const [anchorElUser, setAnchorElUser] = React.useState(null); @@ -18,18 +20,22 @@ const UserMenu = (): JSX.Element => { setAnchorElUser(null); }; + const menuId = useId(); + const isLoggedIn = useAppSelector(getLoggedIn); return ( - + + + { const delTokenFromStorage = (): void => { localStorage.removeItem(tokenName); + sessionStorage.removeItem(tokenName); }; const isTokenInStorage = (): boolean => { return !!localStorage.getItem(tokenName); }; + const setTokenInSessionStorage = (token: string): void => { + sessionStorage.setItem(tokenName, token); + }; + + const getTokenFromSessionStorage = (): string | null => { + return sessionStorage.getItem(tokenName); + }; + + const isTokenInLocalStorage = (): boolean => { + return !!sessionStorage.getItem(tokenName); + }; + return { setTokenInStorage, getTokenFromStorage, delTokenFromStorage, isTokenInStorage, + setTokenInSessionStorage, + getTokenFromSessionStorage, + isTokenInLocalStorage, }; }; diff --git a/e-commerce-app/src/pages/.gitkeep b/e-commerce-app/src/pages/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/e-commerce-app/src/pages/AboutPage/AboutPage.tsx b/e-commerce-app/src/pages/AboutPage/AboutPage.tsx index 744760d..c9a3d1c 100644 --- a/e-commerce-app/src/pages/AboutPage/AboutPage.tsx +++ b/e-commerce-app/src/pages/AboutPage/AboutPage.tsx @@ -19,7 +19,7 @@ import Backgroung from '../../assets/AboutPageImg/fon-trava.jpeg'; export const AboutPage: React.FC = () => { return ( { - Python developer, meme creator, great sense of humor. + Python enjoyer, meme creator, great sense of humor. diff --git a/e-commerce-app/src/pages/ErrorPage/ErrorPage.tsx b/e-commerce-app/src/pages/ErrorPage/ErrorPage.tsx index 1bbfcd6..6d1d5b1 100644 --- a/e-commerce-app/src/pages/ErrorPage/ErrorPage.tsx +++ b/e-commerce-app/src/pages/ErrorPage/ErrorPage.tsx @@ -16,16 +16,19 @@ export const ErrorPage: React.FC = () => { justifyContent: 'start', alignItems: 'center', flexDirection: 'column', - minHeight: '80vh', + minHeight: '90vh', marginBottom: '3%', }} + pt={5} > Sorry, the page you’re looking for doesn’t exist. home-icon ); diff --git a/e-commerce-app/src/pages/LoginPage/LoginPage.tsx b/e-commerce-app/src/pages/LoginPage/LoginPage.tsx index a58845b..ae6225b 100644 --- a/e-commerce-app/src/pages/LoginPage/LoginPage.tsx +++ b/e-commerce-app/src/pages/LoginPage/LoginPage.tsx @@ -12,7 +12,7 @@ import { } from '@mui/material'; import LoginImage from '../../assets/images/ImgLoginPage.png'; import { NavLink, useNavigate } from 'react-router-dom'; -import { FC, useEffect, useState } from 'react'; +import { FC, useEffect, useId, useState } from 'react'; import { useValidate } from '../../hooks/useValidate'; import { SubmitHandler, useForm } from 'react-hook-form'; import VisibilityIcon from '@mui/icons-material/Visibility'; @@ -59,7 +59,7 @@ export const LoginPage: FC = () => { }, [isLoggedIn]); const { validateField } = useValidate(); - const { setTokenInStorage } = useLocalToken(); + const { setTokenInStorage, setTokenInSessionStorage } = useLocalToken(); const dispatch = useAppDispatch(); const [globalError, setGlobalError] = useState({ @@ -85,6 +85,7 @@ export const LoginPage: FC = () => { useEffect(() => { if (!isSuccess || !data) return; dispatch(setAuth({ access_token: data.access_token, refresh_token: data.refresh_token })); + setTokenInSessionStorage(data.refresh_token); if (isRememberedUser) { setTokenInStorage(data.refresh_token); } @@ -97,6 +98,8 @@ export const LoginPage: FC = () => { dispatch(setLogOut()); }, [isError]); + const loginFormId = useId(); + const submitHandler: SubmitHandler = (data) => { if (data.email) { const errStr = validateField('email', data.email); @@ -201,7 +204,7 @@ export const LoginPage: FC = () => { component="form" noValidate sx={{ mt: 5, ml: 8, mr: 8 }} - id="login-form" + id={loginFormId} onSubmit={handleSubmit(submitHandler)} > {globalError.status && ( @@ -212,7 +215,7 @@ export const LoginPage: FC = () => { { = ({ register, errors, diff --git a/e-commerce-app/src/pages/UserPage/UserAddresses.tsx b/e-commerce-app/src/pages/UserPage/UserAddresses.tsx index 8150cac..0cc2144 100644 --- a/e-commerce-app/src/pages/UserPage/UserAddresses.tsx +++ b/e-commerce-app/src/pages/UserPage/UserAddresses.tsx @@ -1,5 +1,5 @@ import { FC, useState } from 'react'; -import { Box, Typography, Button } from '@mui/material'; +import { Box, Typography } from '@mui/material'; import { AddressPanel } from '../../components/AddressPanel/AddressPanel'; import { AddressList } from '../../components/AddressList/AddressList'; import { IUserProps } from '../../interfaces/IUserProps'; diff --git a/e-commerce-app/src/pages/UserPage/UserPage.tsx b/e-commerce-app/src/pages/UserPage/UserPage.tsx index 3d5e101..577b8ea 100644 --- a/e-commerce-app/src/pages/UserPage/UserPage.tsx +++ b/e-commerce-app/src/pages/UserPage/UserPage.tsx @@ -11,18 +11,12 @@ import { Divider, Grid, Stack, - Tab, - Tabs, useMediaQuery, } from '@mui/material'; import PersonIcon from '@mui/icons-material/Person'; import ContactsIcon from '@mui/icons-material/Contacts'; -import LocalShippingIcon from '@mui/icons-material/LocalShipping'; -import HomeIcon from '@mui/icons-material/Home'; -import PaymentIcon from '@mui/icons-material/Payment'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import { UserData } from './UserData'; -import { UserAddresses } from './UserAddresses'; import { useValidate } from '../../hooks/useValidate'; import { IRegistrationFormData } from '../../interfaces/IRegistrationFormData'; import { useForm, SubmitHandler, FieldErrors } from 'react-hook-form'; @@ -54,8 +48,6 @@ import UserPersonalAddressTab from '../../components/UserPersonalAddressTab/User import UserPersonalAddAddress from '../../components/UserPersonalAddAddress/UserPersonalAddAddress'; import { UserPassword } from './UserPassword'; -const steps = ['Personal information', 'Shipping/Billing address', 'Change password']; - export const UserPage: React.FC = () => { const firstName = useAppSelector(getMyCustomerFirstName); const lastName = useAppSelector(getMyCustomerLastName); @@ -66,7 +58,6 @@ export const UserPage: React.FC = () => { const billingAddressId = useAppSelector(getMyCustomerBillingAddressIds); const shippingDefaultAddressId = useAppSelector(getMyCustomerDefaultShippingAddressId); const billingDefaultAddressId = useAppSelector(getMyCustomerDefaultBillingAddressId); - const password = useAppSelector(getMyCustomerPassword); const myCustomerVersion = useAppSelector(getMyCustomerVersion); const [activeStep, setActiveStep] = useState(0); @@ -76,16 +67,6 @@ export const UserPage: React.FC = () => { const accessToken = useAppSelector(getAccessToken) as string; const [updateMyCustomer] = useUpdateMyCustomerMutation(); - const initialUserBio: IMakeUpdateMyCustomerPersonalQueryObject = { - firstName, - lastName, - birthDate, - email, - }; - - const billingAddresses = addresses.filter((address) => billingAddressId.includes(address.id)); - const shippingAddresses = addresses.filter((address) => shippingAddressId.includes(address.id)); - const { register, handleSubmit, @@ -98,43 +79,6 @@ export const UserPage: React.FC = () => { } = useForm(); const [activeAddressTab, setActiveAddressTab] = useState(0); - const mediumViewport = useMediaQuery('(min-width:900px)'); - const handleAddressTabChange = (event: React.SyntheticEvent, newValue: number) => { - setActiveAddressTab(newValue); - }; - - const [openEditBio, setOpenEditBio] = React.useState(false); - - const handleClickOpenEditBio = () => { - setOpenEditBio(true); - }; - - const handleCloseClickCloseEditBio = () => { - setOpenEditBio(false); - }; - - const isStepSkipped = (step: number) => { - return skipped.has(step); - }; - - const handleNext = () => { - let newSkipped = skipped; - if (isStepSkipped(activeStep)) { - newSkipped = new Set(newSkipped.values()); - newSkipped.delete(activeStep); - } - - setActiveStep((prevActiveStep) => prevActiveStep + 1); - setSkipped(newSkipped); - }; - - const handleBack = () => { - setActiveStep((prevActiveStep) => prevActiveStep - 1); - }; - - const handleReset = () => { - setActiveStep(0); - }; const globalErrors = Object.keys(validationErrors).reduce>( (acc, item) => { @@ -184,7 +128,7 @@ export const UserPage: React.FC = () => { }; const onSubmitPersonal: SubmitHandler = (data) => { - if (Object.keys(globalErrors).length) { + if (Object.keys(globalErrors).length || !Object.keys(data).length) { return; } @@ -214,8 +158,6 @@ export const UserPage: React.FC = () => { updateMyCustomer({ token: accessToken, data: updateData, - }).then((a) => { - console.log(a); }); }; @@ -228,14 +170,6 @@ export const UserPage: React.FC = () => { const userData = [firstName, lastName, birthDate, email]; - const userAddresses = [ - addresses, - shippingAddressId, - billingAddressId, - shippingDefaultAddressId, - billingDefaultAddressId, - ]; - return ( <> diff --git a/e-commerce-app/src/pages/UserPage/UserPassword.tsx b/e-commerce-app/src/pages/UserPage/UserPassword.tsx index 2c4940b..8c856bf 100644 --- a/e-commerce-app/src/pages/UserPage/UserPassword.tsx +++ b/e-commerce-app/src/pages/UserPage/UserPassword.tsx @@ -16,6 +16,7 @@ import { getAccessToken, getUserEmail, setAuth } from '../../store/slices/userSl import { useChangePasswordMyCustomerMutation } from '../../api/myCustomerApi'; import { useDispatch } from 'react-redux'; import { useLoginUserMutation } from '../../api/authApi'; +import { useLocalToken } from '../../hooks/useLocalToken'; interface IResetPasswordForm { currentPassword: string; @@ -35,6 +36,8 @@ export const UserPassword = () => { const [newPassword, setNewPassword] = useState(''); const [confirmNewPassword, setConfirmNewPassword] = useState(''); + const { delTokenFromStorage, setTokenInSessionStorage } = useLocalToken(); + const { handleSubmit, setError, @@ -110,9 +113,11 @@ export const UserPassword = () => { .unwrap() .then((result) => { if (result) { + delTokenFromStorage(); dispatch( setAuth({ access_token: result.access_token, refresh_token: result.refresh_token }), ); + setTokenInSessionStorage(result.refresh_token); } }); }) diff --git a/e-commerce-app/src/requestsComponents/ProductsQuery/ProductsQuery.tsx b/e-commerce-app/src/requestsComponents/ProductsQuery/ProductsQuery.tsx index e877281..c3d3492 100644 --- a/e-commerce-app/src/requestsComponents/ProductsQuery/ProductsQuery.tsx +++ b/e-commerce-app/src/requestsComponents/ProductsQuery/ProductsQuery.tsx @@ -28,7 +28,6 @@ const ProductsQuery = (): JSX.Element => { const searchQueryLimit = useAppSelector(getQueryLimit); const searchQueryOffset = useAppSelector(getQueryOffset); - const [params, setParams] = useState({}); useEffect(() => { diff --git a/e-commerce-app/src/routes/.gitkeep b/e-commerce-app/src/routes/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/e-commerce-app/src/routes/navigation.ts b/e-commerce-app/src/routes/navigation.ts index 61532b0..d682c41 100644 --- a/e-commerce-app/src/routes/navigation.ts +++ b/e-commerce-app/src/routes/navigation.ts @@ -11,11 +11,11 @@ export const userLogoutRoutes = { export const navigationRoutes = { home: '/', products: '/products', + about: '/about', + basket: '/basket', }; export const unusedNavigation = { - about: '/about', - basket: '/basket', product: '/product', products: '/products', user: '/user',