diff --git a/shopping-cart/package-lock.json b/shopping-cart/package-lock.json
index 2431d5d..9f0e5e4 100644
--- a/shopping-cart/package-lock.json
+++ b/shopping-cart/package-lock.json
@@ -8,8 +8,10 @@
"name": "shopping-cart",
"version": "0.0.0",
"dependencies": {
+ "prop-types": "^15.8.1",
"react": "^18.3.1",
- "react-dom": "^18.3.1"
+ "react-dom": "^18.3.1",
+ "react-router-dom": "^6.27.0"
},
"devDependencies": {
"@eslint/js": "^9.11.1",
@@ -980,6 +982,15 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
+ "node_modules/@remix-run/router": {
+ "version": "1.20.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.20.0.tgz",
+ "integrity": "sha512-mUnk8rPJBI9loFDZ+YzPGdeniYK+FTmRD1TMCz7ev2SNIozyKKpnGgsxO34u6Z4z/t0ITuu7voi/AshfsGsgFg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.24.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz",
@@ -3328,7 +3339,6 @@
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -3578,7 +3588,6 @@
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"loose-envify": "^1.4.0",
@@ -3625,7 +3634,6 @@
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
- "dev": true,
"license": "MIT"
},
"node_modules/react-refresh": {
@@ -3638,6 +3646,38 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-router": {
+ "version": "6.27.0",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.27.0.tgz",
+ "integrity": "sha512-YA+HGZXz4jaAkVoYBE98VQl+nVzI+cVI2Oj/06F5ZM+0u3TgedN9Y9kmMRo2mnkSK2nCpNQn0DVob4HCsY/WLw==",
+ "license": "MIT",
+ "dependencies": {
+ "@remix-run/router": "1.20.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "6.27.0",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.27.0.tgz",
+ "integrity": "sha512-+bvtFWMC0DgAFrfKXKG9Fc+BcXWRUO1aJIihbB79xaeq0v5UzfvnM5houGUm1Y461WVRcgAQ+Clh5rdb1eCx4g==",
+ "license": "MIT",
+ "dependencies": {
+ "@remix-run/router": "1.20.0",
+ "react-router": "6.27.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
"node_modules/reflect.getprototypeof": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz",
diff --git a/shopping-cart/package.json b/shopping-cart/package.json
index 7fc1012..ca81149 100644
--- a/shopping-cart/package.json
+++ b/shopping-cart/package.json
@@ -10,8 +10,10 @@
"preview": "vite preview"
},
"dependencies": {
+ "prop-types": "^15.8.1",
"react": "^18.3.1",
- "react-dom": "^18.3.1"
+ "react-dom": "^18.3.1",
+ "react-router-dom": "^6.27.0"
},
"devDependencies": {
"@eslint/js": "^9.11.1",
diff --git a/shopping-cart/src/App.jsx b/shopping-cart/src/App.jsx
index 872882b..58625d5 100644
--- a/shopping-cart/src/App.jsx
+++ b/shopping-cart/src/App.jsx
@@ -1,15 +1,16 @@
import { useState } from "react";
-import "./App.css";
+import { Outlet, useParams } from "react-router-dom";
import Main from "./components/main";
+import "./App.css";
import Navbar from "./components/navbar";
function App() {
- const [count, setCount] = useState(0);
-
+ const { path } = useParams();
+ const [cartItems, setCartItems] = useState(0);
return (
<>
-
-
+
+ {path === "cart" ? : path === "store" ? : }
>
);
}
diff --git a/shopping-cart/src/Cart.jsx b/shopping-cart/src/Cart.jsx
index 44b5c76..d42956f 100644
--- a/shopping-cart/src/Cart.jsx
+++ b/shopping-cart/src/Cart.jsx
@@ -1,30 +1,44 @@
+import PropTypes from "prop-types";
+
const Cart = (props) => {
- return (
-
- {props.cart ? (
-
-
Cart
- {props.cart.map((item) =>
-
- )}
-
- ) : (Your cart is empty
)}
-
-
- )
+ return (
+ <>
+
+ {props.cart ? (
+
+
Cart
+ {props.cart.map((item) => (
+
+ ))}
+
+ ) : (
+
Your cart is empty
+ )}
+
+ >
+ );
+};
+
+function CartItem({ item }) {
+ const { name, price, img, qty } = item;
+
+ return (
+
+
+
{name}
+
Qty: {qty}
+
{price}
+
{price * qty}
+
+ );
}
+CartItem.propTypes = {
+ item: PropTypes.object,
+};
-function CartItem({item, qty}) {
- const {name, price, img} = item;
+Cart.propTypes = {
+ cart: PropTypes.array,
+};
- return (
-
-
-
{name}
-
Qty: {qty}
-
{price}
-
{price * qty}
-
- )
-}
\ No newline at end of file
+export default Cart;
diff --git a/shopping-cart/src/Store.jsx b/shopping-cart/src/Store.jsx
new file mode 100644
index 0000000..cb6c631
--- /dev/null
+++ b/shopping-cart/src/Store.jsx
@@ -0,0 +1,38 @@
+import { useEffect, useState } from "react";
+import ProductCollection from "./components/productCollection";
+
+export default function Store(props) {
+ const { items, loading } = useFakeStoreAPI();
+ return (
+
+
Smig.Tech Coaching Store
+
+
+ );
+}
+
+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) {
+ return { 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 });
+ });
+ setItems(arr);
+ })
+ .catch((error) => console.log(error))
+ .finally(() => setLoading(false));
+ }, []);
+
+ return { items, loading };
+}
diff --git a/shopping-cart/src/components/main.jsx b/shopping-cart/src/components/main.jsx
index 79ad0c8..671b404 100644
--- a/shopping-cart/src/components/main.jsx
+++ b/shopping-cart/src/components/main.jsx
@@ -3,14 +3,20 @@ import styles from "./main.module.css";
export default function Main(props) {
return (
-
-
We help you skill up faster
-
- Trying to pivot into tech? There's a lot to figure out. We can
- help you navigate the path. Fast results and guaranteed growth.
-
-
-
+
);
}
+
+function Default() {
+ return (
+
+
We help you skill up faster
+
+ Trying to pivot into tech? There's a lot to figure out. We can help
+ you navigate the path. Fast results and guaranteed growth.
+
+
+
+ );
+}
diff --git a/shopping-cart/src/components/navbar.jsx b/shopping-cart/src/components/navbar.jsx
index 57c249d..5be9659 100644
--- a/shopping-cart/src/components/navbar.jsx
+++ b/shopping-cart/src/components/navbar.jsx
@@ -1,11 +1,13 @@
import styles from "./navbar.module.css";
+import { Link } from "react-router-dom";
+import PropTypes from "prop-types";
-export default function Navbar(props) {
+export default function Navbar({ cartItems }) {
return (
);
}
@@ -13,8 +15,16 @@ export default function Navbar(props) {
function Nav() {
return (
- - home
- - shop
+ -
+ home
+
+ -
+ shop
+
);
}
+
+Navbar.propTypes = {
+ cartItems: PropTypes.number,
+};
diff --git a/shopping-cart/src/components/productCollection.jsx b/shopping-cart/src/components/productCollection.jsx
new file mode 100644
index 0000000..5fbe13f
--- /dev/null
+++ b/shopping-cart/src/components/productCollection.jsx
@@ -0,0 +1,19 @@
+import Product from "./products";
+import PropTypes from "prop-types";
+
+export default function ProductCollection({ loading, items }) {
+ return (
+
+ {!loading
+ ? items.map((item, index) => {
+ return
;
+ })
+ : null}
+
+ );
+}
+
+ProductCollection.propTypes = {
+ loading: PropTypes.bool,
+ items: PropTypes.array,
+};
diff --git a/shopping-cart/src/components/products.jsx b/shopping-cart/src/components/products.jsx
new file mode 100644
index 0000000..344d9f0
--- /dev/null
+++ b/shopping-cart/src/components/products.jsx
@@ -0,0 +1,17 @@
+import PropTypes from "prop-types";
+
+import styles from "./products.module.css";
+
+export default function Product({ item }) {
+ return (
+
+
+
{item.title}
+
${item.price}
+
+ );
+}
+
+Product.propTypes = {
+ item: PropTypes.object,
+};
diff --git a/shopping-cart/src/components/products.module.css b/shopping-cart/src/components/products.module.css
new file mode 100644
index 0000000..a8c0d8a
--- /dev/null
+++ b/shopping-cart/src/components/products.module.css
@@ -0,0 +1,11 @@
+.card {
+ display: flex;
+ flex-direction: column;
+ max-width: 350px;
+ justify-content: center;
+ align-items: center;
+}
+
+.img {
+ max-width: 250px;
+}
diff --git a/shopping-cart/src/errorPage.jsx b/shopping-cart/src/errorPage.jsx
new file mode 100644
index 0000000..129d8a2
--- /dev/null
+++ b/shopping-cart/src/errorPage.jsx
@@ -0,0 +1,14 @@
+import { Link } from "react-router-dom";
+
+function ErrorPage() {
+ return (
+
+
Oh no, this route doesn't exist!
+
+ You can go back to the home page by clicking here, though!
+
+
+ );
+}
+
+export default ErrorPage;
diff --git a/shopping-cart/src/main.jsx b/shopping-cart/src/main.jsx
index 89f91e5..6e8aaf2 100644
--- a/shopping-cart/src/main.jsx
+++ b/shopping-cart/src/main.jsx
@@ -1,10 +1,13 @@
-import { StrictMode } from 'react'
-import { createRoot } from 'react-dom/client'
-import App from './App.jsx'
-import './index.css'
+import { StrictMode } from "react";
+import { createRoot } from "react-dom/client";
+import "./index.css";
+import { createBrowserRouter, RouterProvider } from "react-router-dom";
+import routes from "./routes";
-createRoot(document.getElementById('root')).render(
+const router = createBrowserRouter(routes);
+
+createRoot(document.getElementById("root")).render(
-
+
,
-)
+);
diff --git a/shopping-cart/src/routes.jsx b/shopping-cart/src/routes.jsx
new file mode 100644
index 0000000..57905bd
--- /dev/null
+++ b/shopping-cart/src/routes.jsx
@@ -0,0 +1,25 @@
+import App from "./App";
+import Cart from "./Cart";
+import Store from "./Store";
+import ErrorPage from "./errorPage";
+
+const routes = [
+ {
+ path: "/",
+ element: ,
+ errorElement: ,
+ children: [
+ {
+ path: ":path",
+ element: ,
+ index: true,
+ },
+ {
+ path: "store/:path",
+ element: ,
+ },
+ ],
+ },
+];
+
+export default routes;