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
28,188 changes: 28,188 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
65 changes: 65 additions & 0 deletions public/data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
[
{
"id": "chris-hart",
"author": "Chris Hart",
"posts": [
{
"id": 1,
"title": "Tasty Tacos",
"content": "Here's how to make the best tacos ever."
},
{
"id": 2,
"title": "How to Make a Pizza",
"content": "Here's how to make a pizza."
},
{
"id": 3,
"title": "Cookies and Cream",
"content": "Here's how to make cookies and cream."
}
]
},
{
"id": "sean-shealy",
"author": "Sean Shealy",
"posts": [
{
"id": 1,
"title": "Delicious Donuts",
"content": "Here's how to make the best donuts ever."
},
{
"id": 2,
"title": "How to Make a Burger",
"content": "Here's how to make a burger."
},
{
"id": 3,
"title": "Chocolate and Peanut Butter",
"content": "Here's how to make chocolate and peanut butter."
}
]
},
{
"id": "ashley-grant",
"author": "Ashley Grant",
"posts": [
{
"id": 1,
"title": "Yummy Yogurt",
"content": "Here's how to make the best yogurt ever."
},
{
"id": 2,
"title": "How to Make a Sandwich",
"content": "Here's how to make a sandwich."
},
{
"id": 3,
"title": "Vanilla and Strawberry",
"content": "Here's how to make vanilla and strawberry."
}
]
}
]
31 changes: 8 additions & 23 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,25 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
rel="stylesheet"
/>
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.

Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.

You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.

To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
46 changes: 23 additions & 23 deletions src/App.css
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
.App {
text-align: center;
}

.App-logo {
height: 40vmin;
pointer-events: none;
}

.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}

.App-link {
color: #61dafb;
}
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
26 changes: 7 additions & 19 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,12 @@
import logo from './levvel-logo.svg';
import './App.css';

import { Routes, Route } from "react-router-dom";
import Author from "./Pages/Author";
import Home from "./Pages/Home";
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>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/author/:id" element={<Author />} />
</Routes>
);
}

Expand Down
79 changes: 79 additions & 0 deletions src/Pages/Author.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React from "react";
import { Link, useLocation } from "react-router-dom";

const Author = () => {
const [posts, setPosts] = React.useState([]);
const [authorName, setAuthorName] = React.useState("");
const [error, setError] = React.useState(null);
const location = useLocation();

React.useEffect(() => {
setError(null);
const id = location.pathname.split("/")[2];
const fetchData = async () => {
const response = await fetch("/data.json", {
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
});

const data = await response.json();
const author = data.find((author) => author.id === id);
if (!author) {
setError("Author not found");
return;
}
setPosts(author.posts);
setAuthorName(author.author);
};

fetchData();
}, [location.pathname]);
/**navbar styled with JSX with link to return back to the homepage */
return (
<main>
<nav className="w-full py-3 bg-neutral-400">
<div className="container">
<Link to="/" className="text-white font-bold text-lg">
HOME
</Link>
</div>
</nav>

{error && (
<section className="container">
<div className="text-red-500 my-4 font-bold text-xl">{error}</div>
</section>
)}


{!error && (
<section className="container">
<h1 className="text-2xl font-bold my-4">{authorName}</h1>
<h2 className="text-xl my-2 text-neutral-700 font-serif">
Check out {authorName.split(" ")[0]}'s Recipes!
</h2>

<div className="flex flex-col gap-3">
{posts.map((post) => (
<AuthorPost key={post.id} post={post} />
))}
</div>
</section>
)}
</main>
);
};

/* const used for displaying content and style to the author specific blog page using JSX*/
const AuthorPost = ({ post }) => {
return (
<div className="w-full p-2 flex flex-col gap-2 border-rose-500 border-2 rounded pb-8">
<h2 className="font-bold">{post.title}</h2>
<p>{post.content}</p>
</div>
);
};

export default Author;
63 changes: 63 additions & 0 deletions src/Pages/Home.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React, { useEffect } from "react";
import { Link } from "react-router-dom";

const Home = () => {
const [posts, setPosts] = React.useState([]);

useEffect(() => {
const fetchData = async () => {
const response = await fetch("/data.json", {
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
});
const data = await response.json();
setPosts(data);
};
fetchData();
}, []);
return (
<main>
<nav className="w-full py-3 bg-neutral-400">
<div className="container">
<Link to="/" className="text-white font-bold text-lg">
HOME
</Link>
</div>
</nav>


<section className="container">
<h2 className="text-xl my-2 text-neutral-700 font-serif">
Check out Top Posts from our Authors!
</h2>
<div className="flex flex-col gap-3">
{posts.map((post) => (
<TopPostSection key={post.id} post={post} />
))}
</div>
</section>
</main>
);
};

/** By using the .map method in the section above, I am able to route data stored in the data.json file into this simple div using basic javascript */
const TopPostSection = ({ post }) => {
return (
<div className="flex flex-col gap-1">
<Link
to={`/author/${post.id}`}
className="font-bold text-cyan-700 underline"
>
{post.author}
</Link>
<div className="w-full p-2 flex flex-col gap-2 border-rose-500 border-2 rounded pb-8">
<h2 className="font-semibold">{post.posts[0].title}</h2>
<p>{post.posts[0].content}</p>
</div>
</div>
);
};

export default Home;
25 changes: 15 additions & 10 deletions src/index.css
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
body {
/*Importing Tailwind for styling*/

@tailwind base;
@tailwind components;
@tailwind utilities;


/*styling below applies to all elements on the page*/
* {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
padding: 0;
box-sizing: border-box;
font-family: monospace;
}

code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
/*used @apply to apply custom CSS to container element*/
.container {
@apply w-full max-w-5xl mx-auto px-5;
}
Loading