diff --git a/package-lock.json b/package-lock.json index 3c65e57..695ea7a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,9 @@ "@testing-library/user-event": "^13.5.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-router-dom": "^6.22.1", "react-scripts": "5.0.1", + "switch": "^0.0.0", "web-vitals": "^2.1.4" } }, @@ -3085,6 +3087,14 @@ } } }, + "node_modules/@remix-run/router": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.1.tgz", + "integrity": "sha512-zcU0gM3z+3iqj8UX45AmWY810l3oUmXM7uH4dt5xtzvMhRtYVhKGOmgOd1877dOPPepfCjUv57w+syamWIYe7w==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -13971,6 +13981,36 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "6.22.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.1.tgz", + "integrity": "sha512-0pdoRGwLtemnJqn1K0XHUbnKiX0S4X8CgvVVmHGOWmofESj31msHo/1YiqcJWK7Wxfq2a4uvvtS01KAQyWK/CQ==", + "dependencies": { + "@remix-run/router": "1.15.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.22.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.1.tgz", + "integrity": "sha512-iwMyyyrbL7zkKY7MRjOVRy+TMnS/OPusaFVxM2P11x9dzSzGmLsebkCvYirGq0DWB9K9hOspHYYtDz33gE5Duw==", + "dependencies": { + "@remix-run/router": "1.15.1", + "react-router": "6.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", @@ -15286,6 +15326,11 @@ "boolbase": "~1.0.0" } }, + "node_modules/switch": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/switch/-/switch-0.0.0.tgz", + "integrity": "sha512-Pvi4hlAXWHEIT+4XlQEPPIQ02hRzvn38K/cnZ5sZeM11FsDPoXvBD6i/zyVxFK6cgqSlS8sA5/sIwUGp9+ZMhw==" + }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -18835,6 +18880,11 @@ "source-map": "^0.7.3" } }, + "@remix-run/router": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.1.tgz", + "integrity": "sha512-zcU0gM3z+3iqj8UX45AmWY810l3oUmXM7uH4dt5xtzvMhRtYVhKGOmgOd1877dOPPepfCjUv57w+syamWIYe7w==" + }, "@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -26585,6 +26635,23 @@ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==" }, + "react-router": { + "version": "6.22.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.1.tgz", + "integrity": "sha512-0pdoRGwLtemnJqn1K0XHUbnKiX0S4X8CgvVVmHGOWmofESj31msHo/1YiqcJWK7Wxfq2a4uvvtS01KAQyWK/CQ==", + "requires": { + "@remix-run/router": "1.15.1" + } + }, + "react-router-dom": { + "version": "6.22.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.1.tgz", + "integrity": "sha512-iwMyyyrbL7zkKY7MRjOVRy+TMnS/OPusaFVxM2P11x9dzSzGmLsebkCvYirGq0DWB9K9hOspHYYtDz33gE5Duw==", + "requires": { + "@remix-run/router": "1.15.1", + "react-router": "6.22.1" + } + }, "react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", @@ -27562,6 +27629,11 @@ } } }, + "switch": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/switch/-/switch-0.0.0.tgz", + "integrity": "sha512-Pvi4hlAXWHEIT+4XlQEPPIQ02hRzvn38K/cnZ5sZeM11FsDPoXvBD6i/zyVxFK6cgqSlS8sA5/sIwUGp9+ZMhw==" + }, "symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", diff --git a/package.json b/package.json index 022d9bf..11a0ea8 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,9 @@ "@testing-library/user-event": "^13.5.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-router-dom": "^6.22.1", "react-scripts": "5.0.1", + "switch": "^0.0.0", "web-vitals": "^2.1.4" }, "scripts": { diff --git a/src/App.js b/src/App.js index 3784575..34e6202 100644 --- a/src/App.js +++ b/src/App.js @@ -1,24 +1,29 @@ -import logo from './logo.svg'; + + +import React from 'react'; +import { BrowserRouter as Router, Route, Routes } from 'react-router-dom'; import './App.css'; +import Home from './components/Home'; +import Beers from './components/Beers'; +import RandomBeer from './components/random-beer'; +import NewBeer from './components/NewBeer'; +import Header from './components/Header'; function App() { return ( -
-
- logo -

- Edit src/App.js and save to reload. -

- - Learn React - -
-
+ +
+
+ + + + + + + + +
+
); } diff --git a/src/Header.css b/src/Header.css new file mode 100644 index 0000000..1281767 --- /dev/null +++ b/src/Header.css @@ -0,0 +1,21 @@ +nav{ + padding:50px; + background-color: aqua; + border: 2px solid rgb(40, 45, 47); + +} + +link{ + text-decoration: none; + +} + +.Home{ + text-decoration:none; + display: flex; + justify-content: center; +} +.Home img{ + width:50px; + +} \ No newline at end of file diff --git a/src/Home.css b/src/Home.css new file mode 100644 index 0000000..973668c --- /dev/null +++ b/src/Home.css @@ -0,0 +1,4 @@ +.Home-contents{ + justify-content: center; + display:inline; +} \ No newline at end of file diff --git a/src/assets/home.png b/src/assets/home.png new file mode 100644 index 0000000..95eae8b Binary files /dev/null and b/src/assets/home.png differ diff --git a/src/components/Beers.js b/src/components/Beers.js new file mode 100644 index 0000000..826e222 --- /dev/null +++ b/src/components/Beers.js @@ -0,0 +1,69 @@ +// src/components/Beers.js + +import React, { useState, useEffect } from 'react'; + +function Beers() { + const [beers, setBeers] = useState([]); + const [searchQuery, setSearchQuery] = useState(''); + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + const fetchBeers = async () => { + try { + const response = await fetch(`https://ih-beers-api2.herokuapp.com/beers/search?q=${searchQuery}`); + if (response.ok) { + const data = await response.json(); + setBeers(data); + setIsLoading(false); + } else { + console.error('Failed to fetch filtered beers'); + } + } catch (error) { + console.error('Error fetching filtered beers:', error); + } + }; + + if (searchQuery) { + fetchBeers(); + } + + return () => { + + setIsLoading(true); + }; + }, [searchQuery]); + + const handleChange = (e) => { + setSearchQuery(e.target.value); + }; + + return ( +
+

All Beers

+ + {isLoading ? ( +
Loading...
+ ) : ( +
+ {beers.length === 0 ? ( +
No beers found
+ ) : ( +
+ {beers.map((beer) => ( +
+ {beer.name} +

Name: {beer.name}

+

Tagline: {beer.tagline}

+

Contributed by: {beer.contributed_by}

+
+
+ ))} +
+ )} +
+ )} +
+ ); +} + +export default Beers; diff --git a/src/components/Header.js b/src/components/Header.js new file mode 100644 index 0000000..955c677 --- /dev/null +++ b/src/components/Header.js @@ -0,0 +1,24 @@ +// src/components/Header.js + +import React from 'react'; +import { Link } from 'react-router-dom'; +import "../Header.css" + +function Header() { + return ( +
+ +
+ ); +} + +export default Header; diff --git a/src/components/Home.js b/src/components/Home.js new file mode 100644 index 0000000..00d6e6a --- /dev/null +++ b/src/components/Home.js @@ -0,0 +1,28 @@ +// src/components/Home.js + +import React from 'react'; +import { Link } from 'react-router-dom'; + +function Home() { + return ( +
+

Welcome to RootBeers!

+
+ + beer.png + + + + random + + + + new + + +
+
+ ); +} + +export default Home; diff --git a/src/components/NewBeer.js b/src/components/NewBeer.js new file mode 100644 index 0000000..477f943 --- /dev/null +++ b/src/components/NewBeer.js @@ -0,0 +1,79 @@ +// src/components/NewBeer.js + +import React, { useState } from 'react'; + +function NewBeer() { + const [formData, setFormData] = useState({ + name: '', + tagline: '', + description: '', + first_brewed: '', + brewers_tips: '', + attenuation_level: '', + contributed_by: '' + }); + + const handleChange = (e) => { + const { name, value } = e.target; + setFormData({ ...formData, [name]: value }); + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + try { + const response = await fetch('https://ih-beers-api2.herokuapp.com/beers/new', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(formData) + }); + if (response.ok) { + console.log('New beer successfully created!'); + } else { + console.error('Failed to create new beer'); + } + } catch (error) { + console.error('Error creating new beer:', error); + } + }; + + return ( +
+

Create a New Beer

+
+ + + + + + + + +
+
+ ); +} + +export default NewBeer; diff --git a/src/components/SingleBeer.js b/src/components/SingleBeer.js new file mode 100644 index 0000000..c6cc283 --- /dev/null +++ b/src/components/SingleBeer.js @@ -0,0 +1,46 @@ +// src/components/SingleBeer.js + +import React, { useState, useEffect } from 'react'; +import { useParams } from 'react-router-dom'; + +function SingleBeer() { + const { beerId } = useParams(); + const [beer, setBeer] = useState(null); + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + fetch(`https://ih-beers-api2.herokuapp.com/beers/${beerId}`) + .then(response => response.json()) + .then(data => { + setBeer(data); + setIsLoading(false); + }) + .catch(error => { + console.error('Error fetching beer details:', error); + setIsLoading(false); + }); + }, [beerId]); + + if (isLoading) { + return
Loading...
; + } + + if (!beer) { + return
Beer not found
; + } + + return ( +
+

Beer Details

+ {beer.name} +

Name: {beer.name}

+

Tagline: {beer.tagline}

+

First Brewed: {beer.first_brewed}

+

Attenuation Level: {beer.attenuation_level}

+

Description: {beer.description}

+

Contributed by: {beer.contributed_by}

+
+ ); +} + +export default SingleBeer; diff --git a/src/components/random-beer.js b/src/components/random-beer.js new file mode 100644 index 0000000..7b02b7e --- /dev/null +++ b/src/components/random-beer.js @@ -0,0 +1,44 @@ +// src/components/RandomBeer.js + +import React, { useState, useEffect } from 'react'; + +function RandomBeer() { + const [randomBeer, setRandomBeer] = useState(null); + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + fetch('https://ih-beers-api2.herokuapp.com/beers/random') + .then(response => response.json()) + .then(data => { + setRandomBeer(data); + setIsLoading(false); + }) + .catch(error => { + console.error('Error fetching random beer:', error); + setIsLoading(false); + }); + }, []); + + if (isLoading) { + return
Loading...
; + } + + if (!randomBeer) { + return
Random beer not found
; + } + + return ( +
+

Random Beer

+ {randomBeer.name} +

Name: {randomBeer.name}

+

Tagline: {randomBeer.tagline}

+

First Brewed: {randomBeer.first_brewed}

+

Attenuation Level: {randomBeer.attenuation_level}

+

Description: {randomBeer.description}

+

Contributed by: {randomBeer.contributed_by}

+
+ ); +} + +export default RandomBeer; diff --git a/src/index.css b/src/index.css index ec2585e..18f0e46 100644 --- a/src/index.css +++ b/src/index.css @@ -5,6 +5,7 @@ body { sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + } code { diff --git a/src/index.js b/src/index.js index d563c0f..5a3d73d 100644 --- a/src/index.js +++ b/src/index.js @@ -8,6 +8,7 @@ const root = ReactDOM.createRoot(document.getElementById('root')); root.render( + );