Skip to content
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
469 changes: 350 additions & 119 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.8.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"react-scripts": "^5.0.1",
"web-vitals": "^2.1.4"
},
"scripts": {
Expand Down
150 changes: 126 additions & 24 deletions src/App.css
Original file line number Diff line number Diff line change
@@ -1,38 +1,140 @@
.App {

/* Global Reset */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Arial', sans-serif;
}

/* Centering the Home Icons */
.home-container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;

}

/* Styling Home Page Cards */
.home-card {
text-align: center;
background: white;
padding: 20px;
margin: 10px;
width: 250px;
transition: transform 0.2s;
}
.normal-text{
color: black;
text-decoration: none;
}
.normal-text:hover {
transform: scale(1.05);
}

.home-card img {
width: 100%;
border-radius: 8px;
}

.home-card h2 {
margin: 10px 0;
}

.App-logo {
height: 40vmin;
pointer-events: none;
.home-card p {
color: #666;
}

@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
/* Beer List Styling */
.beer-list-container {
padding: 20px;
}

.App-header {
background-color: #282c34;
min-height: 100vh;
.beer-card {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
gap: 15px;
background: white;
color: black;
text-decoration: none;
margin: 10px 0;
padding: 15px;
border-radius: 10px;
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.1);
cursor: pointer;
}

.beer-card img {
width: 80px;
height: auto;
margin-right: 15px;
border-radius: 8px;
}

.App-link {
color: #61dafb;
.beer-card h3 {
margin: 0;
}

@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
/* Beer Details Page */
.beer-details {
padding: 20px;
max-width: 600px;
margin: 0 auto;
}

.beer-details img {
width: 100%;
border-radius: 10px;
margin: 50px auto;
display: block;
}

.beer-details h1 {
margin: 10px 0;
}

/* Form Styling */
.form-container {
max-width: 500px;
margin: auto;
padding: 20px;
background: white;
border-radius: 10px;
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.2);
}

.form-container label {
font-weight: bold;
}

.form-container input,
.form-container textarea {
width: 100%;
padding: 10px;
margin-top: 5px;
margin-bottom: 15px;
border: 1px solid #ccc;
border-radius: 5px;
}

.form-container button {
width: 100%;
padding: 10px;
background: #007bff;
color: white;
border: none;
cursor: pointer;
}

.form-container button:hover {
background: #0056b3;
}


.search{
width: 70%;
margin: 20px auto;
padding: 10px;
display: block;
}
35 changes: 17 additions & 18 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
import logo from './logo.svg';
import './App.css';
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import Home from "./pages/Home";
import Beers from "./pages/Beers";
import BeerDetails from "./pages/BeerDetails";
import RandomBeer from "./pages/RandomBeer";
import NewBeer from "./pages/NewBeer";
import Header from "./components/Header";

function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
<Router>
<Header />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/beers" element={<Beers />} />
<Route path="/beers/:beerId" element={<BeerDetails />} />
<Route path="/random-beer" element={<RandomBeer />} />
<Route path="/new-beer" element={<NewBeer />} />
</Routes>
</Router>
);
}

Expand Down
9 changes: 9 additions & 0 deletions src/api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import axios from "axios";

const API_URL = "https://ih-beers-api2.herokuapp.com/beers";

export const fetchBeers = () => axios.get(API_URL);
export const fetchBeerById = (id) => axios.get(`${API_URL}/${id}`);
export const fetchRandomBeer = () => axios.get(`${API_URL}/random`);
export const searchBeers = (query) => axios.get(`${API_URL}/search?q=${query}`);
export const createBeer = (beerData) => axios.post(`${API_URL}/new`, beerData);
Empty file added src/components/BeerCard.js
Empty file.
12 changes: 12 additions & 0 deletions src/components/Header.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Link } from "react-router-dom";
import "../App.css"

function Header() {
return (
<header style={{ padding: "10px", textAlign: "center", background: "#007bff", color:"white" , textDecoration: "none" }}>
<Link style={{ color:"white" , textDecoration: "none" }} to="/">🏠 Home</Link>
</header>
);
}

export default Header;
8 changes: 8 additions & 0 deletions src/components/SearchBar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import "../App.css";

function SearchBar({ setSearch }) {
return <input className="search" type="text" placeholder="Search beers..." onChange={(e) => setSearch(e.target.value)} />;
}

export default SearchBar;

1 change: 1 addition & 0 deletions src/index.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
Expand Down
25 changes: 25 additions & 0 deletions src/pages/BeerDetails.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { fetchBeerById } from "../api";

function BeerDetails() {
const { beerId } = useParams();
const [beer, setBeer] = useState(null);

useEffect(() => {
fetchBeerById(beerId).then((res) => setBeer(res.data));
}, [beerId]);

return beer ? (
<div className="beer-details">
<img src={beer.image_url} alt={beer.name} style={{ width: "100px" }} />
<h2>{beer.name}</h2><br />
<p>{beer.tagline}</p>
<p>{beer.description}</p>
</div>
) : (
<p>Loading...</p>
);
}

export default BeerDetails;
36 changes: 36 additions & 0 deletions src/pages/Beers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { useEffect, useState } from "react";
import { fetchBeers } from "../api";
import { Link } from "react-router-dom";
import SearchBar from "../components/SearchBar";
import "../App.css";

function Beers() {
const [beers, setBeers] = useState([]);
const [search, setSearch] = useState("");

useEffect(() => {
fetchBeers().then((res) => setBeers(res.data));
}, []);

return (
<div>
<SearchBar setSearch={setSearch} />
<div className="beer-list-container">
{beers
.filter((beer) => beer.name.toLowerCase().includes(search.toLowerCase()))
.map((beer) => (
<Link to={`/beers/${beer._id}`} key={beer._id} className="beer-card">
<img src={beer.image_url} alt={beer.name} style={{ width: "50px" }} />
<div>
<h3>{beer.name}</h3>
<p>{beer.tagline}</p>
</div>
</Link>

))}
</div>
</div>
);
}

export default Beers;
57 changes: 57 additions & 0 deletions src/pages/Home.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Link } from "react-router-dom";
import beersImg from "../assets/beers.png";
import randomBeerImg from "../assets/random-beer.png";
import newBeerImg from "../assets/new-beer.png";
import "../App.css";

const Home = () => {
const links = [
{
path: "/beers",
label: "All Beers",
image: beersImg,
description:
"Explore our collection of handcrafted beers. Find the perfect drink for any occasion!",
},
{
path: "/random-beer",
label: "Random Beer",
image: randomBeerImg,
description:
"Feeling adventurous? Let us surprise you with a random beer from our collection!",
},
{
path: "/new-beer",
label: "New Beer",
image: newBeerImg,
description:
"Create your own beer entry! Share details about your favorite brew.",
},
];

return (
<div className="home-container">

{/* Cards Section */}
<div className="home-card">
{links.map((link, index) => (
<Link
to={link.path}
key={index}
className="normal-text"
>
<img
src={link.image}
alt={link.label}
className="w-full h-40 object-cover rounded-md mb-4"
/>
<h2 className="text-2xl font-bold text-blue-600 mb-2">{link.label}</h2>
<p className="text-gray-700 text-sm">{link.description}</p><br/>
</Link>
))}
</div>
</div>
);
};

export default Home;
Loading