-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c477d2b
commit 54a42df
Showing
18 changed files
with
1,027 additions
and
0 deletions.
There are no files selected for viewing
29 changes: 29 additions & 0 deletions
29
src/componants/shared/productcard/CategoryCard/CategoryCard.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { useTranslation } from "react-i18next"; | ||
import { Link, useNavigate } from "react-router-dom"; | ||
import { camelCase } from "src/Functions/helper"; | ||
import SvgIcon from "../../MiniComponents/SvgIcon"; | ||
import s from "./CategoryCard.module.scss"; | ||
|
||
const CategoryCard = ({ categoryData }) => { | ||
const { iconName, title } = categoryData; | ||
const categoryType = title.toLowerCase(); | ||
const navigateTo = useNavigate(); | ||
const { t } = useTranslation(); | ||
const categoryTitleTrans = t(`categoriesData.${camelCase(title)}`); | ||
|
||
function navigateToCategory() { | ||
navigateTo(`/category?type=${categoryType}`); | ||
} | ||
|
||
return ( | ||
<Link | ||
className={s.card} | ||
title={categoryTitleTrans} | ||
onClick={navigateToCategory} | ||
> | ||
<SvgIcon name={iconName} /> | ||
<span>{categoryTitleTrans}</span> | ||
</Link> | ||
); | ||
}; | ||
export default CategoryCard; |
76 changes: 76 additions & 0 deletions
76
src/componants/shared/productcard/CategoryCard/CategoryCard.module.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
@import "src/Styles/mixins"; | ||
|
||
.card { | ||
-webkit-tap-highlight-color: transparent; | ||
scroll-snap-align: start; | ||
border-radius: 4px; | ||
border: solid 1px #0000004D; | ||
outline: 2px solid transparent; | ||
outline-offset: -2px; | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
padding: 20px; | ||
transition: background-color .2s; | ||
|
||
&:not(:focus-visible):hover { | ||
background-color: var(--tomato); | ||
border-color: var(--tomato); | ||
} | ||
|
||
&:focus-visible { | ||
background-color: #db444407; | ||
outline-color: var(--tomato); | ||
} | ||
} | ||
|
||
.card svg { | ||
width: 56px; | ||
height: 56px; | ||
transition: fill .2s .1s; | ||
|
||
& :where(path, line) { | ||
stroke: var(--black); | ||
} | ||
} | ||
|
||
.card svg:where([data-fill-hover], [data-stroke-hover]) { | ||
transition: fill .2s, stroke .2s; | ||
} | ||
|
||
.card:not(:focus-visible):hover svg[data-fill-hover] { | ||
& :where(path, line) { | ||
fill: var(--white); | ||
} | ||
} | ||
|
||
.card:not(:focus-visible):hover svg[data-stroke-hover] { | ||
& :where(path, line) { | ||
stroke: var(--white); | ||
} | ||
} | ||
|
||
.card:focus-visible svg[data-fill-hover] { | ||
& :where(path, line) { | ||
fill: var(--tomato); | ||
} | ||
} | ||
|
||
.card:focus-visible svg[data-stroke-hover] { | ||
& :where(path, line) { | ||
stroke: var(--tomato); | ||
} | ||
} | ||
|
||
.card span { | ||
margin-top: 26px; | ||
color: var(--black); | ||
} | ||
|
||
.card:not(:focus-visible):hover span { | ||
color: var(--white); | ||
} | ||
|
||
.card:focus-visible span { | ||
color: var(--tomato); | ||
} |
88 changes: 88 additions & 0 deletions
88
src/componants/shared/productcard/ProductCard/AddToCartButton/AddToCartButton.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import { useState } from "react"; | ||
import { useTranslation } from "react-i18next"; | ||
import { useDispatch, useSelector } from "react-redux"; | ||
import { showAlert } from "src/Features/alertsSlice"; | ||
import { addToArray, removeByKeyName } from "src/Features/productsSlice"; | ||
import { compareDataToObjValue, isItemFound } from "src/Functions/helper"; | ||
import SvgIcon from "../../../MiniComponents/SvgIcon"; | ||
import s from "./AddToCartButton.module.scss"; | ||
|
||
const AddToCartButton = ({ product }) => { | ||
const { t } = useTranslation(); | ||
const { cartProducts, orderProducts } = useSelector( | ||
(state) => state.products | ||
); | ||
const { | ||
loginInfo: { isSignIn }, | ||
} = useSelector((state) => state.user); | ||
const isProductAlreadyExist = isItemFound(cartProducts, product, "shortName"); | ||
const iconName = isProductAlreadyExist ? "trashCan" : "cart3"; | ||
const [iconNameState, setIconName] = useState(iconName); | ||
const dispatch = useDispatch(); | ||
const buttonText = t( | ||
`productCard.buttonText.${ | ||
isProductAlreadyExist ? "removeFromCart" : "addToCart" | ||
}` | ||
); | ||
|
||
function handleCartButton() { | ||
if (!isSignIn) { | ||
showWarning("addToCart"); | ||
return; | ||
} | ||
|
||
const isAlreadyAddedToOrder = compareDataToObjValue( | ||
orderProducts, | ||
product, | ||
"shortName" | ||
); | ||
|
||
if (isAlreadyAddedToOrder) { | ||
showWarning("productAlreadyInOrder"); | ||
return; | ||
} | ||
|
||
isProductAlreadyExist ? removeFromCart() : addToCart(); | ||
} | ||
|
||
function showWarning(translateKey) { | ||
dispatch( | ||
showAlert({ | ||
alertText: t(`toastAlert.${translateKey}`), | ||
alertState: "warning", | ||
alertType: "alert", | ||
}) | ||
); | ||
} | ||
|
||
function addToCart() { | ||
const addAction = addToArray({ key: "cartProducts", value: product }); | ||
dispatch(addAction); | ||
setIconName("trashCan"); | ||
} | ||
|
||
function removeFromCart() { | ||
const removeAction = removeByKeyName({ | ||
dataKey: "cartProducts", | ||
itemKey: "shortName", | ||
keyValue: product.shortName, | ||
}); | ||
|
||
dispatch(removeAction); | ||
setIconName("cart3"); | ||
} | ||
|
||
return ( | ||
<button | ||
type="button" | ||
className={`${s.addToCartBtn} ${s.addToCartButton}`} | ||
onClick={handleCartButton} | ||
aria-label={buttonText} | ||
data-add-to-cart-button | ||
> | ||
<SvgIcon name={iconNameState} /> | ||
<span>{buttonText}</span> | ||
</button> | ||
); | ||
}; | ||
export default AddToCartButton; |
54 changes: 54 additions & 0 deletions
54
src/componants/shared/productcard/ProductCard/AddToCartButton/AddToCartButton.module.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
.addToCartBtn { | ||
-webkit-tap-highlight-color: transparent; | ||
border: none; | ||
outline: none; | ||
position: absolute; | ||
left: 0; | ||
bottom: 0; | ||
border-radius: 0 0 4px 4px; | ||
background: var(--black); | ||
width: 100%; | ||
height: 40px; | ||
cursor: pointer; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
transform: translateY(50px); | ||
transition: background .2s, transform .4s .1s; | ||
|
||
&:hover { | ||
background-color: #303030; | ||
} | ||
|
||
&:focus-visible { | ||
transform: translateY(0); | ||
background-color: #303030; | ||
transition: opacity .3s, var(--outline-transition), background .2s, transform 0; | ||
outline: 2px solid var(--yellow); | ||
outline-offset: -2px; | ||
color: var(--yellow); | ||
} | ||
} | ||
|
||
.addToCartBtn>svg { | ||
fill: var(--white); | ||
margin-inline-end: 6px; | ||
width: 19px; | ||
height: 19px; | ||
transition: fill .2s .05s; | ||
} | ||
|
||
.addToCartBtn:hover>svg, | ||
.addToCartBtn:focus-visible>svg { | ||
fill: var(--yellow); | ||
} | ||
|
||
.addToCartBtn>span { | ||
color: var(--white); | ||
transition: color .2s .05s; | ||
} | ||
|
||
.addToCartBtn:hover>span, | ||
.addToCartBtn:focus-visible>span { | ||
color: var(--yellow); | ||
} |
99 changes: 99 additions & 0 deletions
99
src/componants/shared/productcard/ProductCard/ProductCard.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import { useSelector } from "react-redux"; | ||
import { useNavigate } from "react-router-dom"; | ||
import { checkDateBeforeMonthToPresent } from "src/Functions/helper"; | ||
import AddToCartButton from "./AddToCartButton/AddToCartButton"; | ||
import s from "./ProductCard.module.scss"; | ||
import ProductCardIcons from "./ProductCardIcons/ProductCardIcons"; | ||
import ProductCardInfo from "./ProductCardInfo/ProductCardInfo"; | ||
|
||
const ProductCard = ({ | ||
product, | ||
customization = { | ||
stopHover: false, | ||
showDiscount: true, | ||
showFavIcon: true, | ||
showDetailsIcon: true, | ||
showRemoveIcon: false, | ||
showNewText: false, | ||
showWishList: true, | ||
showColors: false, | ||
}, | ||
removeFrom, | ||
loading = "eager", | ||
}) => { | ||
const { name, discount, img, id, addedDate } = product; | ||
const { | ||
stopHover, | ||
showDiscount, | ||
showNewText, | ||
showFavIcon, | ||
showDetailsIcon, | ||
showRemoveIcon, | ||
showWishList, | ||
showColors, | ||
} = customization; | ||
const noHoverClass = stopHover ? s.noHover : ""; | ||
const hideDiscountClass = discount <= 0 || !showDiscount ? s.hide : ""; | ||
const hideNewClass = shouldHideNewWord(); | ||
const { loadingProductDetails } = useSelector((state) => state.loading); | ||
const navigateTo = useNavigate(); | ||
const iconsData = { | ||
showFavIcon, | ||
showDetailsIcon, | ||
showRemoveIcon, | ||
showWishList, | ||
}; | ||
|
||
function shouldHideNewWord() { | ||
return checkDateBeforeMonthToPresent(addedDate) || !showNewText | ||
? s.hide | ||
: ""; | ||
} | ||
|
||
function navigateToProductDetails() { | ||
if (loadingProductDetails) return; | ||
navigateTo(`/details?product=${name.toLowerCase()}`); | ||
} | ||
|
||
return ( | ||
<div className={`${s.card} ${noHoverClass}`}> | ||
<div className={s.productImg}> | ||
<div className={s.imgHolder}> | ||
<img | ||
src={img} | ||
alt={name} | ||
aria-label={name} | ||
loading={loading} | ||
onClick={navigateToProductDetails} | ||
/> | ||
</div> | ||
|
||
<div className={s.layerContent}> | ||
{hideNewClass && ( | ||
<div className={`${s.discount} ${hideDiscountClass}`}> | ||
-{discount}% | ||
</div> | ||
)} | ||
|
||
<div className={`${s.new} ${hideNewClass}`}>New</div> | ||
|
||
<ProductCardIcons | ||
iconsData={iconsData} | ||
productId={id} | ||
navigateToProductDetails={navigateToProductDetails} | ||
product={product} | ||
removeFrom={removeFrom} | ||
/> | ||
<AddToCartButton hoverDataAttribute={true} product={product} /> | ||
</div> | ||
</div> | ||
|
||
<ProductCardInfo | ||
product={product} | ||
showColors={showColors} | ||
navigateToProductDetails={navigateToProductDetails} | ||
/> | ||
</div> | ||
); | ||
}; | ||
export default ProductCard; |
Oops, something went wrong.