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
1 change: 1 addition & 0 deletions e-commerce-app/src/assets/images/EmptyCatalogPage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions e-commerce-app/src/components/ProductCard/ProductCard.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
transition: box-shadow .3s ease-in-out;
}


&__text {
height: 100%;
display: flex;
Expand All @@ -33,5 +34,19 @@
width: 50%;
font-weight: 700;
text-align: center;

&__marked {
color: rgb(221, 65, 65);
padding-top: 1rem;
width: 50%;
font-weight: 700;
text-align: center;
}

&__sale {
text-decoration: line-through;
text-decoration-color: gray;
padding-top: 1rem;
}
}
}
91 changes: 71 additions & 20 deletions e-commerce-app/src/components/ProductCard/ProductCard.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { FC } from 'react';
import { FC, useEffect, useState } from 'react';
import styles from './ProductCard.module.scss';
import { Box, Typography, Button, CardMedia, CardContent, CardActions, Card } from '@mui/material';
import { useNavigate } from 'react-router-dom';
import { IProductApiResponse } from '../../types/slicesTypes/productsApiTypes';
import { getTaxes } from '../../store/slices/taxesSlice';
import { useAppSelector } from '../../store/hooks';
import { ITaxApiResponse } from '../../types/slicesTypes/taxApiTypes';

interface ICardProps {
item: IProductApiResponse;
Expand All @@ -14,25 +17,49 @@ export const ProductCard: FC<ICardProps> = ({ item }) => {
navigate(`/products/${item.id}`);
};

const taxesArray = useAppSelector(getTaxes);

const [tax, setTax] = useState(0);

useEffect(() => {
taxesArray
.filter((i) => i.id === item.taxCategory.id && i.key === 'sale')
.flatMap((elem) => elem.rates)
.filter((rate: ITaxApiResponse) => rate.country === 'DE')
.forEach((rate: ITaxApiResponse) => {
setTax(rate.amount);
});
}, [item]);


const imgPath = item.masterData.current.masterVariant.images[0].url;
const imgDescription = item.masterData.current.name.en;

const currencyCommon = item.masterData.current.masterVariant.prices[0].value.currencyCode;
const priceCommon = new Intl.NumberFormat('en-IN', {
style: 'currency',
currency: currencyCommon,
}).format(
const currencyEUR = item.masterData.current.masterVariant.prices[0].value.currencyCode;
const numberEUR =
item.masterData.current.masterVariant.prices[0].value.centAmount /
10 ** item.masterData.current.masterVariant.prices[0].value.fractionDigits,
);
const currencySale = item.masterData.current.masterVariant.prices[1].value.currencyCode;
const priceSale = new Intl.NumberFormat('en-IN', {
10 ** item.masterData.current.masterVariant.prices[0].value.fractionDigits;
const priceEUR = new Intl.NumberFormat('en-IN', {
style: 'currency',
currency: currencySale,
}).format(
currency: currencyEUR,
}).format(numberEUR);
const salePriceEUR = new Intl.NumberFormat('en-IN', {
style: 'currency',
currency: currencyEUR,
}).format(numberEUR - numberEUR * tax);

const currencyUSD = item.masterData.current.masterVariant.prices[1].value.currencyCode;
const numberUSD =
item.masterData.current.masterVariant.prices[1].value.centAmount /
10 ** item.masterData.current.masterVariant.prices[1].value.fractionDigits,
);
10 ** item.masterData.current.masterVariant.prices[1].value.fractionDigits;
const priceUSD = new Intl.NumberFormat('en-IN', {
style: 'currency',
currency: currencyUSD,
}).format(numberUSD);
const salePriceUSD = new Intl.NumberFormat('en-IN', {
style: 'currency',
currency: currencyUSD,
}).format(numberUSD - numberUSD * tax);

return (
<Card className={styles.card}>
Expand All @@ -43,12 +70,36 @@ export const ProductCard: FC<ICardProps> = ({ item }) => {
<Typography className={styles.card__title} component="h2">
{item.masterData.current.name.en}
</Typography>
<Typography className={styles.card__price} component="h3">
{priceCommon}
</Typography>
<Typography className={styles.card__price} component="h3">
{priceSale}
</Typography>

{tax !== 0 ? (
<>
<Typography className={styles.card__price__marked} component="h3">
{salePriceEUR}
</Typography>
<Typography className={styles.card__price__sale} component="h3">
{priceEUR}
</Typography>
</>
) : (
<Typography className={styles.card__price} component="h3">
{priceEUR}
</Typography>
)}

{tax !== 0 ? (
<>
<Typography className={styles.card__price__marked} component="h3">
{salePriceUSD}
</Typography>
<Typography className={styles.card__price__sale} component="h3">
{priceUSD}
</Typography>
</>
) : (
<Typography className={styles.card__price} component="h3">
{priceUSD}
</Typography>
)}
</CardContent>
<CardActions>
<Button onClick={handlerNavigation} color="success" variant="outlined">
Expand Down
13 changes: 13 additions & 0 deletions e-commerce-app/src/components/ProductsList/EmptyProducts.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { FC } from 'react';
import styles from './ProductsList.module.scss';
import { Box } from '@mui/material';
import empty from '../../assets/images/EmptyCatalogPage.svg';

export const EmptyProducts: FC = () => {
return (
<Box className={styles.empty__products}>
This is an empty product list. There are no products available!
<img src={empty} alt="home-icon" className={styles.img}/>
</Box>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,15 @@
flex-wrap: wrap;
gap: 1.5rem;
}

.empty__products {
display: flex;
flex-direction: column;
align-items: center;
color: gray;
font-size: 25px;
}

.img {
margin-top: 50px;
}
9 changes: 6 additions & 3 deletions e-commerce-app/src/components/ProductsList/ProductsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@ import styles from './ProductsList.module.scss';
import { useAppSelector } from '../../store/hooks';
import { getProducts } from '../../store/slices/productsSlice';
import { FC } from 'react';
import { EmptyProducts } from './EmptyProducts';

export const ProductsList: FC = () => {
const products = useAppSelector(getProducts);

return (
<Box className={styles.container}>
{products.map((item) => (
<ProductCard item={item} key={item.id} />
))}
{products.length > 0 ? (
products.map((item) => <ProductCard item={item} key={item.id} />)
) : (
<EmptyProducts />
)}
</Box>
);
};
2 changes: 1 addition & 1 deletion e-commerce-app/src/pages/ProductPage/ProductPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const ProductPage: FC = () => {
useEffect(() => {
if (isSuccess) {
taxesArray
.filter((item) => item.id === data.taxCategory.id)
.filter((item) => item.id === data.taxCategory.id && item.key === 'sale')
.flatMap((elem) => elem.rates)
.filter((rate: ITaxApiResponse) => rate.country === 'DE')
.forEach((rate: ITaxApiResponse) => {
Expand Down
13 changes: 7 additions & 6 deletions e-commerce-app/src/types/slicesTypes/taxApiTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import { CountriesType } from '../addressesTypes';
import { IBaseGetAllQueryResponse } from './baseApiResponsesTypes';

export interface ITaxApiResponse {
amount: number,
country: CountriesType
id: string
includedInPrice: boolean
name: string
rates: []
amount: number;
country: CountriesType;
id: string;
includedInPrice: boolean;
name: string;
rates: [];
key: string;
}

export interface IGetAllTaxesResponse extends IBaseGetAllQueryResponse<ITaxApiResponse> {
Expand Down