Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 30 additions & 10 deletions e-commerce-app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
24 changes: 11 additions & 13 deletions e-commerce-app/src/components/ProductCard/ProductCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ interface ICardProps {

export const ProductCard: FC<ICardProps> = ({ item }) => {
const navigate = useNavigate();
const handlerNavigation = () => {
navigate(`/products/${item.id}`);
};

const handlerAddToCart = () => {
console.log('here, add to cart');
const clickOnCardHandler = (e: React.MouseEvent<HTMLDivElement>) => {
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);
Expand Down Expand Up @@ -65,15 +67,11 @@ export const ProductCard: FC<ICardProps> = ({ item }) => {
}).format(numberUSD - numberUSD * tax);

return (
<Card className={styles.card}>
<Box className={styles.card__pointer} width={'100%'} onClick={handlerNavigation}>
<Card className={styles.card} onClick={(e) => clickOnCardHandler(e)}>
<Box width={'100%'}>
<CardMedia sx={{ height: 200, width: '100%' }} image={imgPath} title={imgDescription} />
</Box>
<CardContent
className={`${styles.card__text} ${styles.card__pointer}`}
onClick={handlerNavigation}
sx={{ cursor: 'pointer' }}
>
<CardContent className={styles.card__text}>
<Typography className={styles.card__title} component="h2">
{item.masterData.current.name.en}
</Typography>
Expand Down Expand Up @@ -109,7 +107,7 @@ export const ProductCard: FC<ICardProps> = ({ item }) => {
)}
</CardContent>
<CardActions>
<Button color="success" variant="outlined" onClick={handlerAddToCart}>
<Button color="success" variant="outlined">
Add to Cart
</Button>
</CardActions>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { JSX, useState } from 'react';
import React, { JSX, useId, useState } from 'react';
import {
Box,
Button,
Expand Down Expand Up @@ -38,6 +38,9 @@ const ProductsFilterForm = (): JSX.Element => {
const [sortRate, setSortRate] = useState<SortFormType>(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;
Expand Down Expand Up @@ -92,11 +95,11 @@ const ProductsFilterForm = (): JSX.Element => {
Catalog
</Typography>
<FormControl fullWidth>
<InputLabel id="queryCategories">Categories</InputLabel>
<InputLabel id={categoriesId}>Categories</InputLabel>
<Select
fullWidth
labelId="queryCategories"
id="selectCategories"
labelId={categoriesId}
id={`select-${categoriesId}`}
label="Categories"
value={sortCategories}
{...register('categories', {
Expand All @@ -115,11 +118,11 @@ const ProductsFilterForm = (): JSX.Element => {
</FormControl>

<FormControl fullWidth>
<InputLabel id="sortBy">Sort By</InputLabel>
<InputLabel id={sortById}>Sort By</InputLabel>
<Select
fullWidth
labelId="sortBy"
id="selectSortBy"
labelId={sortById}
id={`select-${sortById}`}
label="Sort By"
value={sortRate}
{...register('sort', {
Expand Down
12 changes: 9 additions & 3 deletions e-commerce-app/src/components/UserMenu/UserMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import React, { JSX } from 'react';
import React, { JSX, useId } from 'react';
import Box from '@mui/material/Box';
import Tooltip from '@mui/material/Tooltip';
import IconButton from '@mui/material/IconButton';
import Avatar from '@mui/material/Avatar';
import PersonIcon from '@mui/icons-material/Person';
import Menu from '@mui/material/Menu';
import { useAppSelector } from '../../store/hooks';
import { getLoggedIn } from '../../store/slices/userSlice';
import MenuLinks from '../MenuLinks/MenuLinks';
import { userLoginRoutes, userLogoutRoutes } from '../../routes/navigation';
import { green } from '@mui/material/colors';

const UserMenu = (): JSX.Element => {
const [anchorElUser, setAnchorElUser] = React.useState<null | HTMLElement>(null);
Expand All @@ -18,18 +20,22 @@ const UserMenu = (): JSX.Element => {
setAnchorElUser(null);
};

const menuId = useId();

const isLoggedIn = useAppSelector(getLoggedIn);

return (
<Box sx={{ flexGrow: 0 }}>
<Tooltip title="Open settings">
<IconButton onClick={handleOpenUserMenu} sx={{ p: 0 }}>
<Avatar alt="" />
<Avatar sx={{ bgcolor: isLoggedIn ? green[700] : '' }}>
<PersonIcon />
</Avatar>
</IconButton>
</Tooltip>
<Menu
sx={{ mt: '45px' }}
id="menu-appbar"
id={menuId}
anchorEl={anchorElUser}
anchorOrigin={{
vertical: 'top',
Expand Down
16 changes: 16 additions & 0 deletions e-commerce-app/src/hooks/useLocalToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,32 @@ export const useLocalToken = () => {

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,
};
};
Empty file removed e-commerce-app/src/pages/.gitkeep
Empty file.
4 changes: 2 additions & 2 deletions e-commerce-app/src/pages/AboutPage/AboutPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import Backgroung from '../../assets/AboutPageImg/fon-trava.jpeg';
export const AboutPage: React.FC = () => {
return (
<Container
component="body"
component="div"
sx={{
backgroundImage: `url(${Backgroung})`,
backgroundRepeat: 'no-repeat',
Expand Down Expand Up @@ -74,7 +74,7 @@ export const AboutPage: React.FC = () => {
</Typography>
<Divider variant="middle" />
<Typography color="grey" fontSize={12} mt={1.5}>
Python developer, meme creator, great sense of humor.
Python enjoyer, meme creator, great sense of humor.
</Typography>
</CardContent>
</Card>
Expand Down
7 changes: 5 additions & 2 deletions e-commerce-app/src/pages/ErrorPage/ErrorPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,19 @@ export const ErrorPage: React.FC = () => {
justifyContent: 'start',
alignItems: 'center',
flexDirection: 'column',
minHeight: '80vh',
minHeight: '90vh',
marginBottom: '3%',
}}
pt={5}
>
<Typography variant="h5" style={{ color: 'darkgreen' }}>
Sorry, the page you’re looking for doesn’t exist.
</Typography>
<img src={gifIcon} alt="home-icon" width={45} height={45} />
<Button variant="contained" sx={{ backgroundColor: 'lightgreen', height: 'fit-content' }}>
<Link to="/">Back Home</Link>
<Link to="/" style={{ textDecoration: 'none' }}>
Back Home
</Link>
</Button>
</Box>
);
Expand Down
13 changes: 8 additions & 5 deletions e-commerce-app/src/pages/LoginPage/LoginPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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<IGlobalError>({
Expand All @@ -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);
}
Expand All @@ -97,6 +98,8 @@ export const LoginPage: FC = () => {
dispatch(setLogOut());
}, [isError]);

const loginFormId = useId();

const submitHandler: SubmitHandler<ILoginFormData> = (data) => {
if (data.email) {
const errStr = validateField('email', data.email);
Expand Down Expand Up @@ -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 && (
Expand All @@ -212,7 +215,7 @@ export const LoginPage: FC = () => {
<TextField
sx={{ mt: 2 }}
fullWidth
id="email"
id={`email-${loginFormId}`}
label="Email Address"
type="email"
autoComplete="off"
Expand All @@ -226,7 +229,7 @@ export const LoginPage: FC = () => {
<TextField
fullWidth
margin="normal"
id="password"
id={`password-${loginFormId}`}
label="Password"
type={showPassword ? 'text' : 'password'}
autoComplete="off"
Expand Down
2 changes: 0 additions & 2 deletions e-commerce-app/src/pages/RegistrationPage/FormPage2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import { TextField, Grid } from '@mui/material';
import { IFormPageProps } from '../../interfaces/IFormPageProps';
import { FC } from 'react';

/* eslint-disable react/prop-types */

export const FormPage2: FC<IFormPageProps> = ({
register,
errors,
Expand Down
2 changes: 1 addition & 1 deletion e-commerce-app/src/pages/UserPage/UserAddresses.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand Down
Loading