Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
innovatixhub authored Nov 25, 2024
1 parent a0f3b7d commit 28edbdd
Show file tree
Hide file tree
Showing 6 changed files with 320 additions and 0 deletions.
56 changes: 56 additions & 0 deletions src/componants/cart/cartproduct/CartProduct.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";
import CustomNumberInput from "../../Shared/MiniComponents/CustomNumberInput/CustomNumberInput";
import s from "./CartProduct.module.scss";
import RemoveCartProductBtn from "./RemoveCartProductBtn";

const CartProduct = ({ data }) => {
const { img, name, shortName, afterDiscount, quantity, id } = data;
const priceAfterDiscount = afterDiscount.replaceAll(",", "");
const subTotal = (quantity * priceAfterDiscount).toFixed(2);
const { t } = useTranslation();

const translatedProductName = translateProduct({
productName: shortName,
translateMethod: t,
translateKey: "shortName",
});

return (
<tr className={s.productContainer}>
<td className={s.product}>
<div className={s.imgHolder}>
<img src={img} alt={`${shortName} product`} />
<RemoveCartProductBtn productId={id} />
</div>

<Link to={`/details?product=${name}`}>{translatedProductName}</Link>
</td>

<td className={s.price}>${afterDiscount}</td>

<td>
<CustomNumberInput product={data} quantity={quantity} />
</td>

<td>${subTotal}</td>
</tr>
);
};
export default CartProduct;

export function translateProduct({
productName,
translateMethod,
translateKey,
uppercase = false,
dynamicData = {},
}) {
const shortNameKey = productName?.replaceAll(" ", "");
const productTrans = `products.${shortNameKey}`;
const translateText = translateMethod(
`${productTrans}.${translateKey}`,
dynamicData
);
return uppercase ? translateText.toUpperCase() : translateText;
}
47 changes: 47 additions & 0 deletions src/componants/cart/cartproduct/CartProduct.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
@import "src/Styles/mixins";

.productContainer {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}

.product {
display: flex;
align-items: center;
width: 260px !important;
}

@include very-small {
.product {
width: 100% !important;
}
}

.imgHolder {
width: fit-content;
height: fit-content;
user-select: none;
position: relative;
}

.product a {
outline: none;
color: var(--black);
transition: color .1s;
text-wrap: balance;

&:hover {
color: var(--dark-gray);
}

&:focus-visible {
color: var(--orange-degree2);
}
}

.product img {
width: 54px;
margin-inline-end: 20px;
}
30 changes: 30 additions & 0 deletions src/componants/cart/cartproduct/CartProducts.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useTranslation } from "react-i18next";
import { useSelector } from "react-redux";
import CartProduct from "./CartProduct";
import s from "./CartProducts.module.scss";

const CartProducts = () => {
const { t } = useTranslation();
const { cartProducts } = useSelector((state) => state.products);
const productsTable = "cartPage.productsTable";

return (
<table className={s.cartProducts}>
<thead>
<tr>
<th>{t(`${productsTable}.product`)}</th>
<th>{t(`${productsTable}.price`)}</th>
<th>{t(`${productsTable}.quantity`)}</th>
<th>{t(`${productsTable}.subtotal`)}</th>
</tr>
</thead>

<tbody>
{cartProducts.map((product) => (
<CartProduct key={product.id} data={product} />
))}
</tbody>
</table>
);
};
export default CartProducts;
99 changes: 99 additions & 0 deletions src/componants/cart/cartproduct/CartProducts.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
@import "src/Styles/mixins";

.cartProducts {
width: 100%;
min-height: 370px;
}

@include small {
.cartProducts {
min-height: 270px;
}
}

.cartProducts tr {
box-shadow: 0 1px 13px 0 #0000000D;
border-radius: 4px;
padding: 24px 40px;
}

@include small {
.cartProducts tr {
padding: 20px;
display: flex;
flex-direction: column;
align-items: center;
width: fit-content;
}
}

@include small {
.cartProducts thead {
display: none;
}
}

.cartProducts thead tr {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 50px;
}

.cartProducts thead tr th {
display: inline-block;
width: 100px;
text-align: start;

&:first-child {
width: 260px;
}
}

.cartProducts tbody {
display: flex;
flex-direction: column;
gap: 40px;
}

@include small {
.cartProducts tbody {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
}

@include small {
.cartProducts tbody tr {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
min-width: 310px;
width: calc(50% - 20px);
}
}

@media (max-width: 520px) {
.cartProducts tbody tr {
min-width: 100%;
width: 100%;
}
}

.cartProducts tbody>tr>td {
width: 100px;
}

@include small {
.cartProducts tbody tr td {
@include center-x-y;
}
}

@include very-small {
.cartProducts tbody tr td {
justify-content: flex-start;
}
}
56 changes: 56 additions & 0 deletions src/componants/cart/cartproduct/RemoveCartProductBtn.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { useDispatch } from "react-redux";
import { SCREEN_SIZES } from "src/Data/globalVariables";
import { removeById } from "src/Features/productsSlice";
import { cartProductToolTipPos } from "src/Functions/componentsFunctions";
import useGetResizeWindow from "src/Hooks/Helper/useGetResizeWindow";
import SvgIcon from "../../Shared/MiniComponents/SvgIcon";
import ToolTip from "../../Shared/MiniComponents/ToolTip";
import s from "./RemoveCartProductBtn.module.scss";

const RemoveCartProductBtn = ({ productId }) => {
const dispatch = useDispatch();
const { t, i18n } = useTranslation();
const { windowWidth } = useGetResizeWindow();

const [toolTipLeftPos, setToolTipLeftPos] = useState(cartProductToolTipPos(i18n.language));
const [toolTipTopPos, setToolTipTopPos] = useState("50%");

function updateToolTipPositions() {
if (windowWidth <= SCREEN_SIZES.laptop) {
setToolTipLeftPos("50%");
setToolTipTopPos("-20px");
return;
}

setToolTipLeftPos(cartProductToolTipPos(i18n.language));
setToolTipTopPos("50%");
}

useEffect(() => {
updateToolTipPositions();
}, [windowWidth, i18n.language]);

return (
<button
type="button"
className={s.removeButton}
aria-label="Remove product from cart"
onClick={() => removeProduct(dispatch, productId)}
>
<SvgIcon name="xMark" />
<ToolTip
top={toolTipTopPos}
left={toolTipLeftPos}
content={t("tooltips.remove")}
/>
</button>
);
};
export default RemoveCartProductBtn;

function removeProduct(dispatch, productId) {
const removeAction = removeById({ key: "cartProducts", id: productId });
dispatch(removeAction);
}
32 changes: 32 additions & 0 deletions src/componants/cart/cartproduct/RemoveCartProductBtn.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
.removeButton {
-webkit-tap-highlight-color: transparent;
border: none;
outline: none;
background-color: var(--tomato);
width: 18px;
height: 18px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 0;
left: 0;
cursor: pointer;

&:focus-visible [data-is-tooltip=true] {
opacity: 1;
}
}

.removeButton>svg {
width: 12px;
height: 12px;
fill: var(--white)
}

// Arabic styles
[lang=ar] .removeButton {
left: auto;
right: 0;
}

0 comments on commit 28edbdd

Please sign in to comment.