adding more logic and components

This commit is contained in:
Mike 2024-10-15 06:47:25 -04:00
parent 9a7596b2a8
commit da6d76e598
10 changed files with 109 additions and 83 deletions

View file

@ -5,13 +5,30 @@ import { useOutletContext } from "react-router-dom";
export default function Store() {
const [cart, setCart, items, setItems] = useOutletContext();
const [loading, setLoading] = useState(true);
const url = 'https://fakestoreapi.com/products?limit=5'
console.table(items)
useFakeStoreAPIData(items, setItems, loading, setLoading);
return (
<div>
<h1>Smig.Tech Coaching Store</h1>
<ProductCollection
loading={loading}
items={items}
cart={cart}
setCart={setCart}
/>
</div>
);
}
function useFakeStoreAPIData(items, setItems, loading, setLoading) {
useEffect(() => {
if (items === null) {
if (items !== null) {
setLoading(false);
return;
}
fetch(url, { mode: "cors" })
fetch("https://fakestoreapi.com/products?limit=5", { mode: "cors" })
.then((response) => {
if (response.status >= 400) {
throw new Error("unable to fetch items");
@ -32,51 +49,5 @@ export default function Store() {
})
.catch((error) => console.log(error))
.finally(() => setLoading(false));
} else {
setLoading(false);
}
}, []);
return (
<div>
<h1>Smig.Tech Coaching Store</h1>
<ProductCollection
loading={loading}
items={items}
cart={cart}
setCart={setCart}
/>
</div>
);
}, [items, setItems, loading, setLoading]);
}
// function useFakeStoreAPI() {
// const [items, setItems] = useState(null);
// const [loading, setLoading] = useState(true);
// useEffect(() => {
// fetch("https://fakestoreapi.com/products?limit=5", { mode: "cors" })
// .then((response) => {
// if (response.status >= 400) {
// throw new Error("unable to fetch items");
// }
// return response.json();
// })
// .then((response) => {
// const arr = [];
// response.forEach((item) => {
// arr.push({
// title: item.title,
// price: item.price,
// image: item.image,
// id: crypto.randomUUID(),
// });
// });
// setItems(arr);
// })
// .catch((error) => console.log(error))
// .finally(() => setLoading(false));
// }, []);
// return { items, loading };
// }

View file

@ -6,7 +6,7 @@ export default function Navbar({ cartItems }) {
const sumCartItems = Object.keys(cartItems).length;
return (
<nav className={styles.nav}>
<nav className={styles.container}>
<h1>Smig.Tech</h1>
<Nav />
{sumCartItems > 0 ? (

View file

@ -1,11 +1,17 @@
nav {
.container {
display: flex;
justify-content: space-between;
padding: 0 1rem;
/*position: relative;*/
}
.nav {
display: flex;
list-style-type: none;
gap: 20px;
/*position: absolute;*/
/*right: 4vw;*/
padding-right: 1rem;
margin-left: auto;
align-self: center;
}

View file

@ -1,6 +1,6 @@
import Product from "./products";
import { Link } from "react-router-dom";
import Products from "./products";
import PropTypes from "prop-types";
import styles from "./productCollection.module.css";
export default function ProductCollection({ loading, items, cart, setCart }) {
@ -9,7 +9,10 @@ export default function ProductCollection({ loading, items, cart, setCart }) {
{!loading
? items.map((item, index) => {
return (
<Product item={item} key={index} cart={cart} setCart={setCart} />
<div key={index} className={styles.card}>
<Products item={item} cart={cart} setCart={setCart} />
<Link to={item.id}> More Info</Link>
</div>
);
})
: null}

View file

@ -0,0 +1,16 @@
.container {
display: flex;
gap: 2rem;
justify-content: center;
flex-wrap: wrap;
align-items: stretch;
}
.card {
display: flex;
flex-direction: column;
max-width: calc(100% / 4);
justify-content: end;
/*flex: 1;*/
padding: 1.5rem;
margin: 1.5rem;
}

View file

@ -0,0 +1,47 @@
import { useParams, useOutletContext } from "react-router-dom";
import Products from "./products";
import PropTypes from "prop-types";
import styles from "./productCollection.module.css";
export default function ProductDetails() {
const [cart, setCart, items, setItems] = useOutletContext();
const { id } = useParams();
const item = items.filter((item) => item.id === id)[0];
return (
<div className={styles.container}>
{item ? (
<div className={styles.card}>
<Products item={item} cart={cart} setCart={setCart} />
<button
onClick={() => {
addToCart(item, cart, setCart);
}}
>
Add to Cart
</button>
</div>
) : null}
</div>
);
}
function addToCart(item, cart, setCart) {
let obj = { ...cart };
if (obj[item.id]) {
obj[item.id].qty += 1;
} else {
obj[item.id] = item;
obj[item.id].qty = 1;
}
setCart(obj);
}
ProductDetails.propTypes = {
item: PropTypes.object,
cart: PropTypes.object,
setCart: PropTypes.func,
};

View file

@ -2,32 +2,17 @@ import PropTypes from "prop-types";
import styles from "./products.module.css";
export default function Product({ item, cart, setCart }) {
export default function Products({ item, cart, setCart }) {
return (
<div className={styles.card}>
<img src={item.image} alt={item.title} className={styles.img} />
<p>{item.title}</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>
);
}
Product.propTypes = {
Products.propTypes = {
item: PropTypes.object,
cart: PropTypes.object,
setCart: PropTypes.func,

View file

@ -1,13 +1,3 @@
.card {
display: flex;
flex-direction: column;
max-width: calc(100% / 5);
justify-content: end;
/*flex: 1;*/
padding: 1.5rem;
margin: 1.5rem;
}
.img {
width: 100%;
height: auto;

View file

@ -0,0 +1,3 @@
.container {
display: flex;
}

View file

@ -1,6 +1,7 @@
import App from "./App";
import Cart from "./Cart";
import Main from "./components/main";
import ProductDetails from "./components/productDetails";
import Store from "./Store";
import ErrorPage from "./errorPage";
@ -19,6 +20,10 @@ const routes = [
path: "store",
element: <Store />,
},
{
path: "store/:id",
element: <ProductDetails />,
},
{
path: "bag",
element: <Cart />,