Skip to content
Open
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
113 changes: 85 additions & 28 deletions Frontend/src/components/ProductCardCompleteInfo.jsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
import React, {useContext} from "react";
import {ProductsContext} from "../context/ProductsContext.jsx";
import React, { useContext } from "react";
import { ProductsContext } from "../context/ProductsContext.jsx";
import { FaRegTrashAlt, FaTag } from "react-icons/fa";

const _ComboBoxVariants = ({attributesMap, productId}) => {
const _ComboBoxVariants = ({ attributesMap = {}, productId }) => {
const { handleAttributeChange } = useContext(ProductsContext);

// Si no hay attributesMap o está vacío, no renderizamos nada
if (!attributesMap || Object.keys(attributesMap).length === 0) {
return null;
}

return (
<form>
{Object.keys(attributesMap).map(key => (
<div className="bg-transparent flex flex-row justify-between space-x-3" key={key}>
<label>{key}: </label>
<select
className="bg-white" name={key}
onChange={(e) => handleAttributeChange(key+'-'+productId, e.target.value)}>
className="bg-white"
name={key}
onChange={(e) => handleAttributeChange(key+'-'+productId, e.target.value)}
>
<option value="">Select {key}</option>
{attributesMap[key].map(variant => (
<option key={key+variant.attributes[0].value} value={variant.attributes[0].value}>
{attributesMap[key]?.map(variant => (
<option
key={key+variant.attributes[0].value}
value={variant.attributes[0].value}
>
{variant.attributes[0].value}
</option>
))}
Expand All @@ -26,6 +38,17 @@ const _ComboBoxVariants = ({attributesMap, productId}) => {

const ProductCardCompleteInfo = ({ product, onDelete }) => {
const { selectedAttributes, handleIncreaseQuantity, handleDecreaseQuantity } = useContext(ProductsContext);

// Validamos que product tenga todas las propiedades necesarias
if (!product || !product.image || !product.image[0]) {
return null;
}

const priceWithDiscount = product.discountPercentage
? product.price * (1 - product.discountPercentage / 100)
: product.price;

const subtotalWithDiscount = priceWithDiscount * product.quantity;

return (
<div className="flex justify-between p-6 border rounded-lg">
Expand All @@ -34,34 +57,68 @@ const ProductCardCompleteInfo = ({ product, onDelete }) => {
alt={product.name}
width="124"
height="124"
className="object-cover"
/>
<div className="flex flex-row items-center">
<div className="flex flex-col p-6 text-right items-end">
<h4 className="font-bold ">{product.name}</h4>
<_ComboBoxVariants attributesMap={product.attributesMap} productId={product.id}></_ComboBoxVariants>
<h4 className="font-bold">{product.name}</h4>

{/* Solo renderizamos _ComboBoxVariants si product.attributesMap existe */}
{product.attributesMap && (
<_ComboBoxVariants
attributesMap={product.attributesMap}
productId={product.id}
/>
)}

<div className="flex flex-row h-fit justify-between w-20">
<button
className="border border-violet-600 pr-2 pl-2 pt-0.5 pb-0.5 rounded-md"
onClick={() => handleIncreaseQuantity(product.id)}
>+</button>
<label className="font-bold text-lg">{product.quantity}</label>
<button
className="border border-violet-600 pr-2 pl-2 pt-0.5 pb-0.5 rounded-md"
onClick={() => handleDecreaseQuantity(product.id)}
>-</button>
<button
className="border border-violet-600 pr-2 pl-2 pt-0.5 pb-0.5 rounded-md hover:bg-violet-100"
onClick={() => handleIncreaseQuantity(product.id)}
>
+
</button>
<label className="font-bold text-lg">
{product.quantity}
</label>
<button
className="border border-violet-600 pr-2 pl-2 pt-0.5 pb-0.5 rounded-md hover:bg-violet-100"
onClick={() => handleDecreaseQuantity(product.id)}
>
-
</button>
</div>
<p className="text-gray-600">
${product.price.toFixed(2)} x {product.quantity}
</p>
<b>Subtotal: ${product.price * product.quantity}</b>

{product.discountPercentage ? (
<div className="flex flex-col items-end">
<p className="text-gray-600 line-through">
${product.price.toFixed(2)} x {product.quantity}
</p>
<div className="flex items-center text-red-500 text-sm font-bold">
<FaTag className="mr-1" />
{product.discountPercentage}% OFF
</div>
<p className="text-gray-600">
${priceWithDiscount.toFixed(2)} x {product.quantity}
</p>
<b>Subtotal: ${subtotalWithDiscount.toFixed(2)}</b>
</div>
) : (
<div className="flex flex-col items-end">
<p className="text-gray-600">
${product.price.toFixed(2)} x {product.quantity}
</p>
<b>Subtotal: ${(product.price * product.quantity).toFixed(2)}</b>
</div>
)}
</div>
<img
src="https://cdn-icons-png.flaticon.com/512/3405/3405244.png"
alt="Delete icon"
width="24"
height="24"

<button
className="p-2 hover:bg-gray-100 rounded-full"
onClick={onDelete}
/>
>
<FaRegTrashAlt className="w-6 h-6 text-gray-600" />
</button>
</div>
</div>
);
Expand Down
27 changes: 17 additions & 10 deletions Frontend/src/components/ShoppingCart.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { ProductsContext } from "../context/ProductsContext";

export function ShoppingCart() {
const [isOpen, setIsOpen] = useState(false);

const { products } = useContext(ProductsContext);

const openMenu = () => {
Expand Down Expand Up @@ -37,20 +36,28 @@ export function ShoppingCart() {
image={item.image[0].url}
quantity={item.quantity}
isAvailableStock={item.stock > item.quantity}
discountPercentage={item.discountPercentage || 0}
priceWithDiscount={
item.discountPercentage
? item.price * (1 - item.discountPercentage / 100)
: item.price
}
/>
))
)
}
</div>
<a href={products.length > 0 ? "/complete-order" : "#"} className={`shopping-cart-go-button ${products.length > 0 ? 'active' : 'disabled'}`}>

{products.length > 0 ? (
<>
<FaShoppingCart /> Go to checkout
</>
) : (
"Add items to cart"
)}
<a
href={products.length > 0 ? "/complete-order" : "#"}
className={`shopping-cart-go-button ${products.length > 0 ? 'active' : 'disabled'}`}
>
{products.length > 0 ? (
<>
<FaShoppingCart /> Go to checkout
</>
) : (
"Add items to cart"
)}
</a>
</div>
</>
Expand Down
75 changes: 52 additions & 23 deletions Frontend/src/components/ShoppingCartItem.jsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,64 @@
import PropTypes from "prop-types";
import '../styles/components/shoppingCartItem.css';
import { FaRegTrashAlt } from "react-icons/fa";
import { FaRegTrashAlt, FaTag } from "react-icons/fa";
import { StockQuantityInput } from "./StockQuantityInput";
import { useContext } from "react";
import { ProductsContext } from "../context/ProductsContext";

export function ShoppingCartItem({
id,
name,
image,
price,
quantity,
isAvailableStock,
discountPercentage,
priceWithDiscount
}) {
const { removeProductById, handleDecreaseQuantity, handleIncreaseQuantity } = useContext(ProductsContext);

export function ShoppingCartItem({ id, name, image, price, quantity , isAvailableStock}) {
const { removeProductById, handleDecreaseQuantity, handleIncreaseQuantity } = useContext(ProductsContext);
return (
<div className="shopping-cart-item">
<img src={image} alt={`Product item ${name}`} className="shopping-cart-item-image" />
<div className="shopping-cart-item-information">
<p className="shopping-cart-item-name">{name}</p>
{discountPercentage > 0 ? (
<div className="shopping-cart-item-price-container">
<p className="shopping-cart-item-original-price">${price.toFixed(2)}</p>
<p className="shopping-cart-item-discount">
<FaTag className="discount-icon" /> {discountPercentage}% OFF
</p>
<p className="shopping-cart-item-final-price">${priceWithDiscount.toFixed(2)}</p>
</div>
) : (
<p className="shopping-cart-item-price">${price.toFixed(2)}</p>
)}
</div>

return (
<div className="shopping-cart-item">
<img src={image} alt={`Product item ${name}`} className="shopping-cart-item-image" />
<div className="shopping-cart-item-information">
<p className="shopping-cart-item-name">{name}</p>
<p className="shopping-cart-item-price">${price.toFixed(2)}</p>
</div>


<StockQuantityInput id={id} quantity={quantity} increse={handleIncreaseQuantity} decrese={handleDecreaseQuantity} isAvailableStock={isAvailableStock} />
<button className="shopping-cart-item-delete-to-cart" onClick={() => removeProductById(id)}>
<FaRegTrashAlt />
</button>
</div>
);
<StockQuantityInput
id={id}
quantity={quantity}
increse={handleIncreaseQuantity}
decrese={handleDecreaseQuantity}
isAvailableStock={isAvailableStock}
/>
<button
className="shopping-cart-item-delete-to-cart"
onClick={() => removeProductById(id)}
>
<FaRegTrashAlt />
</button>
</div>
);
}

ShoppingCartItem.propTypes = {
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
image: PropTypes.string.isRequired,
price: PropTypes.number.isRequired,
quantity: PropTypes.number.isRequired
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
image: PropTypes.string.isRequired,
price: PropTypes.number.isRequired,
quantity: PropTypes.number.isRequired,
isAvailableStock: PropTypes.bool.isRequired,
discountPercentage: PropTypes.number,
priceWithDiscount: PropTypes.number
};
Loading