Skip to content

Joan Nabuuma #124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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 component hierarchy.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

118 changes: 113 additions & 5 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,139 @@
import './styles/reset.css'
import './styles/index.css'
import "./styles/reset.css";
import "./styles/index.css";

import initialStoreItems from './store-items'
import initialStoreItems from "./store-items";

import Store from "./components/Store";
import { useState } from "react";
import Cart from "./components/Cart";

import Filter from "./components/Filter";
import Sorter from "./components/Sorter";

import Detail from "./components/Detail";

export default function App() {
const [storeFruits, setStoreFruits] = useState(initialStoreItems);
const [cartFruits, setCartFruits] = useState([]);
const [detailFruit, setDetailFruit] = useState(null);

const handleAddToCart = (id) => {
const index = cartFruits.findIndex((fruit) => fruit.id === id);
let updatedCartFruits = [];
let fruit = {};
if (index === -1) {
fruit = storeFruits.find((fruit) => fruit.id === id);
fruit = { ...fruit, quantity: 1 };
cartFruits.push(fruit);
} else {
fruit = cartFruits.find((fruit) => fruit.id === id);
fruit.quantity++;
}
updatedCartFruits = cartFruits.map((fruit) => fruit);
setCartFruits(updatedCartFruits);
};

const handleQuantityIncrement = (id) => {
const updatedCartFruits = cartFruits.map((fruit) => {
if (fruit.id === id) {
fruit.quantity++;
}
return fruit;
});
setCartFruits(updatedCartFruits);
};

const handleQuantityDecrement = (id) => {
const updatedFruit = cartFruits.find((fruit) => fruit.id === id);
updatedFruit.quantity--;
const updatedCartFruits = cartFruits.filter((fruit) => fruit.quantity > 0);
setCartFruits(updatedCartFruits);
};

const calculateTotal = () => {
let total = 0;
for (let i = 0; i < cartFruits.length; i++) {
total += cartFruits[i].quantity * cartFruits[i].price;
}
return total;
};

const handleFilter = (event) => {
let filter = event.target.value;
if (filter === "all") {
setStoreFruits(initialStoreItems);
return;
}
let filteredStoreFruits = initialStoreItems.filter(
(fruit) => fruit.type === filter
);
setStoreFruits(filteredStoreFruits);
};

const handleSorter = (event) => {
let sortby = event.target.value;
console.log(sortby);
switch (sortby) {
case "price-asc":
storeFruits.sort((a, b) => a.price - b.price);
break;
case "price-desc":
storeFruits.sort((a, b) => b.price - a.price);
break;
case "alpha":
storeFruits.sort((a, b) => a.name.localeCompare(b.name));
break;
}
let sortedStoreFruits = storeFruits.map((fruit) => fruit);
setStoreFruits(sortedStoreFruits);
};

const handleShowDetails = (fruit) => {
setDetailFruit(fruit);
};

const handleDismiss = () => {
setDetailFruit(null);
};

return (
<>
<header id="store">
<h1>Greengrocers</h1>

<Filter onChangeFilter={handleFilter} />

<Sorter onChangeSort={handleSorter} />

<ul className="item-list store--item-list">
<Store
fruits={storeFruits}
addToCart={handleAddToCart}
showDetails={handleShowDetails}
/>
</ul>
</header>
<main id="cart">
<h2>Your Cart</h2>
<div className="cart--item-list-container">
<ul className="item-list cart--item-list">
<Cart
fruits={cartFruits}
incrementQuantity={handleQuantityIncrement}
decrementQuantity={handleQuantityDecrement}
/>
</ul>
</div>
<div className="total-section">
<div>
<h3>Total</h3>
</div>
<div>
<span className="total-number">£0.00</span>
<span className="total-number">£ {calculateTotal()}</span>
</div>
</div>
</main>
<Detail fruit={detailFruit} dismiss={handleDismiss} />
<div>
Icons made by
<a
Expand All @@ -40,5 +148,5 @@ export default function App() {
</a>
</div>
</>
)
);
}
22 changes: 22 additions & 0 deletions src/components/Cart.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/* eslint-disable react/prop-types */
function Cart({fruits, incrementQuantity, decrementQuantity}) {

return (
<>
{fruits.map((fruit, index) => (
<li key={index}>
<img src={`./assets/icons/${fruit.id}.svg`}></img>
<p>{fruit.name}</p>
<button onClick={() => decrementQuantity(fruit.id)}>
-
</button>
<p>{fruit.quantity}</p>
<button onClick={() => incrementQuantity(fruit.id)}>
+
</button>
</li>
))}
</>
)
}
export default Cart
32 changes: 32 additions & 0 deletions src/components/Detail.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* eslint-disable react/prop-types */
import '../styles/modal.css'

function Detail({ fruit, dismiss }) {


if (fruit === null) return <></>

return <>
<div className="modal">
<div className='modal-content'>
<span className="close" onClick={dismiss}>&times;</span>

<img
className="store--item-icon "
src={`./assets/icons/${fruit.id}.svg`}
></img>

<div>
<p>ID: {fruit.id}</p>
<p>Name: {fruit.name}</p>
<p>Price: ${fruit.price}</p>
<p>Description: {fruit.description}</p>
<p>Type: {fruit.type}</p>
</div>

</div>
</div>
</>
}

export default Detail
17 changes: 17 additions & 0 deletions src/components/Filter.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/* eslint-disable react/prop-types */

function Filter({onChangeFilter}) {
return <>
<div className="item-filter-container">
<p>Filter by:</p>
<select className="item-filter" onChange={onChangeFilter}>
<option value="all">All</option>
<option value="vegetable">Vegetables</option>
<option value="fruit">Fruit</option>
<option value="berry">Berries</option>
</select>
</div>
</>
}

export default Filter
15 changes: 15 additions & 0 deletions src/components/Sorter.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* eslint-disable react/prop-types */

function Sorter({onChangeSort}) {
return <>
<div className="item-sort-container">
<p>Sort by:</p>
<select className="item-sort" onChange={onChangeSort}>
<option value="alpha">Alphabetical</option>
<option value="price-asc">Price low to high</option>
<option value="price-desc">Price high to low</option>
</select>
</div>
</>
}
export default Sorter
21 changes: 21 additions & 0 deletions src/components/Store.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* eslint-disable react/prop-types */

function Store({ fruits, addToCart, showDetails }) {

return (
<>
{fruits.map((fruit, index) => (
<li key={index}>
<img
className="store--item-icon "
src={`./assets/icons/${fruit.id}.svg`}
onClick={() => { showDetails(fruit) }}
></img>
<button onClick={() => addToCart(fruit.id)}>Add To Cart</button>
</li>
))}
</>
)
}

export default Store
38 changes: 38 additions & 0 deletions src/styles/modal.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
.modal {
display: block;
position: fixed;
/* Stay in place */
z-index: 1;
/* Sit on top */
left: 25%;
top: 50%;
width: 50%;
height: fit-content;
overflow: auto;
}

/* Modal Content/Box */
.modal-content {
background-color: #fefefe;
margin: 1% auto;
/* 1% from the top and centered */
padding: 20px;
border: 1px solid #888;
width: 100%;
/* Could be more or less, depending on screen size */
}

/* The Close Button */
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
}

.close:hover,
.close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}