diff --git a/Screenshot 2024-04-29 at 16.52.53.png b/Screenshot 2024-04-29 at 16.52.53.png new file mode 100644 index 0000000..e88c37c Binary files /dev/null and b/Screenshot 2024-04-29 at 16.52.53.png differ diff --git a/src/App.jsx b/src/App.jsx index 03e658b..334ba7a 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,31 +1,19 @@ -import './styles/reset.css' -import './styles/index.css' +import "./styles/reset.css"; +import "./styles/index.css"; -import initialStoreItems from './store-items' +import Header from './Components/Header' +import Cart from './Components/Cart' +import { useState } from "react"; export default function App() { + const [cart, addToCart] = useState([]); + return ( <> -
-

Greengrocers

- -
-
-

Your Cart

-
- -
-
-
-

Total

-
-
- £0.00 -
-
-
+
+ + +
Icons made by
- ) + ); } diff --git a/src/Components/Cart.jsx b/src/Components/Cart.jsx new file mode 100644 index 0000000..f497e6e --- /dev/null +++ b/src/Components/Cart.jsx @@ -0,0 +1,19 @@ +/* eslint-disable react/prop-types */ +import CartCard from './CartCard' +import TotalPrice from './TotalPrice' + +export default function Cart ( {cart, addToCart}) { + return ( +
+

Your Cart

+
+
    + +
+
+
+ +
+
+ ) +} \ No newline at end of file diff --git a/src/Components/CartCard.jsx b/src/Components/CartCard.jsx new file mode 100644 index 0000000..88ff0c3 --- /dev/null +++ b/src/Components/CartCard.jsx @@ -0,0 +1,40 @@ +export default function Cart({ cart, addToCart }) { + + function handleClick(e, item) { + if (e.target.innerText === "+") { + item.quantity++; + } + if (e.target.innerText === "-") { + item.quantity--; + } + addToCart([...cart]); + } + + return cart.map((item, index) => { + if (item.quantity) { + return ( +
  • + {item.name} +

    {item.name}

    + + {item.quantity} + +
  • + ); + } + }); +} diff --git a/src/Components/Header.jsx b/src/Components/Header.jsx new file mode 100644 index 0000000..3f05ca0 --- /dev/null +++ b/src/Components/Header.jsx @@ -0,0 +1,28 @@ +/* eslint-disable react/prop-types */ +import TypeFilter from "./TypeFilter"; +import SortDropdown from "./SortDropdown"; +import initialStoreItems from "../store-items"; +import StoreCard from './StoreCard' +import { useState } from "react"; + +export default function Header( {cart, addToCart} ) { + const [filter, setFilter] = useState("all"); + const [sort, setSort] = useState(""); + + return ( +
    +

    Greengrocers

    + + +
      + +
    +
    + ); +} diff --git a/src/Components/SortDropdown.jsx b/src/Components/SortDropdown.jsx new file mode 100644 index 0000000..8ea0aff --- /dev/null +++ b/src/Components/SortDropdown.jsx @@ -0,0 +1,18 @@ +/* eslint-disable react/prop-types */ +export default function SortDropdown({ setSort }) { + + function handleChange(e) { + setSort(e.target.value) + } + + return ( +
    + + +
    + ); +} diff --git a/src/Components/StoreCard.jsx b/src/Components/StoreCard.jsx new file mode 100644 index 0000000..da192fb --- /dev/null +++ b/src/Components/StoreCard.jsx @@ -0,0 +1,61 @@ +import { useState } from "react"; + +export default function StoreCard({ + initialStoreItems, + addToCart, + cart, + filter, + sort, +}) { + const [itemDetailDisplay, setItemDetailDisplay] = useState(""); + + function handleClick(item) { + if (item.quantity) { + item.quantity++; + } else { + item.quantity = 1; + } + if (cart.includes(item)) { + addToCart([...cart]); + return; + } + addToCart([...cart, item]); + } + + function handleImgClick(item) { + itemDetailDisplay === item.name ? setItemDetailDisplay('') : setItemDetailDisplay(item.name) + + } + + let filteredItems; + + if (filter !== "all") { + filteredItems = initialStoreItems.filter((item) => item.type === filter); + } else { + filteredItems = initialStoreItems; + } + + if (sort) { + if (sort === "name") { + filteredItems.sort((a, b) => a.name.localeCompare(b.name)); + } else { + filteredItems.sort((a, b) => a.price - b.price); + } + } + + return filteredItems.map((item, index) => { + return ( +
  • +
    + handleImgClick(item)} + src={`/assets/icons/${item.id}.svg`} + alt={item.name} + /> +
    + {item.name === itemDetailDisplay &&

    {item.description}

    } + +
  • + ); + }); +} diff --git a/src/Components/TotalPrice.jsx b/src/Components/TotalPrice.jsx new file mode 100644 index 0000000..d62f758 --- /dev/null +++ b/src/Components/TotalPrice.jsx @@ -0,0 +1,23 @@ +/* eslint-disable react/prop-types */ + +export default function TotalPrice({ cart }) { + + function getTotalPrice () { + let runningTotal = 0 + cart.forEach((item) => { + runningTotal += (item.quantity * item.price) + }) + return runningTotal + } + + return ( + <> +
    +

    Total

    +
    +
    + £{getTotalPrice().toFixed(2)} +
    + + ); +} diff --git a/src/Components/TypeFilter.jsx b/src/Components/TypeFilter.jsx new file mode 100644 index 0000000..3f61e03 --- /dev/null +++ b/src/Components/TypeFilter.jsx @@ -0,0 +1,18 @@ +/* eslint-disable react/prop-types */ +export default function TypeFilter ( {setFilter}) { + + function handleChange (e) { + setFilter(e.target.value) + } + + return ( +
    + + +
    + ) +} \ No newline at end of file diff --git a/src/store-items.js b/src/store-items.js index 96dd2ea..e11aba1 100644 --- a/src/store-items.js +++ b/src/store-items.js @@ -3,70 +3,70 @@ const storeItems = [ { id: "001-beetroot", name: "beetroot", - price: 0.35, + price: 0.15, description: "The beetroot is the taproot portion of a beet plant, usually known in North America as beets while the vegetable is referred to as beetroot in British English, and also known as the table beet, garden beet, red beet, dinner beet or golden beet.", type: "vegetable" }, { id: "002-carrot", name: "carrot", - price: 0.35, + price: 0.45, description: "The carrot is a root vegetable, typically orange in color, though heirloom variants including purple, black, red, white, and yellow cultivars exist, all of which are domesticated forms of the wild carrot, Daucus carota, native to Europe and Southwestern Asia.", type: "vegetable" }, { id: "003-apple", name: "apple", - price: 0.35, + price: 0.25, description: "An apple is a round, edible fruit produced by an apple tree (Malus spp., among them the domestic or orchard apple; Malus domestica).", type: "fruit" }, { id: "004-apricot", name: "apricot", - price: 0.35, + price: 0.15, description: "An apricot is a fruit, or the tree that bears the fruit, of several species in the genus Prunus.", type: "fruit" }, { id: "005-avocado", name: "avocado", - price: 0.35, + price: 0.40, description: "The avocado, alligator pear or avocado pear (Persea americana) is a medium-sized, evergreen tree in the laurel family (Lauraceae).", type: "fruit" }, { id: "006-bananas", name: "bananas", - price: 0.35, + price: 1.35, description: "A banana is an elongated, edible fruit – botanically a berry – produced by several kinds of large herbaceous flowering plants in the genus Musa.", type: "fruit" }, { id: "007-bell-pepper", name: "bell pepper", - price: 0.35, + price: 0.50, description: "The bell pepper (also known as sweet pepper, pepper, capsicum /ˈkæpsɪkəm/ or in some places, mangoes) is the fruit of plants in the Grossum Group of the species Capsicum annuum.", type: "fruit" }, { id: "008-berry", name: "berry", - price: 0.35, + price: 0.14, description: "A berry is a small, pulpy, and often edible fruit. Typically, berries are juicy, rounded, brightly colored, sweet, sour or tart, and do not have a stone or pit, although many pips or seeds may be present.", type: "fruit" }, { id: "009-blueberry", name: "blueberry", - price: 0.35, + price: 0.57, description: "Blueberry is a widely distributed and widespread group of perennial flowering plant with blue or purple berries.", type: "fruit" }, { id: "010-eggplant", name: "eggplant", - price: 0.35, + price: 0.51, description: "Eggplant, aubergine, brinjal, or baigan is a plant species in the nightshade family Solanaceae. Solanum melongena is grown worldwide for its edible fruit.", type: "vegetable" } diff --git a/src/styles/index.css b/src/styles/index.css index 0a04c2b..9f4fd81 100644 --- a/src/styles/index.css +++ b/src/styles/index.css @@ -31,7 +31,7 @@ button { background-color: #e7f4ea; } -#store h1 { +#store h1, #store .filter-form, #store .sort-form { text-align: center; } @@ -53,6 +53,14 @@ button { height: 125px; } +.item-detail { + font-size: 7px; + background-color: white; + border-radius: 5px; + padding: 5px; + text-align: center; +} + @media only screen and (max-width: 600px) { .store--item-list { grid-template-columns: repeat(3, 125px); @@ -162,6 +170,10 @@ button { font-weight: bold; } +#in-cart-product-name::first-letter { + text-transform: uppercase; +} + /* Total */ .total-section { @@ -176,6 +188,8 @@ button { font-weight: bold; } + + @media only screen and (max-width: 450px) { .total-section { border-top: 2px solid #00675b;