From 2993dfa79876c4f2a9a81d0f4ebead9fc50a5469 Mon Sep 17 00:00:00 2001 From: itsalifarrukh Date: Mon, 8 Dec 2025 01:00:21 +0500 Subject: [PATCH] Refactor CartItem and CartSlice components; enhance cart functionality and UI - Updated CartItem component to improve layout and functionality, including total amount calculation and item removal. - Added checkout alert and continue shopping button functionality. - Enhanced CartSlice with clearCart action and improved quantity update logic. - Introduced Header component with navigation links and cart item count display. - Created Header.css for styling the header and navigation. - Refactored ProductList component to streamline product display and add to cart functionality. - Improved ProductList.css for better layout and responsiveness. - Updated main.jsx and store.js for consistent import style and structure. - Removed unnecessary styles and code from ProductList. - Adjusted Vite configuration for cleaner setup. --- package-lock.json | 72 +++++++- package.json | 3 +- src/App.css | 22 ++- src/App.jsx | 115 +++++++----- src/CartItem.css | 411 +++++++++++++++++++++++++----------------- src/CartItem.jsx | 162 ++++++++++++++--- src/CartSlice.jsx | 44 +++-- src/Header.css | 159 +++++++++++++++++ src/Header.jsx | 51 ++++++ src/ProductList.css | 369 +++++++++++++++----------------------- src/ProductList.jsx | 423 +++++++++++++++----------------------------- src/main.jsx | 21 +-- src/store.js | 16 +- vite.config.js | 7 +- 14 files changed, 1102 insertions(+), 773 deletions(-) create mode 100644 src/Header.css create mode 100644 src/Header.jsx diff --git a/package-lock.json b/package-lock.json index af7843d848..cb1ab75e2a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,8 @@ "@reduxjs/toolkit": "^2.2.3", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-redux": "^9.1.1" + "react-redux": "^9.1.1", + "react-router-dom": "^7.10.1" }, "devDependencies": { "@types/react": "^18.2.66", @@ -74,6 +75,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", "dev": true, + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.2", @@ -1219,6 +1221,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.0.tgz", "integrity": "sha512-DiUcKjzE6soLyln8NNZmyhcQjVv+WsUIFSqetMN0p8927OztKT4VTfFTqsbAi5oAGIcgOmOajlfBqyptDDjZRw==", "devOptional": true, + "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -1268,6 +1271,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1543,6 +1547,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001587", "electron-to-chromium": "^1.4.668", @@ -1660,6 +1665,19 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -2031,6 +2049,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -3829,6 +3848,7 @@ "version": "18.3.0", "resolved": "https://registry.npmjs.org/react/-/react-18.3.0.tgz", "integrity": "sha512-RPutkJftSAldDibyrjuku7q11d3oy6wKOyPe5K1HA/HwwrXcEqBdHsLypkC2FFYjP7bPUa6gbzSBhw4sY2JcDg==", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -3840,6 +3860,7 @@ "version": "18.3.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.0.tgz", "integrity": "sha512-zaKdLBftQJnvb7FtDIpZtsAIb2MZU087RM8bRDZU8LVCCFYjPTsDZJNFUWPcVz3HFSN1n/caxi0ca4B/aaVQGQ==", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.1" @@ -3858,6 +3879,7 @@ "version": "9.1.1", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.1.tgz", "integrity": "sha512-5ynfGDzxxsoV73+4czQM56qF43vsmgJsO22rmAvU5tZT2z5Xow/A2uhhxwXuGTxgdReF3zcp7A80gma2onRs1A==", + "peer": true, "dependencies": { "@types/use-sync-external-store": "^0.0.3", "use-sync-external-store": "^1.0.0" @@ -3889,10 +3911,49 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.10.1.tgz", + "integrity": "sha512-gHL89dRa3kwlUYtRQ+m8NmxGI6CgqN+k4XyGjwcFoQwwCWF6xXpOCUlDovkXClS0d0XJN/5q7kc5W3kiFEd0Yw==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.10.1.tgz", + "integrity": "sha512-JNBANI6ChGVjA5bwsUIwJk7LHKmqB4JYnYfzFwyp2t12Izva11elds2jx7Yfoup2zssedntwU0oZ5DEmk5Sdaw==", + "license": "MIT", + "dependencies": { + "react-router": "7.10.1" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, "node_modules/redux": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", - "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "peer": true }, "node_modules/redux-thunk": { "version": "3.1.0", @@ -4107,6 +4168,12 @@ "semver": "bin/semver.js" } }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -4522,6 +4589,7 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.10.tgz", "integrity": "sha512-PAzgUZbP7msvQvqdSD+ErD5qGnSFiGOoWmV5yAKUEI0kdhjbH6nMWVyZQC/hSc4aXwc0oJ9aEdIiF9Oje0JFCw==", "dev": true, + "peer": true, "dependencies": { "esbuild": "^0.20.1", "postcss": "^8.4.38", diff --git a/package.json b/package.json index b7d4c1d1d4..5f909e505e 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "@reduxjs/toolkit": "^2.2.3", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-redux": "^9.1.1" + "react-redux": "^9.1.1", + "react-router-dom": "^7.10.1" }, "devDependencies": { "@types/react": "^18.2.66", diff --git a/src/App.css b/src/App.css index 88bb5690eb..b3e058e65c 100644 --- a/src/App.css +++ b/src/App.css @@ -3,7 +3,20 @@ margin: 0; padding: 0; box-sizing: border-box; - overflow: hidden; +} + +body { + overflow-x: hidden; +} + +.app-container { + min-height: 100vh; +} + +.main-content { + padding-top: 0; + min-height: calc(100vh - 100px); + overflow-y: auto; } .landing-page { @@ -11,6 +24,7 @@ width: 100vw; height: 100vh; background-color: #f8f8f8; + overflow: hidden; } .background-image { @@ -24,20 +38,21 @@ background-position: center; filter: brightness(0.8); } + .content { display: flex; align-items: center; justify-content: center; height: 100vh; width: 100vw; - top: 100px; + top: 100px; backdrop-filter: blur(4px); background-color: rgba(0,0,0,0.5); gap: 20px; } .landing_content { - margin-top: 430px; + margin-top: 430px; margin-left: 100px; transform: translate(-50%, -50%); z-index: 1; @@ -113,6 +128,7 @@ .product-list-container.visible { top: 0; } + /* LandingPage.css */ @media screen and (max-width: 768px) { .content { diff --git a/src/App.jsx b/src/App.jsx index 799372d75d..4e69a644f7 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,49 +1,82 @@ - -import React, { useState } from 'react'; -import ProductList from './ProductList'; -import './App.css'; -import AboutUs from './AboutUs'; +import React from "react"; +import { BrowserRouter as Router, Routes, Route, Link } from "react-router-dom"; +import ProductList from "./ProductList"; +import CartItem from "./CartItem"; +import Header from "./Header"; +import "./App.css"; function App() { - - const [showProductList, setShowProductList] = useState(false); - - const handleGetStartedClick = () => { - setShowProductList(true); - }; - - const handleHomeClick = () => { - setShowProductList(false); - }; - return ( -
-
-
-
-
-

Welcome To Paradise Nursery

-
-

Where Green Meets Serenity

- - -
-
- -
-
- + +
+ + +
+
+
+

Welcome To Paradise Nursery

+
+

Where Green Meets Serenity

+ + + +
+
+
+

+ Welcome to Paradise Nursery, where green meets serenity! +

+

+ At Paradise Nursery, we are passionate about bringing + nature closer to you. Our mission is to provide a wide + range of high-quality plants that not only enhance the + beauty of your surroundings but also contribute to a + healthier and more sustainable lifestyle. +

+

+ Our team of experts is dedicated to ensuring that each + plant meets our strict standards of quality and care. + Whether you're a seasoned gardener or just starting your + green journey, we're here to support you every step of + the way. +

+
+
+
+
+ } + /> + +
+
+ +
+ + } + /> + +
+
+ +
+ + } + /> +
-
- -
-
+ ); } export default App; - - - diff --git a/src/CartItem.css b/src/CartItem.css index 66a6a4061f..8e0f7e0d85 100644 --- a/src/CartItem.css +++ b/src/CartItem.css @@ -1,62 +1,145 @@ /* CartItem.css */ -/* CartItem.css */ + +.cart-container { + max-width: 1200px; + margin: 20px auto; + padding: 20px; + background: #f9f9f9; + border-radius: 10px; + box-shadow: 0 4px 8px rgba(0,0,0,0.1); +} + +.cart-summary-header { + background: white; + padding: 15px; + border-radius: 8px; + margin-bottom: 20px; + box-shadow: 0 2px 4px rgba(0,0,0,0.05); +} + +.cart-summary-info { + display: flex; + justify-content: space-between; + align-items: center; + font-size: 18px; +} + +.cart-summary-info span { + padding: 8px 16px; + background: #e8f5e9; + border-radius: 5px; +} + +.cart-items-wrapper { + display: flex; + flex-direction: column; + gap: 20px; +} .cart-item { display: flex; - border-bottom: 1px solid #ccc; - padding: 10px 0; background-color: white; - width: 500px; + border-radius: 10px; + padding: 20px; + box-shadow: 0 2px 8px rgba(0,0,0,0.1); + transition: transform 0.2s ease; + width: 100%; gap: 30px; + align-items: center; +} + +.cart-item:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0,0,0,0.15); } .cart-item-image { - width: 200px; - height: 200px; - /* object-fit: contain; */ - margin-right: 20px; + width: 180px; + height: 180px; + object-fit: cover; + border-radius: 8px; + border: 2px solid #e0e0e0; } .cart-item-details { flex-grow: 1; + display: flex; + flex-direction: column; + gap: 8px; } .cart-item-name { font-weight: bold; + font-size: 24px; + color: #2e7d32; margin-bottom: 5px; - font-size: 25px; } -.cart-item-cost { +.cart-item-description { + color: #666; + font-size: 14px; margin-bottom: 10px; - margin-top: 10px; +} + +.cart-item-cost { + font-size: 18px; + color: #388e3c; + font-weight: 600; + margin-bottom: 15px; } .cart-item-quantity { display: flex; align-items: center; + gap: 10px; margin-bottom: 15px; } .cart-item-button { background-color: #f0f0f0; - border: 1px solid lightgrey; + border: 1px solid #ddd; color: #333; - font-size: 18px; + font-size: 20px; cursor: pointer; - padding: 5px 10px; - margin: 0 5px; + padding: 5px 15px; border-radius: 5px; + transition: all 0.3s ease; + min-width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; +} + +.cart-item-button:hover { + background-color: #e0e0e0; +} + +.cart-item-button.cart-item-button-dec { + background-color: #ffebee; + border-color: #ffcdd2; +} + +.cart-item-button.cart-item-button-inc { + background-color: #e8f5e9; + border-color: #c8e6c9; } .cart-item-quantity-value { - font-size: 16px; + font-size: 20px; font-weight: bold; margin: 0 10px; + min-width: 40px; + text-align: center; } .cart-item-total { font-weight: bold; + font-size: 20px; + color: #2e7d32; + margin-top: 10px; + padding-top: 10px; + border-top: 2px dashed #e0e0e0; } .cart-item-delete { @@ -65,179 +148,177 @@ color: #fff; font-size: 14px; cursor: pointer; - padding: 10px 15px; - margin-top: 10px; - border-radius: 10px; + padding: 10px 20px; + border-radius: 5px; + margin-left: 20px; + transition: all 0.3s ease; } .cart-item-delete:hover { background-color: #cc0000; + transform: scale(1.05); } -/* .cart-item-button-dec{ - background-color: red; + +.cart-footer { + background: white; + padding: 25px; + border-radius: 10px; + margin-top: 30px; + box-shadow: 0 2px 8px rgba(0,0,0,0.1); } -.cart-item-button-inc{ - background-color: green; -} */ -@media (max-width: 768px) { - .cart-item { - flex-direction: column; /* Change flex direction to stack items vertically */ - align-items: flex-start; /* Align items to the start of the container */ - width: 100%; /* Set width to full width */ - } - .cart-item-image { - width: 100%; /* Set image width to full width */ - height: auto; /* Allow image height to adjust proportionally */ - margin-right: 0; /* Remove margin */ - margin-bottom: 10px; /* Add margin bottom for spacing */ - } +.order-summary { + max-width: 400px; + margin: 0 auto 30px; +} - .cart-item-details { - width: 100%; /* Set details width to full width */ - } +.order-summary h3 { + color: #2e7d32; + margin-bottom: 20px; + text-align: center; + font-size: 24px; + padding-bottom: 10px; + border-bottom: 2px solid #e0e0e0; +} - .cart-item-quantity { - margin-top: 10px; /* Add margin top for spacing */ - } +.summary-row { + display: flex; + justify-content: space-between; + padding: 12px 0; + border-bottom: 1px solid #e0e0e0; + color: #555; + font-size: 16px; } -.cart-item { - display: flex; - border-bottom: 1px solid #ccc; - padding: 10px 0; - background-color: white; - width: 500px; - gap: 30px; + +.summary-row.total { + font-size: 20px; + font-weight: 700; + color: #2e7d32; + border-top: 2px solid #4caf50; + margin-top: 15px; + padding-top: 15px; +} + +.cart-buttons { + display: flex; + justify-content: center; + gap: 30px; + flex-wrap: wrap; +} + +.continue-shopping-btn, +.checkout-btn { + padding: 15px 40px; + border-radius: 8px; + font-size: 18px; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + min-width: 220px; + border: none; +} + +.continue-shopping-btn { + background: white; + color: #2e7d32; + border: 2px solid #2e7d32; +} + +.continue-shopping-btn:hover { + background: #e8f5e9; + transform: translateY(-2px); + box-shadow: 0 4px 8px rgba(46, 125, 50, 0.2); +} + +.checkout-btn { + background: linear-gradient(135deg, #2e7d32 0%, #1b5e20 100%); + color: white; +} + +.checkout-btn:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(46, 125, 50, 0.3); +} + +.get-started-button { + padding: 12px 40px; + font-size: 18px; + border: none; + border-radius: 8px; + background-color: #4caf50; + color: white; + cursor: pointer; + transition: background-color 0.3s ease; + margin: 20px auto; + display: block; +} + +.get-started-button:hover { + background-color: #45a049; + transform: translateY(-2px); +} + +.get-started-button1 { + padding: 15px 75px; + font-size: 23px; + border: none; + border-radius: 8px; + background: linear-gradient(135deg, #2e7d32 0%, #1b5e20 100%); + color: white; + cursor: pointer; + transition: all 0.3s ease; + margin-top: 20px; + box-shadow: 0 4px 8px rgba(0,0,0,0.1); +} + +.get-started-button1:hover { + transform: translateY(-2px); + box-shadow: 0 6px 12px rgba(0,0,0,0.15); +} + +@media (max-width: 768px) { + .cart-item { + flex-direction: column; + align-items: center; + text-align: center; + gap: 20px; } - + .cart-item-image { width: 200px; height: 200px; - /* object-fit: contain; */ - margin-right: 20px; - } - - .cart-item-details { - flex-grow: 1; - } - - .cart-item-name { - font-weight: bold; - margin-bottom: 5px; - font-size: 25px; + margin: 0 auto; } - - .cart-item-cost { - margin-bottom: 10px; - margin-top: 10px; - } - + .cart-item-quantity { - display: flex; - align-items: center; - margin-bottom: 15px; - } - - .cart-item-button { - background-color: #f0f0f0; - border: 1px solid lightgrey; - color: #333; - font-size: 18px; - cursor: pointer; - padding: 5px 10px; - margin: 0 5px; - border-radius: 5px; - } - - .cart-item-quantity-value { - font-size: 16px; - font-weight: bold; - margin: 0 10px; - } - - .cart-item-total { - font-weight: bold; + justify-content: center; + flex-wrap: wrap; } - + .cart-item-delete { - background-color: #ff6961; - border: none; - color: #fff; - font-size: 14px; - cursor: pointer; - padding: 10px 15px; + margin-left: 0; margin-top: 10px; - border-radius: 10px; - } - - .cart-item-delete:hover { - background-color: #cc0000; } - /* .cart-item-button-dec{ - background-color: red; + + .cart-buttons { + flex-direction: column; + align-items: center; + gap: 15px; } - .cart-item-button-inc{ - background-color: green; - } */ - @media (max-width: 768px) { - .cart-item { - flex-direction: column; /* Change flex direction to stack items vertically */ - align-items: flex-start; /* Align items to the start of the container */ - width: 100%; /* Set width to full width */ - } - - .cart-item-image { - width: 100%; /* Set image width to full width */ - height: auto; /* Allow image height to adjust proportionally */ - margin-right: 0; /* Remove margin */ - margin-bottom: 10px; /* Add margin bottom for spacing */ - } - - .cart-item-details { - width: 100%; /* Set details width to full width */ - } - - .cart-item-quantity { - margin-top: 10px; /* Add margin top for spacing */ - } + + .continue-shopping-btn, + .checkout-btn { + width: 100%; + max-width: 300px; } - - .cart-container{ - /* text-align: center; */ - display: flex; - align-items: center; + .cart-summary-info { flex-direction: column; - justify-content: center; - gap: 20px; - margin-top: 20px; - } - .total_cart_amount{ - font-size: 20px; - font-weight: 900; - } -.continue_shopping_btn{ - margin-top: -50px; -} - @media (max-width: 768px) { - .cart-container { - padding: 10px; /* Reduce padding */ - } - - .total_cart_amount { - font-size: 18px; /* Reduce font size */ - } + gap: 10px; + text-align: center; } - .get-started-button1 { - padding: 15px 75px; - font-size: 23px; - border: none; - border-radius: 5px; - background-color: #4caf50; - color: white; - cursor: pointer; - transition: background-color 0.3s ease; - margin-top: 40px; + .cart-summary-info span { + width: 100%; } - \ No newline at end of file +} \ No newline at end of file diff --git a/src/CartItem.jsx b/src/CartItem.jsx index e06317433f..7e5632548c 100644 --- a/src/CartItem.jsx +++ b/src/CartItem.jsx @@ -1,68 +1,176 @@ -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 { removeItem, updateQuantity } from "./CartSlice"; +import { useNavigate } from "react-router-dom"; +import "./CartItem.css"; -const CartItem = ({ onContinueShopping }) => { - const cart = useSelector(state => state.cart.items); +const CartItem = () => { + const cart = useSelector((state) => state.cart.items); const dispatch = useDispatch(); + const navigate = useNavigate(); // Calculate total amount for all products in the cart const calculateTotalAmount = () => { - + let total = 0; + cart.forEach((item) => { + const price = parseFloat(item.cost.substring(1)); // Remove the dollar sign and convert to number + total += price * item.quantity; + }); + return total.toFixed(2); }; const handleContinueShopping = (e) => { - + navigate("/plants"); }; - - const handleIncrement = (item) => { + dispatch( + updateQuantity({ + name: item.name, + amount: item.quantity + 1, + }) + ); }; const handleDecrement = (item) => { - + if (item.quantity > 1) { + dispatch( + updateQuantity({ + name: item.name, + amount: item.quantity - 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 price = parseFloat(item.cost.substring(1)); + return (price * item.quantity).toFixed(2); }; + const handleCheckout = () => { + alert( + "Thank you for your purchase! Your order total is $" + + calculateTotalAmount() + ); + }; + + const totalItems = cart.reduce((total, item) => total + item.quantity, 0); + + if (cart.length === 0) { + return ( +
+

+ Your Shopping Cart is Empty +

+
+ +
+
+ ); + } + return (
-

Total Cart Amount: ${calculateTotalAmount()}

-
- {cart.map(item => ( +

+ Shopping Cart +

+ +
+
+ + Total Items: {totalItems} + + + Total Amount: ${calculateTotalAmount()} + +
+
+ +
+ {cart.map((item) => (
{item.name}
{item.name}
-
{item.cost}
+
{item.description}
+
{item.cost} each
- - {item.quantity} - + + + {item.quantity} + + + +
+
+ Total: ${calculateTotalCost(item)}
-
Total: ${calculateTotalCost(item)}
-
))}
-
-
- -
- + +
+
+

Order Summary

+
+ Subtotal ({totalItems} items): + ${calculateTotalAmount()} +
+
+ Shipping: + $5.99 +
+
+ Total: + + ${(parseFloat(calculateTotalAmount()) + 5.99).toFixed(2)} + +
+
+ +
+ + +
); }; export default CartItem; - - diff --git a/src/CartSlice.jsx b/src/CartSlice.jsx index 32b8761ed0..08f12798c5 100644 --- a/src/CartSlice.jsx +++ b/src/CartSlice.jsx @@ -1,23 +1,43 @@ -import { createSlice } from '@reduxjs/toolkit'; +import { createSlice } from "@reduxjs/toolkit"; -export const CartSlice = createSlice({ - name: 'cart', - initialState: { - items: [], // Initialize items as an empty array - }, +const initialState = { + items: [], +}; + +const cartSlice = createSlice({ + name: "cart", + initialState, reducers: { addItem: (state, action) => { - + const existingItem = state.items.find( + (item) => item.name === action.payload.name + ); + if (existingItem) { + existingItem.quantity += 1; + } else { + state.items.push({ ...action.payload, quantity: 1 }); + } }, removeItem: (state, action) => { + state.items = state.items.filter((item) => item.name !== action.payload); }, updateQuantity: (state, action) => { - - + const { name, amount } = action.payload; + const item = state.items.find((item) => item.name === name); + if (item) { + item.quantity = amount; + // Remove item if quantity becomes 0 + if (item.quantity <= 0) { + state.items = state.items.filter((item) => item.name !== name); + } + } + }, + clearCart: (state) => { + state.items = []; }, }, }); -export const { addItem, removeItem, updateQuantity } = CartSlice.actions; - -export default CartSlice.reducer; +export const { addItem, removeItem, updateQuantity, clearCart } = + cartSlice.actions; +export default cartSlice.reducer; diff --git a/src/Header.css b/src/Header.css new file mode 100644 index 0000000000..60a218c6bb --- /dev/null +++ b/src/Header.css @@ -0,0 +1,159 @@ +/* Header.css */ + +.navbar { + background: linear-gradient(135deg, #2e7d32 0%, #1b5e20 100%); + color: white; + padding: 15px 0; + position: sticky; + top: 0; + z-index: 1000; + box-shadow: 0 2px 10px rgba(0,0,0,0.1); +} + +.header-container { + max-width: 1200px; + margin: 0 auto; + padding: 0 20px; + display: flex; + justify-content: space-between; + align-items: center; +} + +.tag { + display: flex; + align-items: center; +} + +.tag_home_link { + display: flex; + align-items: center; + text-decoration: none; + color: white; + gap: 15px; + transition: transform 0.3s ease; +} + +.tag_home_link:hover { + transform: scale(1.05); +} + +.tag_home_link img { + height: 60px; + width: 60px; + border-radius: 50%; + border: 3px solid rgba(255, 255, 255, 0.2); +} + +.tag_home_link h3 { + font-size: 28px; + font-weight: 700; + margin: 0; + text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2); +} + +.luxury { + display: flex; + align-items: center; +} + +.ul { + list-style: none; + display: flex; + gap: 40px; + margin: 0; + padding: 0; +} + +.nav-links { + display: flex; + align-items: center; + gap: 40px; +} + +.nav-links li { + margin: 0; +} + +.nav-links a { + color: white; + text-decoration: none; + font-size: 18px; + font-weight: 600; + padding: 8px 16px; + border-radius: 5px; + transition: all 0.3s ease; + display: flex; + align-items: center; + gap: 8px; +} + +.nav-links a:hover { + background-color: rgba(255, 255, 255, 0.1); + transform: translateY(-2px); +} + +.cart-link-wrapper { + position: relative; +} + +.cart-link { + position: relative; + padding: 8px 20px !important; + background: rgba(255, 255, 255, 0.1); + border-radius: 25px; +} + +.cart-icon { + font-size: 24px; +} + +.cart-text { + font-size: 16px; +} + +.cart_quantity_count { + position: absolute; + top: -8px; + right: 5px; + background-color: #ff5252; + color: white; + border-radius: 50%; + width: 24px; + height: 24px; + display: flex; + align-items: center; + justify-content: center; + font-size: 14px; + font-weight: bold; + box-shadow: 0 2px 4px rgba(0,0,0,0.2); +} + +@media (max-width: 768px) { + .header-container { + flex-direction: column; + gap: 15px; + padding: 15px; + } + + .nav-links { + gap: 20px; + } + + .ul { + gap: 20px; + } + + .nav-links a { + font-size: 16px; + padding: 6px 12px; + } + + .tag_home_link h3 { + font-size: 22px; + } + + .tag_home_link img { + height: 50px; + width: 50px; + } +} \ No newline at end of file diff --git a/src/Header.jsx b/src/Header.jsx new file mode 100644 index 0000000000..51754e95a4 --- /dev/null +++ b/src/Header.jsx @@ -0,0 +1,51 @@ +import React from "react"; +import { Link } from "react-router-dom"; +import { useSelector } from "react-redux"; +import "./Header.css"; + +const Header = () => { + const cartItems = useSelector((state) => state.cart.items); + const totalItems = cartItems.reduce( + (total, item) => total + item.quantity, + 0 + ); + + return ( +
+
+
+ + logo +

Paradise Nursery

+ +
+ +
+
+ ); +}; + +export default Header; diff --git a/src/ProductList.css b/src/ProductList.css index 52f9c7a84f..65b8365192 100644 --- a/src/ProductList.css +++ b/src/ProductList.css @@ -1,252 +1,171 @@ -/* Reset some default styles */ -body, h1, ul { - margin: 0; - padding: 0; -} - -/* Set a background color */ -body { - font-family: Arial, sans-serif; - background-color: #f0f0f0; -} - -/* Navbar */ -.navbar { - background-color: #4CAF50; - color: #fff!important; - padding: 15px; - display: flex; - justify-content: space-between; - align-items: center; - font-size: 20px; -} +/* ProductList.css */ -.navbar .ul { +.product-list-container { + padding: 20px; + } + + .product-header { display: flex; justify-content: space-between; align-items: center; - width: 1100px; -} - -.navbar li { - margin-right: 30px; -} - -.navbar .ul div a { - color: white; - font-size: 30px; - text-decoration: none; - -} - -/* Product Grid */ -.product-grid { - display:flex; - flex-direction: column; - width: 100vw; - align-items: center; - justify-content: center; -} -.product-list { - display: flex; - flex-wrap: wrap; - gap: 50px; - /* background-color: pink; */ - /* justify-content: space-between; */ + margin-bottom: 30px; padding: 20px; - width: 100%; - align-items: center; - justify-content: center; -} - -/* Product Card */ -.product-card { - flex: 0 0 calc(33.33% - 20px); /* Adjust width for 3 cards per row with 20px gap */ - max-width: calc(26.33% - 20px); /* Adjust max-width for 3 cards per row with 20px gap */ + background: white; + border-radius: 10px; + box-shadow: 0 2px 10px rgba(0,0,0,0.05); + } + + .plantname_heading { + flex: 1; + } + + .plant_heading { + text-align: left; + } + + .plant_heading h2 { + color: #2e7d32; + font-size: 32px; + margin: 0; + padding: 0; + border: none; + } + + .cart-summary { + background: #e8f5e9; + padding: 12px 25px; + border-radius: 25px; + font-size: 18px; + color: #2e7d32; + font-weight: 600; + box-shadow: 0 2px 8px rgba(46, 125, 50, 0.2); + } + + .category-section { + margin-bottom: 40px; + } + + .category-section h3 { + color: #388e3c; + font-size: 26px; margin-bottom: 20px; + padding-bottom: 10px; + border-bottom: 3px solid #c8e6c9; + } + + .product-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + gap: 30px; + } + + .product-card { + background: white; + border-radius: 12px; + overflow: hidden; + box-shadow: 0 4px 15px rgba(0,0,0,0.1); + transition: all 0.3s ease; + } + + .product-card:hover { + transform: translateY(-8px); + box-shadow: 0 12px 30px rgba(0,0,0,0.15); + } + + .product-image { + width: 100%; + height: 250px; + object-fit: cover; + border-bottom: 3px solid #e8f5e9; + } + + .product-info { padding: 20px; - background-color: #fff; - border: 1px solid #ccc; - border-radius: 5px; - text-align: center; - position: relative; - - gap: 20px; -} - -/* Pseudo-classes - Hover effect on product button */ -.product-card:hover { - transform: scale(1.05); - transition: transform 0.3s ease-in-out; - z-index: 1; -} - -.product-title { - font-weight: bold; - margin-bottom: 10px; -} - -.product-price { - color: #e74c3c; - font-size: 1.2rem; - margin-bottom: 10px; -} - -.product-image { - max-width: 100%; - height: 200px; /* Adjust height for better consistency */ -} - -.product-button { - background-color: #e74c3c; - color: #fff; - border: none; - padding: 10px 20px; - cursor: pointer; - transition: background-color 0.3s ease-in-out; - margin-top: 10px; -} - -.product-button:hover { - background-color: #c0392b; -} - -/* Pseudo-elements - Sale badge */ -.product-card::before { - content: "SALE"; - background-color: #e74c3c; - color: #fff; - position: absolute; - top: 0; - right: 0; - padding: 5px 10px; - border-radius: 0 0 0 5px; -} -.tag_home_link{ - display: flex; - /* background-color: red; */ - flex-direction: column; - align-items: center; - justify-content: center; - margin-left: 50px; - color: white; - text-decoration: none; + } + + .product-title { font-size: 20px; -} -.tag_home_link h3{ - font-size: 30px; -} -.tag a{ - text-decoration: none; -} -.tag { - width: 400px; - display: flex; - align-items: center; - justify-content: center; -} - -.tag img { - height: 70px; - width: 70px; - border-radius: 70%; - -} - -.luxury { + color: #2e7d32; + margin-bottom: 10px; + font-weight: 600; + } + + .description { + color: #666; + font-size: 14px; + line-height: 1.5; + margin-bottom: 15px; + min-height: 60px; + } + + .price-cart { display: flex; + justify-content: space-between; align-items: center; - justify-content: center; - width: 650px; - font-size: 19px; -} -.cart{ + margin-top: 15px; + } + + .price { + font-size: 24px; + font-weight: 700; + color: #2e7d32; + } + + .product-button { + background: linear-gradient(135deg, #4CAF50 0%, #2e7d32 100%); color: white; - display: flex; -} -.cart_quantity_count{ - margin-top: 16px; - /* background-color: red; */ - margin-left: 27px; - position: absolute; - font-size: 29px; - -} -.plantname_heading{ - display: flex; - align-items: center; - justify-content: center; - /* background-color: yellow; */ -} -.plant_heading{ - width: 400px; - text-align: center; - margin: 20px; - border: 1px solid rgb(5, 4, 4); - border-left: none; - border-right: none; - - -} -/* Add Media Query for responsiveness */ -@media (max-width: 768px) { - .product-card { - flex: 1 1 calc(50% - 20px); /* Adjust width for 2 cards per row with 20px gap on smaller screens */ - max-width: calc(50% - 20px); /* Adjust max-width for 2 cards per row with 20px gap on smaller screens */ - } -} -/* ProductList.css */ - -.product-button { - background-color: #4CAF50; /* Green */ border: none; - color: white; padding: 10px 20px; - text-align: center; - text-decoration: none; - display: inline-block; - font-size: 16px; - margin: 4px 2px; - transition-duration: 0.4s; + border-radius: 25px; cursor: pointer; + font-size: 16px; + font-weight: 600; + transition: all 0.3s ease; + min-width: 120px; } - .product-button:hover { - background-color: #45a049; + .product-button:hover:not(:disabled) { + transform: scale(1.05); + box-shadow: 0 4px 12px rgba(76, 175, 80, 0.3); } - .product-button.added-to-cart { - background-color: grey; /* Grey when product is added */ + .product-button:disabled { + background: linear-gradient(135deg, #757575 0%, #616161 100%); + cursor: not-allowed; + opacity: 0.8; } - @media (max-width: 1200px) { - .product-card { - flex: 1 1 calc(33.33% - 20px); /* Adjust width for 3 cards per row with 20px gap on medium screens */ - max-width: calc(33.33% - 20px); /* Adjust max-width for 3 cards per row with 20px gap on medium screens */ - } + + .added-to-cart { + background: linear-gradient(135deg, #757575 0%, #616161 100%); } + /* Responsive Design */ @media (max-width: 768px) { - .product-card { - flex: 1 1 calc(50% - 20px); /* Adjust width for 2 cards per row with 20px gap on small screens */ - max-width: calc(50% - 20px); /* Adjust max-width for 2 cards per row with 20px gap on small screens */ + .product-header { + flex-direction: column; + gap: 15px; + text-align: center; + } + + .plant_heading h2 { + font-size: 24px; + } + + .cart-summary { + font-size: 16px; + padding: 10px 20px; } - .navbar { - flex-direction: column; /* Change flex direction to stack items vertically */ - align-items: center; /* Align items to the center of the container */ - } - .tag { - margin-bottom: 20px; /* Add margin bottom for spacing */ - text-align: center; /* Align text to the center */ - } + .product-grid { + grid-template-columns: 1fr; + } - .ul { - display: flex; /* Set display to flex */ - flex-direction: column; /* Change flex direction to stack items vertically */ - gap: 10px; /* Add gap between items */ - } + .price-cart { + flex-direction: column; + gap: 15px; + } - .ul div { - text-align: center; /* Align text to the center */ - } + .product-button { + width: 100%; + } } \ No newline at end of file diff --git a/src/ProductList.jsx b/src/ProductList.jsx index 7682c04fc4..e00a2965cb 100644 --- a/src/ProductList.jsx +++ b/src/ProductList.jsx @@ -1,287 +1,158 @@ -import React, { useState, useEffect } from 'react'; -import './ProductList.css' -import CartItem from './CartItem'; -function ProductList({ onHomeClick }) { - const [showCart, setShowCart] = useState(false); - const [showPlants, setShowPlants] = useState(false); // State to control the visibility of the About Us page +import React, { useState } from "react"; +import { useDispatch, useSelector } from "react-redux"; +import { addItem } from "./CartSlice"; +import "./ProductList.css"; - const plantsArray = [ - { - category: "Air Purifying Plants", - plants: [ - { - 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" - }, - { - 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" - }, - { - 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" - }, - { - 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" - }, - { - 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" - }, - { - 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: [ - { - 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" - }, - { - 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" - }, - { - 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" - }, - { - 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" - }, - { - 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" - }, - { - 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: [ - { - 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" - }, - { - 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" - }, - { - 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" - }, - { - 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" - }, - { - 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" - }, - { - 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: [ - { - 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" - }, - { - 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" - }, - { - 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" - }, - { - 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" - }, - { - 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" - }, - { - 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: [ - { - 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" - }, - { - 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" - }, - { - 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" - }, - { - 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" - }, - { - 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" - }, - { - 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', - } +const ProductList = () => { + const dispatch = useDispatch(); + const cartItems = useSelector((state) => state.cart.items); + const [addedToCart, setAddedToCart] = useState({}); - const handleHomeClick = (e) => { - e.preventDefault(); - onHomeClick(); - }; + const plantsArray = [ + { + name: "Monstera Deliciosa", + category: "Tropical", + image: + "https://images.unsplash.com/photo-1614594975525-e45190c55d0b?w=400&h=400&fit=crop", + description: "Large, glossy leaves with unique holes.", + cost: "$45.99", + }, + { + name: "Snake Plant", + category: "Low Light", + image: + "https://images.unsplash.com/photo-1586985367371-7d672fdc5f33?w=400&h-400&fit=crop", + description: "Tall, sword-like leaves that purify air.", + cost: "$24.99", + }, + { + name: "Fiddle Leaf Fig", + category: "Statement", + image: + "https://images.unsplash.com/photo-1593482892290-5d188b9e56dc?w=400&h=400&fit=crop", + description: "Large, violin-shaped leaves.", + cost: "$59.99", + }, + { + name: "Peace Lily", + category: "Flowering", + image: + "https://images.unsplash.com/photo-1486312338219-ce68d2c6f44d?w=400&h=400&fit=crop", + description: "Elegant white flowers and dark green leaves.", + cost: "$32.99", + }, + { + name: "Spider Plant", + category: "Easy Care", + image: + "https://images.unsplash.com/photo-1485955900006-10f4d324d411?w=400&h=400&fit=crop", + description: "Produces baby plantlets on long stems.", + cost: "$18.99", + }, + { + name: "ZZ Plant", + category: "Low Maintenance", + image: + "https://images.unsplash.com/photo-1545243421-89e7c5d5d5c3?w=400&h=400&fit=crop", + description: "Glossy, dark green leaves that thrive in low light.", + cost: "$29.99", + }, + { + name: "Pothos", + category: "Trailing", + image: + "https://images.unsplash.com/photo-1517191434949-5e90cd67d2b6?w=400&h=400&fit=crop", + description: "Fast-growing vine with heart-shaped leaves.", + cost: "$16.99", + }, + { + name: "Aloe Vera", + category: "Succulent", + image: + "https://images.unsplash.com/photo-1525498128493-380d1990a112?w=400&h=400&fit=crop", + description: "Medicinal plant with soothing gel.", + cost: "$14.99", + }, + ]; - 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)); + setAddedToCart((prev) => ({ + ...prev, + [plant.name]: true, + })); - const handleContinueShopping = (e) => { - e.preventDefault(); - setShowCart(false); - }; - return ( -
-
-
- + // Re-enable button after 2 seconds + setTimeout(() => { + setAddedToCart((prev) => ({ + ...prev, + [plant.name]: false, + })); + }, 2000); + }; -
- -
- {!showCart ? ( -
+ // Calculate total items in cart + const totalItems = cartItems.reduce( + (total, item) => total + item.quantity, + 0 + ); + // Get unique categories + const categories = [...new Set(plantsArray.map((plant) => plant.category))]; + return ( +
+
+
+
+

Our Plant Collection

+
+
+
+ + Total Items in Cart: {totalItems} + +
+
+ + {categories.map((category) => ( +
+

{category} Plants

+
+ {plantsArray + .filter((plant) => plant.category === category) + .map((plant, index) => ( +
+ {plant.name} +
+

{plant.name}

+

{plant.description}

+
+ {plant.cost} + +
+
- ) : ( - - )} + ))} +
- ); -} + ))} +
+ ); +}; export default ProductList; diff --git a/src/main.jsx b/src/main.jsx index 9ea042ec2b..08b52de099 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -1,13 +1,14 @@ -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 ReactDOM from "react-dom/client"; +import { Provider } from "react-redux"; +import App from "./App.jsx"; +import store from "./store.js"; +import "./index.css"; + +ReactDOM.createRoot(document.getElementById("root")).render( - + - , -) + +); diff --git a/src/store.js b/src/store.js index 54d0d6d66e..07a2d8b3c8 100644 --- a/src/store.js +++ b/src/store.js @@ -1,8 +1,10 @@ -import { configureStore } from '@reduxjs/toolkit'; -import cartReducer from './CartSlice'; - const store = configureStore({ - reducer: { - cart: cartReducer, - }, +import { configureStore } from "@reduxjs/toolkit"; +import cartReducer from "./CartSlice"; + +const store = configureStore({ + reducer: { + cart: cartReducer, + }, }); -export default store + +export default store; diff --git a/vite.config.js b/vite.config.js index 4d190ae430..9cc50ead1c 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,8 +1,7 @@ -import { defineConfig } from 'vite' -import react from '@vitejs/plugin-react' +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; // https://vitejs.dev/config/ export default defineConfig({ - base: "/shoppingreact", plugins: [react()], -}) +});