From ff572a908369b70dea4f3ddc2b93a076e08b1fd3 Mon Sep 17 00:00:00 2001 From: ximenabaquero Date: Fri, 29 Aug 2025 17:12:04 -0500 Subject: [PATCH 1/7] Update CartSlice.jsx --- src/CartSlice.jsx | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/CartSlice.jsx b/src/CartSlice.jsx index 32b8761ed0..30048783d4 100644 --- a/src/CartSlice.jsx +++ b/src/CartSlice.jsx @@ -1,23 +1,40 @@ -import { createSlice } from '@reduxjs/toolkit'; +import { createSlice } from "@reduxjs/toolkit"; export const CartSlice = createSlice({ - name: 'cart', + name: "cart", initialState: { - items: [], // Initialize items as an empty array + items: [], // cada ítem será { id, name, image, description, cost, qty } }, reducers: { addItem: (state, action) => { - + const plant = action.payload; + const existing = state.items.find((item) => item.id === plant.id); + if (existing) { + existing.qty += 1; // si ya existe, aumenta cantidad + } else { + state.items.push({ ...plant, qty: 1 }); // si no existe, lo agrega con qty=1 + } }, removeItem: (state, action) => { + const id = action.payload; + state.items = state.items.filter((item) => item.id !== id); }, updateQuantity: (state, action) => { - - + const { id, qty } = action.payload; + const item = state.items.find((i) => i.id === id); + if (item) { + item.qty = qty; + } }, + clearCart: (state) => { + state.items = []; + } }, }); -export const { addItem, removeItem, updateQuantity } = CartSlice.actions; +// Exporta las acciones +export const { addItem, removeItem, updateQuantity, clearCart } = CartSlice.actions; +// Exporta el reducer export default CartSlice.reducer; + From 7f21c356e0a5fad0205291025eee9467de628777 Mon Sep 17 00:00:00 2001 From: ximenabaquero Date: Thu, 4 Sep 2025 14:18:17 -0500 Subject: [PATCH 2/7] =?UTF-8?q?Agrega=20ids=20=C3=BAnicos=20a=20cada=20pla?= =?UTF-8?q?nta=20y=20funcionalidad=20de=20agregar=20al=20carrito?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ProductList.jsx | 72 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 2 deletions(-) diff --git a/src/ProductList.jsx b/src/ProductList.jsx index 7682c04fc4..5021c5b95a 100644 --- a/src/ProductList.jsx +++ b/src/ProductList.jsx @@ -1,45 +1,55 @@ import React, { useState, useEffect } from 'react'; +import { useDispatch } from 'react-redux'; // <-- Agrega esto +import { addItem } from './CartSlice'; // <-- Asegúrate que la ruta sea correcta import './ProductList.css' import CartItem from './CartItem'; function ProductList({ onHomeClick }) { + const dispatch = useDispatch(); // <-- Agrega esto const [showCart, setShowCart] = useState(false); const [showPlants, setShowPlants] = useState(false); // State to control the visibility of the About Us page + const [addedToCart, setAddedToCart] = useState({}); // <-- Agrega esto const plantsArray = [ { category: "Air Purifying Plants", plants: [ { + id: "snake-plant-1", name: "Snake Plant", image: "https://cdn.pixabay.com/photo/2021/01/22/06/04/snake-plant-5939187_1280.jpg", description: "Produces oxygen at night, improving air quality.", cost: "$15" }, { + id: "spider-plant-1", name: "Spider Plant", image: "https://cdn.pixabay.com/photo/2018/07/11/06/47/chlorophytum-3530413_1280.jpg", description: "Filters formaldehyde and xylene from the air.", cost: "$12" }, { + id: "peace-lily-1", name: "Peace Lily", image: "https://cdn.pixabay.com/photo/2019/06/12/14/14/peace-lilies-4269365_1280.jpg", description: "Removes mold spores and purifies the air.", cost: "$18" }, { + id: "boston-fern-1", name: "Boston Fern", image: "https://cdn.pixabay.com/photo/2020/04/30/19/52/boston-fern-5114414_1280.jpg", description: "Adds humidity to the air and removes toxins.", cost: "$20" }, { + id: "rubber-plant-1", name: "Rubber Plant", image: "https://cdn.pixabay.com/photo/2020/02/15/11/49/flower-4850729_1280.jpg", description: "Easy to care for and effective at removing toxins.", cost: "$17" }, { + id: "aloe-vera-1", name: "Aloe Vera", image: "https://cdn.pixabay.com/photo/2018/04/02/07/42/leaf-3283175_1280.jpg", description: "Purifies the air and has healing properties for skin.", @@ -51,36 +61,42 @@ function ProductList({ onHomeClick }) { category: "Aromatic Fragrant Plants", plants: [ { + id: "lavender-1", name: "Lavender", image: "https://images.unsplash.com/photo-1611909023032-2d6b3134ecba?q=80&w=1074&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", description: "Calming scent, used in aromatherapy.", cost: "$20" }, { + id: "jasmine-1", name: "Jasmine", image: "https://images.unsplash.com/photo-1592729645009-b96d1e63d14b?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", description: "Sweet fragrance, promotes relaxation.", cost: "$18" }, { + id: "rosemary-1", name: "Rosemary", image: "https://cdn.pixabay.com/photo/2019/10/11/07/12/rosemary-4541241_1280.jpg", description: "Invigorating scent, often used in cooking.", cost: "$15" }, { + id: "mint-1", name: "Mint", image: "https://cdn.pixabay.com/photo/2016/01/07/18/16/mint-1126282_1280.jpg", description: "Refreshing aroma, used in teas and cooking.", cost: "$12" }, { + id: "lemon-balm-1", name: "Lemon Balm", image: "https://cdn.pixabay.com/photo/2019/09/16/07/41/balm-4480134_1280.jpg", description: "Citrusy scent, relieves stress and promotes sleep.", cost: "$14" }, { + id: "hyacinth-1", name: "Hyacinth", image: "https://cdn.pixabay.com/photo/2019/04/07/20/20/hyacinth-4110726_1280.jpg", description: "Hyacinth is a beautiful flowering plant known for its fragrant.", @@ -92,36 +108,42 @@ function ProductList({ onHomeClick }) { category: "Insect Repellent Plants", plants: [ { + id: "oregano-1", name: "oregano", image: "https://cdn.pixabay.com/photo/2015/05/30/21/20/oregano-790702_1280.jpg", description: "The oregano plants contains compounds that can deter certain insects.", cost: "$10" }, { + id: "marigold-1", name: "Marigold", image: "https://cdn.pixabay.com/photo/2022/02/22/05/45/marigold-7028063_1280.jpg", description: "Natural insect repellent, also adds color to the garden.", cost: "$8" }, { + id: "geraniums-1", name: "Geraniums", image: "https://cdn.pixabay.com/photo/2012/04/26/21/51/flowerpot-43270_1280.jpg", description: "Known for their insect-repelling properties while adding a pleasant scent.", cost: "$20" }, { + id: "basil-1", name: "Basil", image: "https://cdn.pixabay.com/photo/2016/07/24/20/48/tulsi-1539181_1280.jpg", description: "Repels flies and mosquitoes, also used in cooking.", cost: "$9" }, { + id: "lavender-2", name: "Lavender", image: "https://images.unsplash.com/photo-1611909023032-2d6b3134ecba?q=80&w=1074&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", description: "Calming scent, used in aromatherapy.", cost: "$20" }, { + id: "catnip-1", name: "Catnip", image: "https://cdn.pixabay.com/photo/2015/07/02/21/55/cat-829681_1280.jpg", description: "Repels mosquitoes and attracts cats.", @@ -133,36 +155,42 @@ function ProductList({ onHomeClick }) { category: "Medicinal Plants", plants: [ { + id: "aloe-vera-2", name: "Aloe Vera", image: "https://cdn.pixabay.com/photo/2018/04/02/07/42/leaf-3283175_1280.jpg", description: "Soothing gel used for skin ailments.", cost: "$14" }, { + id: "echinacea-1", name: "Echinacea", image: "https://cdn.pixabay.com/photo/2014/12/05/03/53/echinacea-557477_1280.jpg", description: "Boosts immune system, helps fight colds.", cost: "$16" }, { + id: "peppermint-1", name: "Peppermint", image: "https://cdn.pixabay.com/photo/2017/07/12/12/23/peppermint-2496773_1280.jpg", description: "Relieves digestive issues and headaches.", cost: "$13" }, { + id: "lemon-balm-2", name: "Lemon Balm", image: "https://cdn.pixabay.com/photo/2019/09/16/07/41/balm-4480134_1280.jpg", description: "Calms nerves and promotes relaxation.", cost: "$14" }, { + id: "chamomile-1", name: "Chamomile", image: "https://cdn.pixabay.com/photo/2016/08/19/19/48/flowers-1606041_1280.jpg", description: "Soothes anxiety and promotes sleep.", cost: "$15" }, { + id: "calendula-1", name: "Calendula", image: "https://cdn.pixabay.com/photo/2019/07/15/18/28/flowers-4340127_1280.jpg", description: "Heals wounds and soothes skin irritations.", @@ -174,36 +202,42 @@ function ProductList({ onHomeClick }) { category: "Low Maintenance Plants", plants: [ { + id: "zz-plant-1", name: "ZZ Plant", image: "https://images.unsplash.com/photo-1632207691143-643e2a9a9361?q=80&w=464&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", description: "Thrives in low light and requires minimal watering.", cost: "$25" }, { + id: "pothos-1", name: "Pothos", image: "https://cdn.pixabay.com/photo/2018/11/15/10/32/plants-3816945_1280.jpg", description: "Tolerates neglect and can grow in various conditions.", cost: "$10" }, { + id: "snake-plant-2", name: "Snake Plant", image: "https://cdn.pixabay.com/photo/2021/01/22/06/04/snake-plant-5939187_1280.jpg", description: "Needs infrequent watering and is resilient to most pests.", cost: "$15" }, { + id: "cast-iron-plant-1", name: "Cast Iron Plant", image: "https://cdn.pixabay.com/photo/2017/02/16/18/04/cast-iron-plant-2072008_1280.jpg", description: "Hardy plant that tolerates low light and neglect.", cost: "$20" }, { + id: "succulents-1", name: "Succulents", image: "https://cdn.pixabay.com/photo/2016/11/21/16/05/cacti-1846147_1280.jpg", description: "Drought-tolerant plants with unique shapes and colors.", cost: "$18" }, { + id: "aglaonema-1", name: "Aglaonema", image: "https://cdn.pixabay.com/photo/2014/10/10/04/27/aglaonema-482915_1280.jpg", description: "Requires minimal care and adds color to indoor spaces.", @@ -252,6 +286,15 @@ function ProductList({ onHomeClick }) { e.preventDefault(); setShowCart(false); }; + + const handleAddToCart = (plant) => { + dispatch(addItem(plant)); // Despacha la acción para agregar la planta al carrito + setAddedToCart((prevState) => ({ + ...prevState, + [plant.name]: true, // Marca la planta como añadida en el estado local + })); + }; + return (
@@ -274,8 +317,33 @@ function ProductList({ onHomeClick }) {
{!showCart ? (
- - + {plantsArray.map((category, index) => ( +
+

+
{category.category}
+

+
+ {category.plants.map((plant, plantIndex) => ( +
+ {plant.name} +
{plant.name}
+
{plant.description}
+
{plant.cost}
+ +
+ ))} +
+
+ ))}
) : ( From 3b3ca60973ac77e08bac64af763643a0e385f188 Mon Sep 17 00:00:00 2001 From: ximenabaquero Date: Thu, 4 Sep 2025 16:28:21 -0500 Subject: [PATCH 3/7] =?UTF-8?q?Arregla=20CartSlice,=20ProductList=20y=20Ca?= =?UTF-8?q?rtItem:=20a=C3=B1adir/eliminar/actualizar=20carrito?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CartItem.jsx | 27 +- src/CartSlice.jsx | 43 +-- src/ProductList.jsx | 692 ++++++++++++++++++++++---------------------- src/store.js | 14 +- 4 files changed, 405 insertions(+), 371 deletions(-) diff --git a/src/CartItem.jsx b/src/CartItem.jsx index e06317433f..bcac731860 100644 --- a/src/CartItem.jsx +++ b/src/CartItem.jsx @@ -4,32 +4,47 @@ import { removeItem, updateQuantity } from './CartSlice'; import './CartItem.css'; const CartItem = ({ onContinueShopping }) => { - const cart = useSelector(state => state.cart.items); + const cart = useSelector(state => state.cart?.items ?? []); const dispatch = useDispatch(); // Calculate total amount for all products in the cart const calculateTotalAmount = () => { - + let total = 0; + cart.forEach(item => { + const qty = item.quantity ?? item.qty ?? 0; + const price = item.cost ? parseFloat(String(item.cost).replace(/[^0-9.-]+/g, '')) : 0; + total += price * qty; + }); + return total.toFixed(2); }; const handleContinueShopping = (e) => { - + if (onContinueShopping) onContinueShopping(e); }; - - const handleIncrement = (item) => { + const current = item.quantity ?? item.qty ?? 0; + dispatch(updateQuantity({ name: item.name, quantity: current + 1 })); }; const handleDecrement = (item) => { - + const current = item.quantity ?? item.qty ?? 0; + if (current > 1) { + dispatch(updateQuantity({ name: item.name, quantity: current - 1 })); + } else { + dispatch(removeItem(item.name)); + } }; const handleRemove = (item) => { + dispatch(removeItem(item.name)); }; // Calculate total cost based on quantity for an item const calculateTotalCost = (item) => { + const qty = item.quantity ?? item.qty ?? 0; + const price = item.cost ? parseFloat(String(item.cost).replace(/[^0-9.-]+/g, '')) : 0; + return (price * qty).toFixed(2); }; return ( diff --git a/src/CartSlice.jsx b/src/CartSlice.jsx index 30048783d4..f20797a2ae 100644 --- a/src/CartSlice.jsx +++ b/src/CartSlice.jsx @@ -1,40 +1,49 @@ import { createSlice } from "@reduxjs/toolkit"; +const initialState = { items: [] }; + export const CartSlice = createSlice({ name: "cart", - initialState: { - items: [], // cada ítem será { id, name, image, description, cost, qty } - }, + initialState, reducers: { addItem: (state, action) => { - const plant = action.payload; - const existing = state.items.find((item) => item.id === plant.id); + const p = action.payload; + const id = p.id ?? p.name; + const existing = state.items.find((i) => i.id === id || i.name === id); if (existing) { - existing.qty += 1; // si ya existe, aumenta cantidad + existing.qty = (existing.qty ?? existing.quantity ?? 0) + (p.qty ?? 1); + existing.quantity = existing.qty; } else { - state.items.push({ ...plant, qty: 1 }); // si no existe, lo agrega con qty=1 + state.items.push({ + id, + name: p.name, + image: p.image ?? "", + cost: p.cost ?? "$0", + qty: p.qty ?? 1, + quantity: p.qty ?? 1, + }); } }, + removeItem: (state, action) => { - const id = action.payload; - state.items = state.items.filter((item) => item.id !== id); + state.items = state.items.filter((item) => item.name !== action.payload); }, + updateQuantity: (state, action) => { - const { id, qty } = action.payload; - const item = state.items.find((i) => i.id === id); - if (item) { - item.qty = qty; + const { name, quantity } = action.payload; // Destructure product name and new quantity + const itemToUpdate = state.items.find((item) => item.name === name); + if (itemToUpdate) { + itemToUpdate.quantity = quantity; // Actualiza quantity + itemToUpdate.qty = quantity; // Mantener compatibilidad con `qty` si se usa en otras partes } }, + clearCart: (state) => { state.items = []; - } + }, }, }); -// Exporta las acciones export const { addItem, removeItem, updateQuantity, clearCart } = CartSlice.actions; - -// Exporta el reducer export default CartSlice.reducer; diff --git a/src/ProductList.jsx b/src/ProductList.jsx index 5021c5b95a..660adaebdd 100644 --- a/src/ProductList.jsx +++ b/src/ProductList.jsx @@ -1,355 +1,365 @@ import React, { useState, useEffect } from 'react'; -import { useDispatch } from 'react-redux'; // <-- Agrega esto -import { addItem } from './CartSlice'; // <-- Asegúrate que la ruta sea correcta +import { useDispatch, useSelector } from 'react-redux'; // <-- Agrega esto +import { addItem } from './CartSlice'; import './ProductList.css' import CartItem from './CartItem'; function ProductList({ onHomeClick }) { - const dispatch = useDispatch(); // <-- Agrega esto - const [showCart, setShowCart] = useState(false); - const [showPlants, setShowPlants] = useState(false); // State to control the visibility of the About Us page - const [addedToCart, setAddedToCart] = useState({}); // <-- Agrega esto + const dispatch = useDispatch(); + const cartItems = useSelector(state => state.cart?.items ?? []); + const [showCart, setShowCart] = useState(false); + const [showPlants, setShowPlants] = useState(false); - const plantsArray = [ - { - category: "Air Purifying Plants", - plants: [ - { - id: "snake-plant-1", - name: "Snake Plant", - image: "https://cdn.pixabay.com/photo/2021/01/22/06/04/snake-plant-5939187_1280.jpg", - description: "Produces oxygen at night, improving air quality.", - cost: "$15" - }, - { - id: "spider-plant-1", - name: "Spider Plant", - image: "https://cdn.pixabay.com/photo/2018/07/11/06/47/chlorophytum-3530413_1280.jpg", - description: "Filters formaldehyde and xylene from the air.", - cost: "$12" - }, - { - id: "peace-lily-1", - name: "Peace Lily", - image: "https://cdn.pixabay.com/photo/2019/06/12/14/14/peace-lilies-4269365_1280.jpg", - description: "Removes mold spores and purifies the air.", - cost: "$18" - }, - { - id: "boston-fern-1", - name: "Boston Fern", - image: "https://cdn.pixabay.com/photo/2020/04/30/19/52/boston-fern-5114414_1280.jpg", - description: "Adds humidity to the air and removes toxins.", - cost: "$20" - }, - { - id: "rubber-plant-1", - name: "Rubber Plant", - image: "https://cdn.pixabay.com/photo/2020/02/15/11/49/flower-4850729_1280.jpg", - description: "Easy to care for and effective at removing toxins.", - cost: "$17" - }, - { - id: "aloe-vera-1", - name: "Aloe Vera", - image: "https://cdn.pixabay.com/photo/2018/04/02/07/42/leaf-3283175_1280.jpg", - description: "Purifies the air and has healing properties for skin.", - cost: "$14" - } - ] - }, - { - category: "Aromatic Fragrant Plants", - plants: [ - { - id: "lavender-1", - name: "Lavender", - image: "https://images.unsplash.com/photo-1611909023032-2d6b3134ecba?q=80&w=1074&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", - description: "Calming scent, used in aromatherapy.", - cost: "$20" - }, - { - id: "jasmine-1", - name: "Jasmine", - image: "https://images.unsplash.com/photo-1592729645009-b96d1e63d14b?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", - description: "Sweet fragrance, promotes relaxation.", - cost: "$18" - }, - { - id: "rosemary-1", - name: "Rosemary", - image: "https://cdn.pixabay.com/photo/2019/10/11/07/12/rosemary-4541241_1280.jpg", - description: "Invigorating scent, often used in cooking.", - cost: "$15" - }, - { - id: "mint-1", - name: "Mint", - image: "https://cdn.pixabay.com/photo/2016/01/07/18/16/mint-1126282_1280.jpg", - description: "Refreshing aroma, used in teas and cooking.", - cost: "$12" - }, - { - id: "lemon-balm-1", - name: "Lemon Balm", - image: "https://cdn.pixabay.com/photo/2019/09/16/07/41/balm-4480134_1280.jpg", - description: "Citrusy scent, relieves stress and promotes sleep.", - cost: "$14" - }, - { - id: "hyacinth-1", - name: "Hyacinth", - image: "https://cdn.pixabay.com/photo/2019/04/07/20/20/hyacinth-4110726_1280.jpg", - description: "Hyacinth is a beautiful flowering plant known for its fragrant.", - cost: "$22" - } - ] - }, - { - category: "Insect Repellent Plants", - plants: [ - { - id: "oregano-1", - name: "oregano", - image: "https://cdn.pixabay.com/photo/2015/05/30/21/20/oregano-790702_1280.jpg", - description: "The oregano plants contains compounds that can deter certain insects.", - cost: "$10" - }, - { - id: "marigold-1", - name: "Marigold", - image: "https://cdn.pixabay.com/photo/2022/02/22/05/45/marigold-7028063_1280.jpg", - description: "Natural insect repellent, also adds color to the garden.", - cost: "$8" - }, - { - id: "geraniums-1", - name: "Geraniums", - image: "https://cdn.pixabay.com/photo/2012/04/26/21/51/flowerpot-43270_1280.jpg", - description: "Known for their insect-repelling properties while adding a pleasant scent.", - cost: "$20" - }, - { - id: "basil-1", - name: "Basil", - image: "https://cdn.pixabay.com/photo/2016/07/24/20/48/tulsi-1539181_1280.jpg", - description: "Repels flies and mosquitoes, also used in cooking.", - cost: "$9" - }, - { - id: "lavender-2", - name: "Lavender", - image: "https://images.unsplash.com/photo-1611909023032-2d6b3134ecba?q=80&w=1074&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", - description: "Calming scent, used in aromatherapy.", - cost: "$20" - }, - { - id: "catnip-1", - name: "Catnip", - image: "https://cdn.pixabay.com/photo/2015/07/02/21/55/cat-829681_1280.jpg", - description: "Repels mosquitoes and attracts cats.", - cost: "$13" - } - ] - }, - { - category: "Medicinal Plants", - plants: [ - { - id: "aloe-vera-2", - name: "Aloe Vera", - image: "https://cdn.pixabay.com/photo/2018/04/02/07/42/leaf-3283175_1280.jpg", - description: "Soothing gel used for skin ailments.", - cost: "$14" - }, - { - id: "echinacea-1", - name: "Echinacea", - image: "https://cdn.pixabay.com/photo/2014/12/05/03/53/echinacea-557477_1280.jpg", - description: "Boosts immune system, helps fight colds.", - cost: "$16" - }, - { - id: "peppermint-1", - name: "Peppermint", - image: "https://cdn.pixabay.com/photo/2017/07/12/12/23/peppermint-2496773_1280.jpg", - description: "Relieves digestive issues and headaches.", - cost: "$13" - }, - { - id: "lemon-balm-2", - name: "Lemon Balm", - image: "https://cdn.pixabay.com/photo/2019/09/16/07/41/balm-4480134_1280.jpg", - description: "Calms nerves and promotes relaxation.", - cost: "$14" - }, - { - id: "chamomile-1", - name: "Chamomile", - image: "https://cdn.pixabay.com/photo/2016/08/19/19/48/flowers-1606041_1280.jpg", - description: "Soothes anxiety and promotes sleep.", - cost: "$15" - }, - { - id: "calendula-1", - name: "Calendula", - image: "https://cdn.pixabay.com/photo/2019/07/15/18/28/flowers-4340127_1280.jpg", - description: "Heals wounds and soothes skin irritations.", - cost: "$12" - } - ] - }, - { - category: "Low Maintenance Plants", - plants: [ - { - id: "zz-plant-1", - name: "ZZ Plant", - image: "https://images.unsplash.com/photo-1632207691143-643e2a9a9361?q=80&w=464&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", - description: "Thrives in low light and requires minimal watering.", - cost: "$25" - }, - { - id: "pothos-1", - name: "Pothos", - image: "https://cdn.pixabay.com/photo/2018/11/15/10/32/plants-3816945_1280.jpg", - description: "Tolerates neglect and can grow in various conditions.", - cost: "$10" - }, - { - id: "snake-plant-2", - name: "Snake Plant", - image: "https://cdn.pixabay.com/photo/2021/01/22/06/04/snake-plant-5939187_1280.jpg", - description: "Needs infrequent watering and is resilient to most pests.", - cost: "$15" - }, - { - id: "cast-iron-plant-1", - name: "Cast Iron Plant", - image: "https://cdn.pixabay.com/photo/2017/02/16/18/04/cast-iron-plant-2072008_1280.jpg", - description: "Hardy plant that tolerates low light and neglect.", - cost: "$20" - }, - { - id: "succulents-1", - name: "Succulents", - image: "https://cdn.pixabay.com/photo/2016/11/21/16/05/cacti-1846147_1280.jpg", - description: "Drought-tolerant plants with unique shapes and colors.", - cost: "$18" - }, - { - id: "aglaonema-1", - name: "Aglaonema", - image: "https://cdn.pixabay.com/photo/2014/10/10/04/27/aglaonema-482915_1280.jpg", - description: "Requires minimal care and adds color to indoor spaces.", - cost: "$22" - } - ] - } - ]; - const styleObj = { - backgroundColor: '#4CAF50', - color: '#fff!important', - padding: '15px', - display: 'flex', - justifyContent: 'space-between', - alignIems: 'center', - fontSize: '20px', - } - const styleObjUl = { - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - width: '1100px', - } - const styleA = { - color: 'white', - fontSize: '30px', - textDecoration: 'none', - } + // Añade este estado para rastrear artículos añadidos (ya lo tienes en el archivo) + const [addedToCart, setAddedToCart] = useState({}); - const handleHomeClick = (e) => { - e.preventDefault(); - onHomeClick(); - }; + const plantsArray = [ + { + category: "Air Purifying Plants", + plants: [ + { + id: "snake-plant-1", + name: "Snake Plant", + image: "https://cdn.pixabay.com/photo/2021/01/22/06/04/snake-plant-5939187_1280.jpg", + description: "Produces oxygen at night, improving air quality.", + cost: "$15" + }, + { + id: "spider-plant-1", + name: "Spider Plant", + image: "https://cdn.pixabay.com/photo/2018/07/11/06/47/chlorophytum-3530413_1280.jpg", + description: "Filters formaldehyde and xylene from the air.", + cost: "$12" + }, + { + id: "peace-lily-1", + name: "Peace Lily", + image: "https://cdn.pixabay.com/photo/2019/06/12/14/14/peace-lilies-4269365_1280.jpg", + description: "Removes mold spores and purifies the air.", + cost: "$18" + }, + { + id: "boston-fern-1", + name: "Boston Fern", + image: "https://cdn.pixabay.com/photo/2020/04/30/19/52/boston-fern-5114414_1280.jpg", + description: "Adds humidity to the air and removes toxins.", + cost: "$20" + }, + { + id: "rubber-plant-1", + name: "Rubber Plant", + image: "https://cdn.pixabay.com/photo/2020/02/15/11/49/flower-4850729_1280.jpg", + description: "Easy to care for and effective at removing toxins.", + cost: "$17" + }, + { + id: "aloe-vera-1", + name: "Aloe Vera", + image: "https://cdn.pixabay.com/photo/2018/04/02/07/42/leaf-3283175_1280.jpg", + description: "Purifies the air and has healing properties for skin.", + cost: "$14" + } + ] + }, + { + category: "Aromatic Fragrant Plants", + plants: [ + { + id: "lavender-1", + name: "Lavender", + image: "https://images.unsplash.com/photo-1611909023032-2d6b3134ecba?q=80&w=1074&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", + description: "Calming scent, used in aromatherapy.", + cost: "$20" + }, + { + id: "jasmine-1", + name: "Jasmine", + image: "https://images.unsplash.com/photo-1592729645009-b96d1e63d14b?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", + description: "Sweet fragrance, promotes relaxation.", + cost: "$18" + }, + { + id: "rosemary-1", + name: "Rosemary", + image: "https://cdn.pixabay.com/photo/2019/10/11/07/12/rosemary-4541241_1280.jpg", + description: "Invigorating scent, often used in cooking.", + cost: "$15" + }, + { + id: "mint-1", + name: "Mint", + image: "https://cdn.pixabay.com/photo/2016/01/07/18/16/mint-1126282_1280.jpg", + description: "Refreshing aroma, used in teas and cooking.", + cost: "$12" + }, + { + id: "lemon-balm-1", + name: "Lemon Balm", + image: "https://cdn.pixabay.com/photo/2019/09/16/07/41/balm-4480134_1280.jpg", + description: "Citrusy scent, relieves stress and promotes sleep.", + cost: "$14" + }, + { + id: "hyacinth-1", + name: "Hyacinth", + image: "https://cdn.pixabay.com/photo/2019/04/07/20/20/hyacinth-4110726_1280.jpg", + description: "Hyacinth is a beautiful flowering plant known for its fragrant.", + cost: "$22" + } + ] + }, + { + category: "Insect Repellent Plants", + plants: [ + { + id: "oregano-1", + name: "oregano", + image: "https://cdn.pixabay.com/photo/2015/05/30/21/20/oregano-790702_1280.jpg", + description: "The oregano plants contains compounds that can deter certain insects.", + cost: "$10" + }, + { + id: "marigold-1", + name: "Marigold", + image: "https://cdn.pixabay.com/photo/2022/02/22/05/45/marigold-7028063_1280.jpg", + description: "Natural insect repellent, also adds color to the garden.", + cost: "$8" + }, + { + id: "geraniums-1", + name: "Geraniums", + image: "https://cdn.pixabay.com/photo/2012/04/26/21/51/flowerpot-43270_1280.jpg", + description: "Known for their insect-repelling properties while adding a pleasant scent.", + cost: "$20" + }, + { + id: "basil-1", + name: "Basil", + image: "https://cdn.pixabay.com/photo/2016/07/24/20/48/tulsi-1539181_1280.jpg", + description: "Repels flies and mosquitoes, also used in cooking.", + cost: "$9" + }, + { + id: "lavender-2", + name: "Lavender", + image: "https://images.unsplash.com/photo-1611909023032-2d6b3134ecba?q=80&w=1074&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", + description: "Calming scent, used in aromatherapy.", + cost: "$20" + }, + { + id: "catnip-1", + name: "Catnip", + image: "https://cdn.pixabay.com/photo/2015/07/02/21/55/cat-829681_1280.jpg", + description: "Repels mosquitoes and attracts cats.", + cost: "$13" + } + ] + }, + { + category: "Medicinal Plants", + plants: [ + { + id: "aloe-vera-2", + name: "Aloe Vera", + image: "https://cdn.pixabay.com/photo/2018/04/02/07/42/leaf-3283175_1280.jpg", + description: "Soothing gel used for skin ailments.", + cost: "$14" + }, + { + id: "echinacea-1", + name: "Echinacea", + image: "https://cdn.pixabay.com/photo/2014/12/05/03/53/echinacea-557477_1280.jpg", + description: "Boosts immune system, helps fight colds.", + cost: "$16" + }, + { + id: "peppermint-1", + name: "Peppermint", + image: "https://cdn.pixabay.com/photo/2017/07/12/12/23/peppermint-2496773_1280.jpg", + description: "Relieves digestive issues and headaches.", + cost: "$13" + }, + { + id: "lemon-balm-2", + name: "Lemon Balm", + image: "https://cdn.pixabay.com/photo/2019/09/16/07/41/balm-4480134_1280.jpg", + description: "Calms nerves and promotes relaxation.", + cost: "$14" + }, + { + id: "chamomile-1", + name: "Chamomile", + image: "https://cdn.pixabay.com/photo/2016/08/19/19/48/flowers-1606041_1280.jpg", + description: "Soothes anxiety and promotes sleep.", + cost: "$15" + }, + { + id: "calendula-1", + name: "Calendula", + image: "https://cdn.pixabay.com/photo/2019/07/15/18/28/flowers-4340127_1280.jpg", + description: "Heals wounds and soothes skin irritations.", + cost: "$12" + } + ] + }, + { + category: "Low Maintenance Plants", + plants: [ + { + id: "zz-plant-1", + name: "ZZ Plant", + image: "https://images.unsplash.com/photo-1632207691143-643e2a9a9361?q=80&w=464&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", + description: "Thrives in low light and requires minimal watering.", + cost: "$25" + }, + { + id: "pothos-1", + name: "Pothos", + image: "https://cdn.pixabay.com/photo/2018/11/15/10/32/plants-3816945_1280.jpg", + description: "Tolerates neglect and can grow in various conditions.", + cost: "$10" + }, + { + id: "snake-plant-2", + name: "Snake Plant", + image: "https://cdn.pixabay.com/photo/2021/01/22/06/04/snake-plant-5939187_1280.jpg", + description: "Needs infrequent watering and is resilient to most pests.", + cost: "$15" + }, + { + id: "cast-iron-plant-1", + name: "Cast Iron Plant", + image: "https://cdn.pixabay.com/photo/2017/02/16/18/04/cast-iron-plant-2072008_1280.jpg", + description: "Hardy plant that tolerates low light and neglect.", + cost: "$20" + }, + { + id: "succulents-1", + name: "Succulents", + image: "https://cdn.pixabay.com/photo/2016/11/21/16/05/cacti-1846147_1280.jpg", + description: "Drought-tolerant plants with unique shapes and colors.", + cost: "$18" + }, + { + id: "aglaonema-1", + name: "Aglaonema", + image: "https://cdn.pixabay.com/photo/2014/10/10/04/27/aglaonema-482915_1280.jpg", + description: "Requires minimal care and adds color to indoor spaces.", + cost: "$22" + } + ] + } + ]; + const styleObj = { + backgroundColor: '#4CAF50', + color: '#fff!important', + padding: '15px', + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', // <-- corregido + fontSize: '20px', + } + const styleObjUl = { + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + width: '1100px', + } + const styleA = { + color: 'white', + fontSize: '30px', + textDecoration: 'none', + } - const handleCartClick = (e) => { - e.preventDefault(); - setShowCart(true); // Set showCart to true when cart icon is clicked - }; - const handlePlantsClick = (e) => { - e.preventDefault(); - setShowPlants(true); // Set showAboutUs to true when "About Us" link is clicked - setShowCart(false); // Hide the cart when navigating to About Us - }; + const handleHomeClick = (e) => { + e.preventDefault(); + onHomeClick(); + }; - const handleContinueShopping = (e) => { - e.preventDefault(); - setShowCart(false); - }; + const handleCartClick = (e) => { + e.preventDefault(); + setShowCart(true); // Set showCart to true when cart icon is clicked + }; + const handlePlantsClick = (e) => { + e.preventDefault(); + setShowPlants(true); // Set showAboutUs to true when "About Us" link is clicked + setShowCart(false); // Hide the cart when navigating to About Us + }; - const handleAddToCart = (plant) => { - dispatch(addItem(plant)); // Despacha la acción para agregar la planta al carrito - setAddedToCart((prevState) => ({ - ...prevState, - [plant.name]: true, // Marca la planta como añadida en el estado local - })); - }; + const handleContinueShopping = (e) => { + e.preventDefault(); + setShowCart(false); + }; - return ( -
- - {!showCart ? ( -
- {plantsArray.map((category, index) => ( -
-

-
{category.category}
-

-
- {category.plants.map((plant, plantIndex) => ( -
- {plant.name} -
{plant.name}
-
{plant.description}
-
{plant.cost}
- -
- ))} -
-
- ))} -
- ) : ( - - )} -
+ // Despacha a addItem en tu slice cuando el usuario pulsa "Agregar al Carrito" + const handleAddToCart = (plant) => { + dispatch( + addItem({ + id: plant.id ?? plant.name, + name: plant.name, + image: plant.image ?? "", + cost: plant.cost ?? "$0", + qty: 1, + }) ); + setAddedToCart((prev) => ({ ...prev, [plant.id ?? plant.name]: true })); + }; + + return ( +
+ + {!showCart ? ( +
+ {plantsArray.map((category, index) => ( +
+

+
{category.category}
+

+
+ {category.plants.map((plant) => ( +
+ {plant.name} +
{plant.name}
+
{plant.description}
+
{plant.cost}
+ +
+ ))} +
+
+ ))} +
+ ) : ( + + )} +
+ ); } export default ProductList; diff --git a/src/store.js b/src/store.js index 54d0d6d66e..3c3fa6579c 100644 --- a/src/store.js +++ b/src/store.js @@ -1,8 +1,8 @@ -import { configureStore } from '@reduxjs/toolkit'; -import cartReducer from './CartSlice'; - const store = configureStore({ - reducer: { - cart: cartReducer, - }, +import { configureStore } from "@reduxjs/toolkit"; +import cartReducer from "./CartSlice"; + +export default configureStore({ + reducer: { + cart: cartReducer, + }, }); -export default store From 6a4fd4cd5044ada2e14f2f27808a9595770071b7 Mon Sep 17 00:00:00 2001 From: ximenabaquero Date: Thu, 4 Sep 2025 17:00:57 -0500 Subject: [PATCH 4/7] Add gh-pages deploy scripts --- package.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b7d4c1d1d4..4b537240c6 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,9 @@ "dev": "vite", "build": "vite build", "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", - "preview": "vite build; vite preview --host" + "preview": "vite build; vite preview --host", + "predeploy": "npm run build", + "deploy": "gh-pages -d dist" }, "dependencies": { "@reduxjs/toolkit": "^2.2.3", @@ -23,7 +25,7 @@ "eslint-plugin-react": "^7.34.1", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.6", - "gh-pages": "^6.1.1", + "gh-pages": "^6.3.0", "vite": "^5.2.0" } } From 6fd012afc83433cacd651aacb47cecba9eadaac6 Mon Sep 17 00:00:00 2001 From: ximenabaquero Date: Thu, 4 Sep 2025 17:04:19 -0500 Subject: [PATCH 5/7] Add vite base and gh-pages deploy scripts --- package-lock.json | 235 +++++++++++---- src/CartItem.jsx | 97 ++++-- src/CartSlice.jsx | 21 +- src/ProductList.jsx | 696 ++++++++++++++++++++++---------------------- src/main.jsx | 22 +- src/store.js | 8 +- vite.config.js | 2 +- 7 files changed, 631 insertions(+), 450 deletions(-) diff --git a/package-lock.json b/package-lock.json index af7843d848..3e89598b75 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "eslint-plugin-react": "^7.34.1", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.6", - "gh-pages": "^6.1.1", + "gh-pages": "^6.3.0", "vite": "^5.2.0" } }, @@ -1364,24 +1364,13 @@ } }, "node_modules/array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", - "dev": true, - "dependencies": { - "array-uniq": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/array.prototype.findlast": { @@ -1524,6 +1513,19 @@ "concat-map": "0.0.1" } }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/browserslist": { "version": "4.23.0", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", @@ -1634,12 +1636,13 @@ "dev": true }, "node_modules/commander": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", - "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", + "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/commondir": { @@ -1788,6 +1791,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -2336,6 +2352,36 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -2395,6 +2441,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/find-cache-dir": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", @@ -2573,18 +2632,19 @@ } }, "node_modules/gh-pages": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.1.1.tgz", - "integrity": "sha512-upnohfjBwN5hBP9w2dPE7HO5JJTHzSGMV1JrLrHvNuqmjoYHg6TBrCcnEoorjG/e0ejbuvnwyKMdTyM40PEByw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.3.0.tgz", + "integrity": "sha512-Ot5lU6jK0Eb+sszG8pciXdjMXdBJ5wODvgjR+imihTqsUWF2K6dJ9HST55lgqcs8wWcw6o6wAsUzfcYRhJPXbA==", "dev": true, + "license": "MIT", "dependencies": { "async": "^3.2.4", - "commander": "^11.0.0", + "commander": "^13.0.0", "email-addresses": "^5.0.0", "filenamify": "^4.3.0", "find-cache-dir": "^3.3.1", "fs-extra": "^11.1.1", - "globby": "^6.1.0" + "globby": "^11.1.0" }, "bin": { "gh-pages": "bin/gh-pages.js", @@ -2651,19 +2711,24 @@ } }, "node_modules/globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, + "license": "MIT", "dependencies": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/gopd": { @@ -3029,6 +3094,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/is-number-object": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", @@ -3370,6 +3445,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3639,40 +3738,33 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", - "dev": true, - "dependencies": { - "pinkie": "^2.0.0" + "node": ">=8.6" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/pkg-dir": { @@ -4178,6 +4270,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/source-map-js": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", @@ -4337,6 +4439,19 @@ "node": ">=4" } }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/trim-repeated": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", diff --git a/src/CartItem.jsx b/src/CartItem.jsx index bcac731860..cc4ebe6fb9 100644 --- a/src/CartItem.jsx +++ b/src/CartItem.jsx @@ -1,18 +1,20 @@ -import React from 'react'; -import { useSelector, useDispatch } from 'react-redux'; -import { removeItem, updateQuantity } from './CartSlice'; -import './CartItem.css'; +import React from "react"; +import { useSelector, useDispatch } from "react-redux"; +import { updateQuantity, removeItem } from "./CartSlice"; +import "./CartItem.css"; const CartItem = ({ onContinueShopping }) => { - const cart = useSelector(state => state.cart?.items ?? []); + const cart = useSelector((state) => state.cart?.items ?? []); const dispatch = useDispatch(); // Calculate total amount for all products in the cart const calculateTotalAmount = () => { let total = 0; - cart.forEach(item => { + cart.forEach((item) => { const qty = item.quantity ?? item.qty ?? 0; - const price = item.cost ? parseFloat(String(item.cost).replace(/[^0-9.-]+/g, '')) : 0; + const price = item.cost + ? parseFloat(String(item.cost).replace(/[^0-9.-]+/g, "")) + : 0; total += price * qty; }); return total.toFixed(2); @@ -23,14 +25,23 @@ const CartItem = ({ onContinueShopping }) => { }; const handleIncrement = (item) => { - const current = item.quantity ?? item.qty ?? 0; - dispatch(updateQuantity({ name: item.name, quantity: current + 1 })); + dispatch( + updateQuantity({ + name: item.name, + quantity: (item.quantity ?? item.qty ?? 0) + 1, + }) + ); }; const handleDecrement = (item) => { const current = item.quantity ?? item.qty ?? 0; if (current > 1) { - dispatch(updateQuantity({ name: item.name, quantity: current - 1 })); + dispatch( + updateQuantity({ + name: item.name, + quantity: current - 1, + }) + ); } else { dispatch(removeItem(item.name)); } @@ -40,39 +51,77 @@ const CartItem = ({ onContinueShopping }) => { dispatch(removeItem(item.name)); }; - // Calculate total cost based on quantity for an item + // Calculate total cost for a single item (subtotal) const calculateTotalCost = (item) => { - const qty = item.quantity ?? item.qty ?? 0; - const price = item.cost ? parseFloat(String(item.cost).replace(/[^0-9.-]+/g, '')) : 0; - return (price * qty).toFixed(2); + const quantity = item.quantity ?? item.qty ?? 0; + const price = item.cost ? parseFloat(item.cost.substring(1)) : 0; + return (price * quantity).toFixed(2); + }; + + const handleCheckoutShopping = (e) => { + alert("Functionality to be added for future reference"); }; return (
-

Total Cart Amount: ${calculateTotalAmount()}

+

+ Total Cart Amount: ${calculateTotalAmount()} +

- {cart.map(item => ( + {cart.map((item) => (
{item.name}
{item.name}
{item.cost}
- - {item.quantity} - + + + {item.quantity ?? item.qty ?? 0} + + +
+
+ Total: ${calculateTotalCost(item)}
-
Total: ${calculateTotalCost(item)}
- +
))}
-
+
- +
- +
); diff --git a/src/CartSlice.jsx b/src/CartSlice.jsx index f20797a2ae..a0c6d1b9cd 100644 --- a/src/CartSlice.jsx +++ b/src/CartSlice.jsx @@ -26,7 +26,8 @@ export const CartSlice = createSlice({ }, removeItem: (state, action) => { - state.items = state.items.filter((item) => item.name !== action.payload); + const key = action.payload; + state.items = state.items.filter(item => item.id !== key && item.name !== key); }, updateQuantity: (state, action) => { @@ -47,3 +48,21 @@ export const CartSlice = createSlice({ export const { addItem, removeItem, updateQuantity, clearCart } = CartSlice.actions; export default CartSlice.reducer; +// Calculate total amount for all items in the cart +export const calculateTotalAmount = (items) => { + let total = 0; + (items || []).forEach((item) => { + const qty = item.qty ?? item.quantity ?? 0; + const price = item.cost ? parseFloat(String(item.cost).replace(/[^0-9.-]+/g, "")) : 0; + total += price * qty; + }); + return total; +}; + +// Calculate subtotal for a single cart item +export const calculateSubtotal = (item) => { + const qty = item?.qty ?? item?.quantity ?? 0; + const price = item?.cost ? parseFloat(String(item.cost).replace(/[^0-9.-]+/g, "")) : 0; + return price * qty; +}; + diff --git a/src/ProductList.jsx b/src/ProductList.jsx index 660adaebdd..4ec79530ad 100644 --- a/src/ProductList.jsx +++ b/src/ProductList.jsx @@ -1,365 +1,363 @@ import React, { useState, useEffect } from 'react'; -import { useDispatch, useSelector } from 'react-redux'; // <-- Agrega esto +import { useDispatch, useSelector } from 'react-redux'; import { addItem } from './CartSlice'; import './ProductList.css' import CartItem from './CartItem'; function ProductList({ onHomeClick }) { - const dispatch = useDispatch(); - const cartItems = useSelector(state => state.cart?.items ?? []); - const [showCart, setShowCart] = useState(false); - const [showPlants, setShowPlants] = useState(false); + const dispatch = useDispatch(); + const cartItems = useSelector((state) => state.cart?.items ?? []); - // Añade este estado para rastrear artículos añadidos (ya lo tienes en el archivo) - const [addedToCart, setAddedToCart] = useState({}); + const [showCart, setShowCart] = useState(false); + const [showPlants, setShowPlants] = useState(false); // State to control the visibility of the About Us page + const [addedToCart, setAddedToCart] = useState({}); // <-- Agrega esto - const plantsArray = [ - { - category: "Air Purifying Plants", - plants: [ - { - id: "snake-plant-1", - name: "Snake Plant", - image: "https://cdn.pixabay.com/photo/2021/01/22/06/04/snake-plant-5939187_1280.jpg", - description: "Produces oxygen at night, improving air quality.", - cost: "$15" - }, - { - id: "spider-plant-1", - name: "Spider Plant", - image: "https://cdn.pixabay.com/photo/2018/07/11/06/47/chlorophytum-3530413_1280.jpg", - description: "Filters formaldehyde and xylene from the air.", - cost: "$12" - }, - { - id: "peace-lily-1", - name: "Peace Lily", - image: "https://cdn.pixabay.com/photo/2019/06/12/14/14/peace-lilies-4269365_1280.jpg", - description: "Removes mold spores and purifies the air.", - cost: "$18" - }, - { - id: "boston-fern-1", - name: "Boston Fern", - image: "https://cdn.pixabay.com/photo/2020/04/30/19/52/boston-fern-5114414_1280.jpg", - description: "Adds humidity to the air and removes toxins.", - cost: "$20" - }, - { - id: "rubber-plant-1", - name: "Rubber Plant", - image: "https://cdn.pixabay.com/photo/2020/02/15/11/49/flower-4850729_1280.jpg", - description: "Easy to care for and effective at removing toxins.", - cost: "$17" - }, - { - id: "aloe-vera-1", - name: "Aloe Vera", - image: "https://cdn.pixabay.com/photo/2018/04/02/07/42/leaf-3283175_1280.jpg", - description: "Purifies the air and has healing properties for skin.", - cost: "$14" - } - ] - }, - { - category: "Aromatic Fragrant Plants", - plants: [ - { - id: "lavender-1", - name: "Lavender", - image: "https://images.unsplash.com/photo-1611909023032-2d6b3134ecba?q=80&w=1074&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", - description: "Calming scent, used in aromatherapy.", - cost: "$20" - }, - { - id: "jasmine-1", - name: "Jasmine", - image: "https://images.unsplash.com/photo-1592729645009-b96d1e63d14b?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", - description: "Sweet fragrance, promotes relaxation.", - cost: "$18" - }, - { - id: "rosemary-1", - name: "Rosemary", - image: "https://cdn.pixabay.com/photo/2019/10/11/07/12/rosemary-4541241_1280.jpg", - description: "Invigorating scent, often used in cooking.", - cost: "$15" - }, - { - id: "mint-1", - name: "Mint", - image: "https://cdn.pixabay.com/photo/2016/01/07/18/16/mint-1126282_1280.jpg", - description: "Refreshing aroma, used in teas and cooking.", - cost: "$12" - }, - { - id: "lemon-balm-1", - name: "Lemon Balm", - image: "https://cdn.pixabay.com/photo/2019/09/16/07/41/balm-4480134_1280.jpg", - description: "Citrusy scent, relieves stress and promotes sleep.", - cost: "$14" - }, - { - id: "hyacinth-1", - name: "Hyacinth", - image: "https://cdn.pixabay.com/photo/2019/04/07/20/20/hyacinth-4110726_1280.jpg", - description: "Hyacinth is a beautiful flowering plant known for its fragrant.", - cost: "$22" - } - ] - }, - { - category: "Insect Repellent Plants", - plants: [ - { - id: "oregano-1", - name: "oregano", - image: "https://cdn.pixabay.com/photo/2015/05/30/21/20/oregano-790702_1280.jpg", - description: "The oregano plants contains compounds that can deter certain insects.", - cost: "$10" - }, - { - id: "marigold-1", - name: "Marigold", - image: "https://cdn.pixabay.com/photo/2022/02/22/05/45/marigold-7028063_1280.jpg", - description: "Natural insect repellent, also adds color to the garden.", - cost: "$8" - }, - { - id: "geraniums-1", - name: "Geraniums", - image: "https://cdn.pixabay.com/photo/2012/04/26/21/51/flowerpot-43270_1280.jpg", - description: "Known for their insect-repelling properties while adding a pleasant scent.", - cost: "$20" - }, - { - id: "basil-1", - name: "Basil", - image: "https://cdn.pixabay.com/photo/2016/07/24/20/48/tulsi-1539181_1280.jpg", - description: "Repels flies and mosquitoes, also used in cooking.", - cost: "$9" - }, - { - id: "lavender-2", - name: "Lavender", - image: "https://images.unsplash.com/photo-1611909023032-2d6b3134ecba?q=80&w=1074&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", - description: "Calming scent, used in aromatherapy.", - cost: "$20" - }, - { - id: "catnip-1", - name: "Catnip", - image: "https://cdn.pixabay.com/photo/2015/07/02/21/55/cat-829681_1280.jpg", - description: "Repels mosquitoes and attracts cats.", - cost: "$13" - } - ] - }, - { - category: "Medicinal Plants", - plants: [ - { - id: "aloe-vera-2", - name: "Aloe Vera", - image: "https://cdn.pixabay.com/photo/2018/04/02/07/42/leaf-3283175_1280.jpg", - description: "Soothing gel used for skin ailments.", - cost: "$14" - }, - { - id: "echinacea-1", - name: "Echinacea", - image: "https://cdn.pixabay.com/photo/2014/12/05/03/53/echinacea-557477_1280.jpg", - description: "Boosts immune system, helps fight colds.", - cost: "$16" - }, - { - id: "peppermint-1", - name: "Peppermint", - image: "https://cdn.pixabay.com/photo/2017/07/12/12/23/peppermint-2496773_1280.jpg", - description: "Relieves digestive issues and headaches.", - cost: "$13" - }, - { - id: "lemon-balm-2", - name: "Lemon Balm", - image: "https://cdn.pixabay.com/photo/2019/09/16/07/41/balm-4480134_1280.jpg", - description: "Calms nerves and promotes relaxation.", - cost: "$14" - }, - { - id: "chamomile-1", - name: "Chamomile", - image: "https://cdn.pixabay.com/photo/2016/08/19/19/48/flowers-1606041_1280.jpg", - description: "Soothes anxiety and promotes sleep.", - cost: "$15" - }, - { - id: "calendula-1", - name: "Calendula", - image: "https://cdn.pixabay.com/photo/2019/07/15/18/28/flowers-4340127_1280.jpg", - description: "Heals wounds and soothes skin irritations.", - cost: "$12" - } - ] - }, - { - category: "Low Maintenance Plants", - plants: [ - { - id: "zz-plant-1", - name: "ZZ Plant", - image: "https://images.unsplash.com/photo-1632207691143-643e2a9a9361?q=80&w=464&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", - description: "Thrives in low light and requires minimal watering.", - cost: "$25" - }, - { - id: "pothos-1", - name: "Pothos", - image: "https://cdn.pixabay.com/photo/2018/11/15/10/32/plants-3816945_1280.jpg", - description: "Tolerates neglect and can grow in various conditions.", - cost: "$10" - }, - { - id: "snake-plant-2", - name: "Snake Plant", - image: "https://cdn.pixabay.com/photo/2021/01/22/06/04/snake-plant-5939187_1280.jpg", - description: "Needs infrequent watering and is resilient to most pests.", - cost: "$15" - }, - { - id: "cast-iron-plant-1", - name: "Cast Iron Plant", - image: "https://cdn.pixabay.com/photo/2017/02/16/18/04/cast-iron-plant-2072008_1280.jpg", - description: "Hardy plant that tolerates low light and neglect.", - cost: "$20" - }, - { - id: "succulents-1", - name: "Succulents", - image: "https://cdn.pixabay.com/photo/2016/11/21/16/05/cacti-1846147_1280.jpg", - description: "Drought-tolerant plants with unique shapes and colors.", - cost: "$18" - }, - { - id: "aglaonema-1", - name: "Aglaonema", - image: "https://cdn.pixabay.com/photo/2014/10/10/04/27/aglaonema-482915_1280.jpg", - description: "Requires minimal care and adds color to indoor spaces.", - cost: "$22" - } - ] - } - ]; - const styleObj = { - backgroundColor: '#4CAF50', - color: '#fff!important', - padding: '15px', - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', // <-- corregido - fontSize: '20px', - } - const styleObjUl = { - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - width: '1100px', - } - const styleA = { - color: 'white', - fontSize: '30px', - textDecoration: 'none', - } + const plantsArray = [ + { + category: "Air Purifying Plants", + plants: [ + { + id: "snake-plant-1", + name: "Snake Plant", + image: "https://cdn.pixabay.com/photo/2021/01/22/06/04/snake-plant-5939187_1280.jpg", + description: "Produces oxygen at night, improving air quality.", + cost: "$15" + }, + { + id: "spider-plant-1", + name: "Spider Plant", + image: "https://cdn.pixabay.com/photo/2018/07/11/06/47/chlorophytum-3530413_1280.jpg", + description: "Filters formaldehyde and xylene from the air.", + cost: "$12" + }, + { + id: "peace-lily-1", + name: "Peace Lily", + image: "https://cdn.pixabay.com/photo/2019/06/12/14/14/peace-lilies-4269365_1280.jpg", + description: "Removes mold spores and purifies the air.", + cost: "$18" + }, + { + id: "boston-fern-1", + name: "Boston Fern", + image: "https://cdn.pixabay.com/photo/2020/04/30/19/52/boston-fern-5114414_1280.jpg", + description: "Adds humidity to the air and removes toxins.", + cost: "$20" + }, + { + id: "rubber-plant-1", + name: "Rubber Plant", + image: "https://cdn.pixabay.com/photo/2020/02/15/11/49/flower-4850729_1280.jpg", + description: "Easy to care for and effective at removing toxins.", + cost: "$17" + }, + { + id: "aloe-vera-1", + name: "Aloe Vera", + image: "https://cdn.pixabay.com/photo/2018/04/02/07/42/leaf-3283175_1280.jpg", + description: "Purifies the air and has healing properties for skin.", + cost: "$14" + } + ] + }, + { + category: "Aromatic Fragrant Plants", + plants: [ + { + id: "lavender-1", + name: "Lavender", + image: "https://images.unsplash.com/photo-1611909023032-2d6b3134ecba?q=80&w=1074&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", + description: "Calming scent, used in aromatherapy.", + cost: "$20" + }, + { + id: "jasmine-1", + name: "Jasmine", + image: "https://images.unsplash.com/photo-1592729645009-b96d1e63d14b?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", + description: "Sweet fragrance, promotes relaxation.", + cost: "$18" + }, + { + id: "rosemary-1", + name: "Rosemary", + image: "https://cdn.pixabay.com/photo/2019/10/11/07/12/rosemary-4541241_1280.jpg", + description: "Invigorating scent, often used in cooking.", + cost: "$15" + }, + { + id: "mint-1", + name: "Mint", + image: "https://cdn.pixabay.com/photo/2016/01/07/18/16/mint-1126282_1280.jpg", + description: "Refreshing aroma, used in teas and cooking.", + cost: "$12" + }, + { + id: "lemon-balm-1", + name: "Lemon Balm", + image: "https://cdn.pixabay.com/photo/2019/09/16/07/41/balm-4480134_1280.jpg", + description: "Citrusy scent, relieves stress and promotes sleep.", + cost: "$14" + }, + { + id: "hyacinth-1", + name: "Hyacinth", + image: "https://cdn.pixabay.com/photo/2019/04/07/20/20/hyacinth-4110726_1280.jpg", + description: "Hyacinth is a beautiful flowering plant known for its fragrant.", + cost: "$22" + } + ] + }, + { + category: "Insect Repellent Plants", + plants: [ + { + id: "oregano-1", + name: "oregano", + image: "https://cdn.pixabay.com/photo/2015/05/30/21/20/oregano-790702_1280.jpg", + description: "The oregano plants contains compounds that can deter certain insects.", + cost: "$10" + }, + { + id: "marigold-1", + name: "Marigold", + image: "https://cdn.pixabay.com/photo/2022/02/22/05/45/marigold-7028063_1280.jpg", + description: "Natural insect repellent, also adds color to the garden.", + cost: "$8" + }, + { + id: "geraniums-1", + name: "Geraniums", + image: "https://cdn.pixabay.com/photo/2012/04/26/21/51/flowerpot-43270_1280.jpg", + description: "Known for their insect-repelling properties while adding a pleasant scent.", + cost: "$20" + }, + { + id: "basil-1", + name: "Basil", + image: "https://cdn.pixabay.com/photo/2016/07/24/20/48/tulsi-1539181_1280.jpg", + description: "Repels flies and mosquitoes, also used in cooking.", + cost: "$9" + }, + { + id: "lavender-2", + name: "Lavender", + image: "https://images.unsplash.com/photo-1611909023032-2d6b3134ecba?q=80&w=1074&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", + description: "Calming scent, used in aromatherapy.", + cost: "$20" + }, + { + id: "catnip-1", + name: "Catnip", + image: "https://cdn.pixabay.com/photo/2015/07/02/21/55/cat-829681_1280.jpg", + description: "Repels mosquitoes and attracts cats.", + cost: "$13" + } + ] + }, + { + category: "Medicinal Plants", + plants: [ + { + id: "aloe-vera-2", + name: "Aloe Vera", + image: "https://cdn.pixabay.com/photo/2018/04/02/07/42/leaf-3283175_1280.jpg", + description: "Soothing gel used for skin ailments.", + cost: "$14" + }, + { + id: "echinacea-1", + name: "Echinacea", + image: "https://cdn.pixabay.com/photo/2014/12/05/03/53/echinacea-557477_1280.jpg", + description: "Boosts immune system, helps fight colds.", + cost: "$16" + }, + { + id: "peppermint-1", + name: "Peppermint", + image: "https://cdn.pixabay.com/photo/2017/07/12/12/23/peppermint-2496773_1280.jpg", + description: "Relieves digestive issues and headaches.", + cost: "$13" + }, + { + id: "lemon-balm-2", + name: "Lemon Balm", + image: "https://cdn.pixabay.com/photo/2019/09/16/07/41/balm-4480134_1280.jpg", + description: "Calms nerves and promotes relaxation.", + cost: "$14" + }, + { + id: "chamomile-1", + name: "Chamomile", + image: "https://cdn.pixabay.com/photo/2016/08/19/19/48/flowers-1606041_1280.jpg", + description: "Soothes anxiety and promotes sleep.", + cost: "$15" + }, + { + id: "calendula-1", + name: "Calendula", + image: "https://cdn.pixabay.com/photo/2019/07/15/18/28/flowers-4340127_1280.jpg", + description: "Heals wounds and soothes skin irritations.", + cost: "$12" + } + ] + }, + { + category: "Low Maintenance Plants", + plants: [ + { + id: "zz-plant-1", + name: "ZZ Plant", + image: "https://images.unsplash.com/photo-1632207691143-643e2a9a9361?q=80&w=464&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", + description: "Thrives in low light and requires minimal watering.", + cost: "$25" + }, + { + id: "pothos-1", + name: "Pothos", + image: "https://cdn.pixabay.com/photo/2018/11/15/10/32/plants-3816945_1280.jpg", + description: "Tolerates neglect and can grow in various conditions.", + cost: "$10" + }, + { + id: "snake-plant-2", + name: "Snake Plant", + image: "https://cdn.pixabay.com/photo/2021/01/22/06/04/snake-plant-5939187_1280.jpg", + description: "Needs infrequent watering and is resilient to most pests.", + cost: "$15" + }, + { + id: "cast-iron-plant-1", + name: "Cast Iron Plant", + image: "https://cdn.pixabay.com/photo/2017/02/16/18/04/cast-iron-plant-2072008_1280.jpg", + description: "Hardy plant that tolerates low light and neglect.", + cost: "$20" + }, + { + id: "succulents-1", + name: "Succulents", + image: "https://cdn.pixabay.com/photo/2016/11/21/16/05/cacti-1846147_1280.jpg", + description: "Drought-tolerant plants with unique shapes and colors.", + cost: "$18" + }, + { + id: "aglaonema-1", + name: "Aglaonema", + image: "https://cdn.pixabay.com/photo/2014/10/10/04/27/aglaonema-482915_1280.jpg", + description: "Requires minimal care and adds color to indoor spaces.", + cost: "$22" + } + ] + } + ]; + const styleObj = { + backgroundColor: '#4CAF50', + color: '#fff!important', + padding: '15px', + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + fontSize: '20px', + } + const styleObjUl = { + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + width: '1100px', + } + const styleA = { + color: 'white', + fontSize: '30px', + textDecoration: 'none', + } - const handleHomeClick = (e) => { - e.preventDefault(); - onHomeClick(); - }; + const handleHomeClick = (e) => { + e.preventDefault(); + onHomeClick(); + }; - const handleCartClick = (e) => { - e.preventDefault(); - setShowCart(true); // Set showCart to true when cart icon is clicked - }; - const handlePlantsClick = (e) => { - e.preventDefault(); - setShowPlants(true); // Set showAboutUs to true when "About Us" link is clicked - setShowCart(false); // Hide the cart when navigating to About Us - }; + const handleCartClick = (e) => { + e.preventDefault(); + setShowCart(true); // Set showCart to true when cart icon is clicked + }; + const handlePlantsClick = (e) => { + e.preventDefault(); + setShowPlants(true); // Set showAboutUs to true when "About Us" link is clicked + setShowCart(false); // Hide the cart when navigating to About Us + }; - const handleContinueShopping = (e) => { - e.preventDefault(); - setShowCart(false); - }; + const handleContinueShopping = (e) => { + e.preventDefault(); + setShowCart(false); + }; - // Despacha a addItem en tu slice cuando el usuario pulsa "Agregar al Carrito" - const handleAddToCart = (plant) => { - dispatch( - addItem({ - id: plant.id ?? plant.name, - name: plant.name, - image: plant.image ?? "", - cost: plant.cost ?? "$0", - qty: 1, - }) - ); - setAddedToCart((prev) => ({ ...prev, [plant.id ?? plant.name]: true })); - }; + // Añade al carrito (normaliza qty para el slice) + const handleAddToCart = (product) => { + dispatch(addItem({ ...product, qty: 1 })); + // si usas el estado local addedToCart, márcalo aquí: + if (typeof setAddedToCart === 'function') { + setAddedToCart(prev => ({ ...prev, [product.id ?? product.name]: true })); + } + }; + + // Calcula la cantidad total de artículos en el carrito + const calculateTotalQuantity = () => { + return cartItems ? cartItems.reduce((total, item) => total + (item.qty ?? item.quantity ?? 0), 0) : 0; + }; - return ( -
-
-
- + return ( +
+ - {!showCart ? ( -
- {plantsArray.map((category, index) => ( -
-

-
{category.category}
-

-
- {category.plants.map((plant) => ( -
- {plant.name} -
{plant.name}
-
{plant.description}
-
{plant.cost}
- -
- ))} -
-
- ))} -
- ) : ( - - )} -
- ); +
+ +
+ {!showCart ? ( +
+ {plantsArray.map((category, index) => ( +
+

+
{category.category}
+

+
+ {category.plants.map((plant, plantIndex) => ( +
+ {plant.name} +
{plant.name}
+
{plant.description}
+
{plant.cost}
+ +
+ ))} +
+
+ ))} +
+ ) : ( + + )} +
+ ); } export default ProductList; diff --git a/src/main.jsx b/src/main.jsx index 9ea042ec2b..412327d39e 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -1,13 +1,11 @@ -import React from 'react' -import ReactDOM from 'react-dom/client' -import App from './App.jsx' -import './index.css' -import { Provider } from 'react-redux' -import store from './store.js' -ReactDOM.createRoot(document.getElementById('root')).render( - - +import React from "react"; +import { createRoot } from "react-dom/client"; +import { Provider } from "react-redux"; +import App from "./App"; +import store from "./store"; + +createRoot(document.getElementById("root")).render( + - - , -) + +); diff --git a/src/store.js b/src/store.js index 3c3fa6579c..9773015056 100644 --- a/src/store.js +++ b/src/store.js @@ -1,8 +1,10 @@ -import { configureStore } from "@reduxjs/toolkit"; -import cartReducer from "./CartSlice"; +import { configureStore } from '@reduxjs/toolkit'; +import cartReducer from './CartSlice'; -export default configureStore({ +const store = configureStore({ reducer: { cart: cartReducer, }, }); + +export default store; diff --git a/vite.config.js b/vite.config.js index 4d190ae430..ed97a94459 100644 --- a/vite.config.js +++ b/vite.config.js @@ -3,6 +3,6 @@ import react from '@vitejs/plugin-react' // https://vitejs.dev/config/ export default defineConfig({ - base: "/shoppingreact", + base: '/e-plantShopping', plugins: [react()], }) From 90cd81a0ddb67b36314a35140a8919e219f7e6db Mon Sep 17 00:00:00 2001 From: ximenabaquero Date: Thu, 4 Sep 2025 17:49:06 -0500 Subject: [PATCH 6/7] Guarda cambios en ProductList --- src/ProductList.jsx | 159 +++++++++++++++++++++++++------------------- 1 file changed, 89 insertions(+), 70 deletions(-) diff --git a/src/ProductList.jsx b/src/ProductList.jsx index 4ec79530ad..5b3fcb6987 100644 --- a/src/ProductList.jsx +++ b/src/ProductList.jsx @@ -1,15 +1,80 @@ import React, { useState, useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { addItem } from './CartSlice'; -import './ProductList.css' import CartItem from './CartItem'; +import './ProductList.css' + function ProductList({ onHomeClick }) { const dispatch = useDispatch(); const cartItems = useSelector((state) => state.cart?.items ?? []); const [showCart, setShowCart] = useState(false); - const [showPlants, setShowPlants] = useState(false); // State to control the visibility of the About Us page - const [addedToCart, setAddedToCart] = useState({}); // <-- Agrega esto + const [addedToCart, setAddedToCart] = useState({}); + + // Keep addedToCart in sync with store (so page reloads preserve "Añadido") + useEffect(() => { + const map = {}; + (cartItems || []).forEach(i => { + const key = i.id ?? i.name; + map[key] = true; + }); + setAddedToCart(map); + }, [cartItems]); + + const calculateTotalQuantity = () => + cartItems ? cartItems.reduce((total, item) => total + (item.qty ?? item.quantity ?? 0), 0) : 0; + + const handleAddToCart = (plant) => { + const key = plant.id ?? plant.name; + dispatch(addItem({ + id: key, + name: plant.name, + image: plant.image, + cost: plant.cost, + qty: 1, + })); + setAddedToCart(prev => ({ ...prev, [key]: true })); + }; + + const styleObj = { + backgroundColor: '#4CAF50', + color: '#fff!important', + padding: '15px', + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + fontSize: '20px', + } + const styleObjUl = { + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + width: '1100px', + } + const styleA = { + color: 'white', + fontSize: '30px', + textDecoration: 'none', + } + + const handleHomeClick = (e) => { + e.preventDefault(); + onHomeClick(); + }; + + const handleCartClick = (e) => { + e.preventDefault(); + setShowCart(true); // Set showCart to true when cart icon is clicked + }; + const handlePlantsClick = (e) => { + e.preventDefault(); + setShowCart(false); // Hide the cart when navigating to About Us + }; + + const handleContinueShopping = (e) => { + e.preventDefault(); + setShowCart(false); + }; const plantsArray = [ { @@ -248,60 +313,6 @@ function ProductList({ onHomeClick }) { ] } ]; - const styleObj = { - backgroundColor: '#4CAF50', - color: '#fff!important', - padding: '15px', - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - fontSize: '20px', - } - const styleObjUl = { - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - width: '1100px', - } - const styleA = { - color: 'white', - fontSize: '30px', - textDecoration: 'none', - } - - const handleHomeClick = (e) => { - e.preventDefault(); - onHomeClick(); - }; - - const handleCartClick = (e) => { - e.preventDefault(); - setShowCart(true); // Set showCart to true when cart icon is clicked - }; - const handlePlantsClick = (e) => { - e.preventDefault(); - setShowPlants(true); // Set showAboutUs to true when "About Us" link is clicked - setShowCart(false); // Hide the cart when navigating to About Us - }; - - const handleContinueShopping = (e) => { - e.preventDefault(); - setShowCart(false); - }; - - // Añade al carrito (normaliza qty para el slice) - const handleAddToCart = (product) => { - dispatch(addItem({ ...product, qty: 1 })); - // si usas el estado local addedToCart, márcalo aquí: - if (typeof setAddedToCart === 'function') { - setAddedToCart(prev => ({ ...prev, [product.id ?? product.name]: true })); - } - }; - - // Calcula la cantidad total de artículos en el carrito - const calculateTotalQuantity = () => { - return cartItems ? cartItems.reduce((total, item) => total + (item.qty ?? item.quantity ?? 0), 0) : 0; - }; return (
@@ -320,9 +331,16 @@ function ProductList({ onHomeClick }) {
+ {!showCart ? (
{plantsArray.map((category, index) => ( @@ -331,24 +349,25 @@ function ProductList({ onHomeClick }) {
{category.category}
- {category.plants.map((plant, plantIndex) => ( -
- {plant.name} + {category.plants.map((plant, plantIndex) => { + const key = plant.id ?? plant.name; + const inCart = cartItems.some(i => i.id === key || i.name === key); + return ( +
+ {plant.name}
{plant.name}
{plant.description}
{plant.cost}
-
- ))} +
+ ); + })}
))} From 5b1e4fcb2afcbea44304a85404e3d6bacbe3172f Mon Sep 17 00:00:00 2001 From: ximenabaquero Date: Thu, 4 Sep 2025 17:53:50 -0500 Subject: [PATCH 7/7] Add cart badge and mark items as added --- src/ProductList.jsx | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/ProductList.jsx b/src/ProductList.jsx index 5b3fcb6987..7fa05d1db2 100644 --- a/src/ProductList.jsx +++ b/src/ProductList.jsx @@ -332,14 +332,38 @@ function ProductList({ onHomeClick }) {
handlePlantsClick(e)} style={styleA}>Plants
- handleCartClick(e)} style={styleA}> -

{/* NO emoji, solo número */} - {calculateTotalQuantity()} -

-
+ handleCartClick(e)} style={{ textDecoration: 'none', color: 'white' }}> +
+ {/* cart icon (SVG) - visual only */} + + + + + + + {/* badge with count (number inside/over the cart) */} + + {calculateTotalQuantity()} +
+
+ {!showCart ? (