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
11 changes: 10 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 29 additions & 5 deletions src/CartItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,53 @@ const CartItem = ({ onContinueShopping }) => {
const cart = useSelector(state => state.cart.items);
const dispatch = useDispatch();

// Calculate total amount for all products in the cart
// Calcule le montant total pour tous les produits dans le panier
const calculateTotalAmount = () => {

// Somme de (prix * quantité) pour chaque article
const total = cart.reduce((sum, it) => {
const price = parseFloat(String(it.cost).replace(/[^0-9.-]+/g, '')) || 0;
const qty = Number(it.quantity) || 0;
return sum + price * qty;
}, 0);
return total.toFixed(2);
};

const handleContinueShopping = (e) => {

e.preventDefault();
if (typeof onContinueShopping === 'function') onContinueShopping();
};



const handleIncrement = (item) => {
const qty = Number(item.quantity) || 0;
dispatch(updateQuantity({ name: item.name, quantity: qty + 1 }));
};

const handleDecrement = (item) => {

const qty = Number(item.quantity) || 0;
if (qty > 1) {
dispatch(updateQuantity({ name: item.name, quantity: qty - 1 }));
} else {
// Si la quantité passe à 0, supprime l'article
dispatch(removeItem(item.name));
}
};

const handleRemove = (item) => {
dispatch(removeItem(item.name));
};

const handleCheckoutShopping = (e) => {
e.preventDefault();
alert('Functionality to be added for future reference');
};

// Calculate total cost based on quantity for an item
const calculateTotalCost = (item) => {
const price = parseFloat(String(item.cost).replace(/[^0-9.-]+/g, '')) || 0;
const qty = Number(item.quantity) || 0;
return (price * qty).toFixed(2);
};

return (
Expand Down Expand Up @@ -57,7 +81,7 @@ const CartItem = ({ onContinueShopping }) => {
<div className="continue_shopping_btn">
<button className="get-started-button" onClick={(e) => handleContinueShopping(e)}>Continue Shopping</button>
<br />
<button className="get-started-button1">Checkout</button>
<button className="get-started-button1" onClick={(e) => handleCheckoutShopping(e)}>Checkout</button>
</div>
</div>
);
Expand Down
28 changes: 25 additions & 3 deletions src/CartSlice.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,39 @@ export const CartSlice = createSlice({
},
reducers: {
addItem: (state, action) => {

// payload is expected to be a product object
const product = action.payload;
// try to find an existing item by name (or you can use an id if available)
const existing = state.items.find((it) => it.name === product.name);
if (existing) {
// if already in cart, increment quantity
existing.quantity = (existing.quantity || 1) + 1;
} else {
// add new item with quantity = 1
state.items.push({ ...product, quantity: 1 });
}
},
removeItem: (state, action) => {
// payload expected to be product name or an identifier
const name = action.payload;
state.items = state.items.filter((it) => it.name !== name);
},
updateQuantity: (state, action) => {


// payload expected to be { name, quantity }
const { name, quantity } = action.payload;
const item = state.items.find((it) => it.name === name);
if (item) {
if (quantity > 0) item.quantity = quantity;
else {
// remove if quantity set to 0 or less
state.items = state.items.filter((it) => it.name !== name);
}
}
},
},
});


export const { addItem, removeItem, updateQuantity } = CartSlice.actions;

export default CartSlice.reducer;
71 changes: 67 additions & 4 deletions src/ProductList.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
import React, { useState, useEffect } from 'react';
import './ProductList.css'
import CartItem from './CartItem';
import { useDispatch, useSelector } from 'react-redux';
import { addItem } from './CartSlice';
function ProductList({ onHomeClick }) {
const [showCart, setShowCart] = useState(false);
const [showPlants, setShowPlants] = useState(false); // State to control the visibility of the About Us page
const [addedToCart, setAddedToCart] = useState({});
const dispatch = useDispatch();
const handleAddToCart = (product) => {
dispatch(addItem(product)); // Dispatch the action to add the product to the cart (Redux action)

setAddedToCart((prevState) => ({ // Update the local state to reflect that the product has been added
...prevState, // Spread the previous state to retain existing entries
[product.name]: true, // Set the current product's name as a key with value 'true' to mark it as added
}));
};

const plantsArray = [
{
Expand Down Expand Up @@ -218,7 +230,7 @@ function ProductList({ onHomeClick }) {
padding: '15px',
display: 'flex',
justifyContent: 'space-between',
alignIems: 'center',
alignItems: 'center',
fontSize: '20px',
}
const styleObjUl = {
Expand Down Expand Up @@ -252,6 +264,9 @@ function ProductList({ onHomeClick }) {
e.preventDefault();
setShowCart(false);
};
// cart items and total count
const cartItems = useSelector((state) => state.cart.items);
const totalCount = cartItems.reduce((sum, it) => sum + (Number(it.quantity) || 0), 0);
return (
<div>
<div className="navbar" style={styleObj}>
Expand All @@ -269,13 +284,61 @@ function ProductList({ onHomeClick }) {
</div>
<div style={styleObjUl}>
<div> <a href="#" onClick={(e) => handlePlantsClick(e)} style={styleA}>Plants</a></div>
<div> <a href="#" onClick={(e) => handleCartClick(e)} style={styleA}><h1 className='cart'><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" id="IconChangeColor" height="68" width="68"><rect width="156" height="156" fill="none"></rect><circle cx="80" cy="216" r="12"></circle><circle cx="184" cy="216" r="12"></circle><path d="M42.3,72H221.7l-26.4,92.4A15.9,15.9,0,0,1,179.9,176H84.1a15.9,15.9,0,0,1-15.4-11.6L32.5,37.8A8,8,0,0,0,24.8,32H8" fill="none" stroke="#faf9f9" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" id="mainIconPathAttribute"></path></svg></h1></a></div>
<div>
<a href="#" onClick={(e) => handleCartClick(e)} style={styleA}>
<div style={{ position: 'relative', display: 'inline-block' }}>
<h1 className='cart'>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" id="IconChangeColor" height="68" width="68"><rect width="156" height="156" fill="none"></rect><circle cx="80" cy="216" r="12"></circle><circle cx="184" cy="216" r="12"></circle><path d="M42.3,72H221.7l-26.4,92.4A15.9,15.9,0,0,1,179.9,176H84.1a15.9,15.9,0,0,1-15.4-11.6L32.5,37.8A8,8,0,0,0,24.8,32H8" fill="none" stroke="#faf9f9" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" id="mainIconPathAttribute"></path></svg>
</h1>
{totalCount > 0 && (
<span style={{
position: 'absolute',
top: 0,
right: 0,
background: 'red',
color: 'white',
borderRadius: '50%',
padding: '4px 7px',
fontSize: '12px'
}}>{totalCount}</span>
)}
</div>
</a>
</div>
</div>
</div>
{!showCart ? (
<div className="product-grid">


{plantsArray.map((category, index) => ( // Loop through each category in plantsArray
<div key={index}> {/* Unique key for each category div */}
<h1>
<div>{category.category}</div> {/* Display the category name */}
</h1>
<div className="product-list"> {/* Container for the list of plant cards */}
{category.plants.map((plant, plantIndex) => ( // Loop through each plant in the current category
<div className="product-card" key={plantIndex}> {/* Unique key for each plant card */}
<img
className="product-image"
src={plant.image} // Display the plant image
alt={plant.name} // Alt text for accessibility
/>
<div className="product-title">{plant.name}</div> {/* Display plant name */}
{/* Display other plant details like description and cost */}
<div className="product-description">{plant.description}</div> {/* Display plant description */}
<div className="product-cost">{plant.cost}</div> {/* Display plant cost */}
<button
className="product-button"
onClick={() => handleAddToCart(plant)} // Handle adding plant to cart
disabled={cartItems.some((it) => it.name === plant.name)}
style={cartItems.some((it) => it.name === plant.name) ? { backgroundColor: '#ccc', cursor: 'not-allowed' } : {}}
>
{cartItems.some((it) => it.name === plant.name) ? 'Ajouté au panier' : 'Ajouter au panier'}
</button>
</div>
))}
</div>
</div>
))}
</div>
) : (
<CartItem onContinueShopping={handleContinueShopping} />
Expand Down