Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added Screenshot 2024-04-29 at 16.52.53.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 12 additions & 24 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -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 (
<>
<header id="store">
<h1>Greengrocers</h1>
<ul className="item-list store--item-list">
</ul>
</header>
<main id="cart">
<h2>Your Cart</h2>
<div className="cart--item-list-container">
<ul className="item-list cart--item-list">
</ul>
</div>
<div className="total-section">
<div>
<h3>Total</h3>
</div>
<div>
<span className="total-number">£0.00</span>
</div>
</div>
</main>
<Header cart={cart} addToCart={addToCart}/>

<Cart cart={cart} addToCart={addToCart}/>

<div>
Icons made by
<a
Expand All @@ -40,5 +28,5 @@ export default function App() {
</a>
</div>
</>
)
);
}
19 changes: 19 additions & 0 deletions src/Components/Cart.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/* eslint-disable react/prop-types */
import CartCard from './CartCard'
import TotalPrice from './TotalPrice'

export default function Cart ( {cart, addToCart}) {
return (
<main id="cart">
<h2>Your Cart</h2>
<div className="cart--item-list-container">
<ul className="item-list cart--item-list">
<CartCard cart={cart} addToCart={addToCart} />
</ul>
</div>
<div className="total-section">
<TotalPrice cart={cart} />
</div>
</main>
)
}
40 changes: 40 additions & 0 deletions src/Components/CartCard.jsx
Original file line number Diff line number Diff line change
@@ -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 (
<li key={index}>
<img
src={`/assets/icons/${item.id}.svg`}
alt={item.name}
className="cart--item-icon"
/>
<p id="in-cart-product-name">{item.name}</p>
<button
onClick={(e) => handleClick(e, item)}
className="quantity-btn remove-btn center"
>
-
</button>
<span className="quantity-text center">{item.quantity}</span>
<button
onClick={(e) => handleClick(e, item)}
className="quantity-btn add-btn center"
>
+
</button>
</li>
);
}
});
}
28 changes: 28 additions & 0 deletions src/Components/Header.jsx
Original file line number Diff line number Diff line change
@@ -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 (
<header id="store">
<h1>Greengrocers</h1>
<TypeFilter setFilter={setFilter} />
<SortDropdown setSort={setSort} />
<ul className="item-list store--item-list">
<StoreCard
initialStoreItems={initialStoreItems}
addToCart={addToCart}
cart={cart}
filter={filter}
sort={sort}
/>
</ul>
</header>
);
}
18 changes: 18 additions & 0 deletions src/Components/SortDropdown.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* eslint-disable react/prop-types */
export default function SortDropdown({ setSort }) {

function handleChange(e) {
setSort(e.target.value)
}

return (
<div className="sort-form">
<label htmlFor="sort-dropdown">Sort by: </label>
<select onChange={(e) => handleChange(e)} name="sort-dropdown">
<option value="">-</option>
<option value="price">Price</option>
<option value="name">Name</option>
</select>
</div>
);
}
61 changes: 61 additions & 0 deletions src/Components/StoreCard.jsx
Original file line number Diff line number Diff line change
@@ -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 (
<li key={index}>
<div className="store--item-icon">
<img
onClick={() => handleImgClick(item)}
src={`/assets/icons/${item.id}.svg`}
alt={item.name}
/>
</div>
{item.name === itemDetailDisplay && <p className="item-detail">{item.description}</p>}
<button onClick={() => handleClick(item)}>Add to cart</button>
</li>
);
});
}
23 changes: 23 additions & 0 deletions src/Components/TotalPrice.jsx
Original file line number Diff line number Diff line change
@@ -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 (
<>
<div>
<h3>Total</h3>
</div>
<div>
<span className="total-number">£{getTotalPrice().toFixed(2)}</span>
</div>
</>
);
}
18 changes: 18 additions & 0 deletions src/Components/TypeFilter.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* eslint-disable react/prop-types */
export default function TypeFilter ( {setFilter}) {

function handleChange (e) {
setFilter(e.target.value)
}

return (
<div className="filter-form">
<label htmlFor="type-filter">Filter by type: </label>
<select onChange={(e) => handleChange(e)} name="type-filter">
<option value="all">All</option>
<option value="vegetable">Vegetables</option>
<option value="fruit">Fruit</option>
</select>
</div>
)
}
20 changes: 10 additions & 10 deletions src/store-items.js
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
Expand Down
16 changes: 15 additions & 1 deletion src/styles/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ button {
background-color: #e7f4ea;
}

#store h1 {
#store h1, #store .filter-form, #store .sort-form {
text-align: center;
}

Expand All @@ -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);
Expand Down Expand Up @@ -162,6 +170,10 @@ button {
font-weight: bold;
}

#in-cart-product-name::first-letter {
text-transform: uppercase;
}

/* Total */

.total-section {
Expand All @@ -176,6 +188,8 @@ button {
font-weight: bold;
}



@media only screen and (max-width: 450px) {
.total-section {
border-top: 2px solid #00675b;
Expand Down