basic functionality complete

This commit is contained in:
Mike 2024-10-14 07:23:02 -04:00
parent 81d70ec032
commit f34aa95bfe
9 changed files with 98 additions and 37 deletions

View file

@ -1,16 +1,14 @@
import { useState } from "react"; import { useState } from "react";
import { Outlet, useParams } from "react-router-dom"; import { Outlet } from "react-router-dom";
import Main from "./components/main";
import "./App.css"; import "./App.css";
import Navbar from "./components/navbar"; import Navbar from "./components/navbar";
function App() { function App() {
const { path } = useParams(); const [cart, setCart] = useState({});
const [cartItems, setCartItems] = useState(0);
return ( return (
<> <>
<Navbar cartItems={cartItems} /> <Navbar cartItems={cart} />
{path === "cart" ? <Outlet /> : path === "store" ? <Outlet /> : <Main />} <Outlet context={[cart, setCart]} />
</> </>
); );
} }

View file

@ -1,14 +1,20 @@
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import styles from "./css/cart.module.css";
import { useOutletContext } from "react-router-dom";
const Cart = () => {
const [cart, setCart] = useOutletContext();
const cartItems = Object.keys(cart);
const Cart = (props) => {
return ( return (
<> <>
<div> <div>
{props.cart ? ( {cart ? (
<div> <div>
<h2>Cart</h2> <h2>Cart</h2>
{props.cart.map((item) => ( {cartItems.map((item, index) => (
<CartItem item={item} key={item.id} /> <CartItem item={cart[item]} key={index} />
))} ))}
</div> </div>
) : ( ) : (
@ -20,15 +26,16 @@ const Cart = (props) => {
}; };
function CartItem({ item }) { function CartItem({ item }) {
const { name, price, img, qty } = item; const { title, price, image, qty } = item;
return ( return (
<div> <div className={styles.container}>
<img src={img} alt={name} /> <img src={image} alt={title} />
<h3>{name}</h3> <h3>{title}</h3>
<p>Qty: {qty}</p> <p>Qty: {qty}</p>
<p>{price}</p> <p>Price: {price}</p>
<p>{price * qty}</p> <p>Total: {price * qty}</p>
<p>{item.id}</p>
</div> </div>
); );
} }

View file

@ -1,12 +1,20 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import ProductCollection from "./components/productCollection"; import ProductCollection from "./components/productCollection";
import { useOutletContext } from "react-router-dom";
export default function Store(props) { export default function Store() {
const [cart, setCart] = useOutletContext();
const { items, loading } = useFakeStoreAPI(); const { items, loading } = useFakeStoreAPI();
return ( return (
<div> <div>
<h1>Smig.Tech Coaching Store</h1> <h1>Smig.Tech Coaching Store</h1>
<ProductCollection loading={loading} items={items} /> <ProductCollection
loading={loading}
items={items}
cart={cart}
setCart={setCart}
/>
</div> </div>
); );
} }
@ -19,14 +27,19 @@ function useFakeStoreAPI() {
fetch("https://fakestoreapi.com/products?limit=5", { mode: "cors" }) fetch("https://fakestoreapi.com/products?limit=5", { mode: "cors" })
.then((response) => { .then((response) => {
if (response.status >= 400) { if (response.status >= 400) {
return { error: "unable to fetch items" }; throw new Error("unable to fetch items");
} }
return response.json(); return response.json();
}) })
.then((response) => { .then((response) => {
const arr = []; const arr = [];
response.forEach((item) => { response.forEach((item) => {
arr.push({ title: item.title, price: item.price, image: item.image }); arr.push({
title: item.title,
price: item.price,
image: item.image,
id: crypto.randomUUID(),
});
}); });
setItems(arr); setItems(arr);
}) })

View file

@ -3,11 +3,20 @@ import { Link } from "react-router-dom";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
export default function Navbar({ cartItems }) { export default function Navbar({ cartItems }) {
const sumCartItems = Object.keys(cartItems).length;
return ( return (
<nav className={styles.nav}> <nav className={styles.nav}>
<h1>Smig.Tech</h1> <h1>Smig.Tech</h1>
<Nav /> <Nav />
{cartItems ? <h1>{cartItems}</h1> : <button>I&apos;m Ready</button>} {sumCartItems > 0 ? (
<Link to="bag">
{" "}
<h1>{sumCartItems}</h1>
</Link>
) : (
<button>I&apos;m Ready</button>
)}
</nav> </nav>
); );
} }
@ -26,5 +35,5 @@ function Nav() {
} }
Navbar.propTypes = { Navbar.propTypes = {
cartItems: PropTypes.number, cartItems: PropTypes.object,
}; };

View file

@ -1,12 +1,16 @@
import Product from "./products"; import Product from "./products";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
export default function ProductCollection({ loading, items }) { import styles from "./productCollection.module.css";
export default function ProductCollection({ loading, items, cart, setCart }) {
return ( return (
<div> <div className={styles.container}>
{!loading {!loading
? items.map((item, index) => { ? items.map((item, index) => {
return <Product item={item} key={index} />; return (
<Product item={item} key={index} cart={cart} setCart={setCart} />
);
}) })
: null} : null}
</div> </div>
@ -16,4 +20,6 @@ export default function ProductCollection({ loading, items }) {
ProductCollection.propTypes = { ProductCollection.propTypes = {
loading: PropTypes.bool, loading: PropTypes.bool,
items: PropTypes.array, items: PropTypes.array,
cart: PropTypes.object,
setCart: PropTypes.func,
}; };

View file

@ -2,16 +2,33 @@ import PropTypes from "prop-types";
import styles from "./products.module.css"; import styles from "./products.module.css";
export default function Product({ item }) { export default function Product({ item, cart, setCart }) {
return ( return (
<div className={styles.card}> <div className={styles.card}>
<img src={item.image} alt={item.title} className={styles.img} /> <img src={item.image} alt={item.title} className={styles.img} />
<p>{item.title}</p> <p>{item.title}</p>
<p>${item.price}</p> <p>${item.price}</p>
<button
onClick={() => {
let obj = { ...cart };
if (obj[item.id]) {
obj[item.id].qty += 1;
} else {
obj[item.id] = item;
obj[item.id].qty = 1;
}
setCart(obj);
}}
>
Add to Cart
</button>
</div> </div>
); );
} }
Product.propTypes = { Product.propTypes = {
item: PropTypes.object, item: PropTypes.object,
cart: PropTypes.object,
setCart: PropTypes.func,
}; };

View file

@ -1,11 +1,15 @@
.card { .card {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
max-width: 350px; max-width: calc(100% / 5);
justify-content: center; justify-content: end;
align-items: center; /*flex: 1;*/
padding: 1.5rem;
margin: 1.5rem;
} }
.img { .img {
max-width: 250px; width: 100%;
height: auto;
vertical-align: middle;
} }

View file

@ -3,10 +3,12 @@ import { Link } from "react-router-dom";
function ErrorPage() { function ErrorPage() {
return ( return (
<div> <div>
<h1>Oh no, this route doesn't exist!</h1> <h1>Oh no, this route doesn&apos;t exist!</h1>
<Link to="/"> <p>
You can go back to the home page by clicking here, though! You can go back to the home page by clicking&nbsp;
</Link> <Link to="/">here</Link>
&nbsp;though!
</p>
</div> </div>
); );
} }

View file

@ -1,5 +1,6 @@
import App from "./App"; import App from "./App";
import Cart from "./Cart"; import Cart from "./Cart";
import Main from "./components/main";
import Store from "./Store"; import Store from "./Store";
import ErrorPage from "./errorPage"; import ErrorPage from "./errorPage";
@ -10,12 +11,16 @@ const routes = [
errorElement: <ErrorPage />, errorElement: <ErrorPage />,
children: [ children: [
{ {
path: ":path", path: "/",
element: <Store />, element: <Main />,
index: true, index: true,
}, },
{ {
path: "store/:path", path: "store",
element: <Store />,
},
{
path: "bag",
element: <Cart />, element: <Cart />,
}, },
], ],