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
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
{
"homepage": "https://cwilliams85216.github.io/e-plantShopping/",
"name": "shoppingcart",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"predeploy": "npm run build",
"deploy": "gh-pages -d dist",
"build": "vite build",
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite build; vite preview --host"

},
"dependencies": {
"@reduxjs/toolkit": "^2.2.3",
Expand Down
38 changes: 30 additions & 8 deletions src/CartItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,55 @@ import { useSelector, useDispatch } from 'react-redux';
import { removeItem, updateQuantity } from './CartSlice';
import './CartItem.css';

const CartItem = ({ onContinueShopping }) => {
const CartItem = ({ onContinueShopping, onItemRemoved }) => {
const cart = useSelector(state => state.cart.items);
const dispatch = useDispatch();

// Calculate total amount for all products in the cart
const calculateTotalAmount = () => {

};
const calculateTotalAmount = (cartItems) => {
return cart.reduce((total, item) => {
// For each item, add its calculated cost to the `total`
return total + calculateTotalCost(item);
}, 0);
};

const handleContinueShopping = (e) => {

onContinueShopping(e);
};


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

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

const handleDecrement = (item) => {

if(item.quantity > 1){
dispatch(updateQuantity({
name: item.name,
quantity: item.quantity - 1
}));
}
else {
dispatch(removeItem({ name: item.name }));
onItemRemoved(item.name);
}
};

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

// Calculate total cost based on quantity for an item
const calculateTotalCost = (item) => {
let totalCost = parseFloat(item.cost.substring(1)) * item.quantity;
return totalCost;
};

return (
Expand Down Expand Up @@ -57,7 +79,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
24 changes: 20 additions & 4 deletions src/CartSlice.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,31 @@ export const CartSlice = createSlice({
},
reducers: {
addItem: (state, action) => {

const { name, image, cost } = action.payload; // Destructure product details from the action payload
// Check if the item already exists in the cart by comparing names
const existingItem = state.items.find(item => item.name === name);
if (existingItem) {
// If item already exists in the cart, increase its quantity
existingItem.quantity++;
} else {
// If item does not exist, add it to the cart with quantity 1
state.items.push({ name, image, cost, quantity: 1 });
}
},
removeItem: (state, action) => {
const { name } = action.payload; // Destructure product details from the action payload
state.items = state.items.filter(item => item.name !== name);
},
updateQuantity: (state, action) => {


updateQuantity: (state, action) => {
const{name, quantity} = action.payload;
// Find the item in the cart that matches the given name
const existingItem = state.items.find(item => item.name === name);
if (existingItem) {
existingItem.quantity = quantity;
}
},
},
},
});

export const { addItem, removeItem, updateQuantity } = CartSlice.actions;
Expand Down
2 changes: 1 addition & 1 deletion src/ProductList.css
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ body {
background-color: #45a049;
}

.product-button.added-to-cart {
.product-button:disabled {
background-color: grey; /* Grey when product is added */
}
@media (max-width: 1200px) {
Expand Down
69 changes: 66 additions & 3 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 { addItem } from './CartSlice';
import { useDispatch, useSelector } from 'react-redux';



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();

// Access the number of items in the cart from Redux store
const cartItems = useSelector((state) => state.cart.items);
const totalItems = cartItems.reduce((total, item) => total + item.quantity, 0);

const plantsArray = [
{
Expand Down Expand Up @@ -252,6 +264,24 @@ function ProductList({ onHomeClick }) {
e.preventDefault();
setShowCart(false);
};

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 handleItemRemoved = (product) => {
setAddedToCart((prevState) => {
const newState = { ...prevState };
delete newState[product];
return newState;
});
};
return (
<div>
<div className="navbar" style={styleObj}>
Expand All @@ -269,16 +299,49 @@ 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}><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>
<span className="cart_quantity_count">{totalItems}</span></h1>
</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 = {addedToCart[plant.name]} // Disable Button after clicked
>
{addedToCart[plant.name] ? 'Added to Cart' : 'Add to Cart'}
</button>
</div>
))}
</div>
</div>
))}

</div>
) : (
<CartItem onContinueShopping={handleContinueShopping} />
<CartItem onContinueShopping={handleContinueShopping}
onItemRemoved={handleItemRemoved}
/>
)}
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion src/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ import cartReducer from './CartSlice';
cart: cartReducer,
},
});
export default store
export default store;
2 changes: 1 addition & 1 deletion vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
base: "/shoppingreact",
base: "/e-plantShopping",
plugins: [react()],
})