Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

London 10 | Elena Barker | Full-Stack-Project | Level-300 #428

Closed
wants to merge 34 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
fba498e
Initial commit
ElenaBarker Aug 26, 2023
cbc77f3
Level 100 done
ElenaBarker Aug 30, 2023
cab558c
Create .gitignore
ElenaBarker Sep 1, 2023
7c9d9de
adding gitignore file
ElenaBarker Sep 6, 2023
6a55f61
removing node modules
ElenaBarker Sep 6, 2023
5e5873d
updated App.js and Video.js
ElenaBarker Sep 12, 2023
4f91344
updates in App.js, Video.js, created new component CountVotes.js
ElenaBarker Sep 12, 2023
42a2d9a
installed "@material-ui/icons", updated CountVotes.js, added CSS
ElenaBarker Sep 13, 2023
dbcc61d
Level 200 done
ElenaBarker Sep 6, 2023
3cd83bb
adding express
ElenaBarker Sep 6, 2023
a2fec56
installed CORS, made Fetch for all videos
ElenaBarker Sep 14, 2023
a330081
added Delete button in video.js component, updated server,.js, Level…
ElenaBarker Sep 15, 2023
ddc025e
installed .env and .pg, updated app.js in client, created database, u…
ElenaBarker Sep 15, 2023
2c19af7
installed CORS, made Fetch for all videos
ElenaBarker Sep 14, 2023
586f378
removed merge conflicts
ElenaBarker Sep 15, 2023
2237025
update post endpoint
ElenaBarker Sep 16, 2023
9a5cc7a
small mistake resolved
ElenaBarker Sep 16, 2023
b94f33b
moved .env in .gitignore
ElenaBarker Sep 19, 2023
4d08dfc
installed @material-ui/core
ElenaBarker Sep 19, 2023
b03bd01
removed background image
ElenaBarker Sep 19, 2023
d96a624
changed localhost to link from Render in frontend
ElenaBarker Sep 19, 2023
7330ec5
Update server.js
ElenaBarker Sep 30, 2023
af7953a
Update App.css
ElenaBarker Oct 25, 2023
1650206
background color changed
ElenaBarker Oct 25, 2023
8501eee
updated POST and DELETE enpoints
ElenaBarker Oct 28, 2023
cb49d7f
updated frontend to be able to delete videos
ElenaBarker Oct 28, 2023
d462f56
implemented CSS for buttons
ElenaBarker Oct 30, 2023
1789dba
Updated query for POST endpoint to be able to get Id
ElenaBarker Oct 30, 2023
4d2a688
updated code for Add Video
ElenaBarker Oct 30, 2023
05684ea
added validation to only be able add videos with YouTube URL
ElenaBarker Oct 31, 2023
1b5d964
Update App.js
ElenaBarker Nov 23, 2023
09d71cd
Create data.sql
ElenaBarker Feb 13, 2024
2b62237
Update App.js
ElenaBarker Feb 13, 2024
8a17143
Update App.js
ElenaBarker Feb 13, 2024
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
server/node_modules
client/node_modules
server/.env
711 changes: 689 additions & 22 deletions client/package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@material-ui/core": "^4.12.4",
"@material-ui/icons": "^4.11.3",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.2.7",
"@testing-library/user-event": "^12.1.10",
Expand Down
1 change: 1 addition & 0 deletions client/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
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>
Expand Down
51 changes: 51 additions & 0 deletions client/src/AddVideo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React, { useState } from "react";

const AddVideo = ({ onAddVideo }) => {
const [title, setTitle] = useState("");
const [url, setUrl] = useState("");

const clearForm = () => {
setTitle("");
setUrl("");
};

const isYouTubeURL = (inputURL) => {
const youTubePattern = /^https:\/\/www.youtube.com\/watch\?v=.+$/;
return youTubePattern.test(inputURL);
};

const handleSubmit = (e) => {
e.preventDefault();

if (isYouTubeURL(url)) {
onAddVideo(title, url, clearForm);
} else {
alert("Please enter a valid YouTube URL");
clearForm();
}
};

return (
<div className="add-video">
<h3>Add a Video</h3>
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="Title"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<input
type="text"
placeholder="URL"
value={url}
onChange={(e) => setUrl(e.target.value)}
/>
<button type="submit">Add Video</button>{" "}
</form>
</div>
);
};


export default AddVideo;
1 change: 1 addition & 0 deletions client/src/App.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.App {
text-align: center;

}
72 changes: 70 additions & 2 deletions client/src/App.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,81 @@
import "./App.css";
import React, { useEffect, useState } from "react";
import Video from "./Video";
import AddVideo from "./AddVideo";

const App = () => {
const [videos, setVideos] = useState([]);

useEffect(() => {
fetchAllVideos();
}, []);

const fetchAllVideos = async () => {
try {
const response = await fetch(
"https://full-stack-project-video-reccomendations.onrender.com/videos"
);
if (!response.ok) {
throw Error(`Failed to fetch. Error: ${response.status}`);
}
const data = await response.json();
setVideos(data);
} catch (error) {
console.error(error);
}
};

const handleAddVideo = async (title, url, clearForm) => {
try {
const response = await fetch(
"https://full-stack-project-video-reccomendations.onrender.com/videos",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ title, url, rating: 0 }),
}
);
if (!response.ok) {
throw Error(`Failed to add video. Error: ${response.status}`);
}
await fetchAllVideos();
clearForm();
} catch (error) {
console.error(error);
}
};

const handleDeleteVideo = async (id) => {
try {
const response = await fetch(
`https://full-stack-project-video-reccomendations.onrender.com/videos/${id}`,
{
method: "DELETE",
}
);
if (!response.ok) {
throw new Error("Video not found!");
}
await fetchAllVideos();
} catch (error) {
console.log(error.message);
}
};

function App() {
return (
<div className="App">
<header className="App-header">
<h1>Video Recommendation</h1>
</header>
{videos.map((video) => (
<Video key={video.id} video={video} onDeleteVideo={handleDeleteVideo} />
))}

<AddVideo onAddVideo={handleAddVideo} />
</div>
);
}
};

export default App;
71 changes: 71 additions & 0 deletions client/src/CountVotes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { useState } from "react";
import ThumbUp from "@material-ui/icons/ThumbUp";
import ThumbDown from "@material-ui/icons/ThumbDown";

const CountVotes = () => {
const [likeCount, setLikeCount] = useState(0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These three pieces of state all only ever change together, which means they maybe could be collapsed into one piece of state (maybe with values "like", "neutral", and "dislike") - what do you think?

const [dislikeCount, setDislikeCount] = useState(0);
const [activeButton, setActiveButton] = useState("none");

const handleLikeClick = () => {
if (activeButton === "none") {
setLikeCount(likeCount + 1);
setActiveButton("like");
return;
}

if (activeButton === "like") {
setLikeCount(likeCount - 1);
setActiveButton("none");
return;
}

if (activeButton === "dislike") {
setLikeCount(likeCount + 1);
setDislikeCount(dislikeCount - 1);
setActiveButton("like");
}
};
const handleDislikeClick = () => {
if (activeButton === "none") {
setDislikeCount(dislikeCount + 1);
setActiveButton("dislike");
return;
}
if (activeButton === "dislike") {
setDislikeCount(dislikeCount - 1);
setActiveButton("none");
return;
}
if (activeButton === "like") {
setDislikeCount(dislikeCount + 1);
setLikeCount(likeCount - 1);
setActiveButton("dislike");
}
};
return (
<div className="main-container">
<div className="button-container">
<button
className={`button ${activeButton === "like" ? "like-active" : ""}`}
onClick={handleLikeClick}
>
<ThumbUp />
Like {likeCount}
</button>

<button
className={`button ${
activeButton === "dislike" ? "dislike-active" : ""
}`}
onClick={handleDislikeClick}
>
<ThumbDown />
Dislike {dislikeCount}
</button>
</div>
</div>
);
};

export default CountVotes;
63 changes: 63 additions & 0 deletions client/src/Data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
export const videosData = [
{
id: 523523,
title: "Never Gonna Give You Up",
url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
rating: 23,
},
{
id: 523427,
title: "The Coding Train",
url: "https://www.youtube.com/watch?v=HerCR8bw_GE",
rating: 230,
},
{
id: 82653,
title: "Mac & Cheese | Basics with Babish",
url: "https://www.youtube.com/watch?v=FUeyrEN14Rk",
rating: 2111,
},
{
id: 858566,
title: "Videos for Cats to Watch - 8 Hour Bird Bonanza",
url: "https://www.youtube.com/watch?v=xbs7FT7dXYc",
rating: 11,
},
{
id: 453538,
title:
"The Complete London 2012 Opening Ceremony | London 2012 Olympic Games",
url: "https://www.youtube.com/watch?v=4As0e4de-rI",
rating: 3211,
},
{
id: 283634,
title: "Learn Unity - Beginner's Game Development Course",
url: "https://www.youtube.com/watch?v=gB1F9G0JXOo",
rating: 211,
},
{
id: 562824,
title: "Cracking Enigma in 2021 - Computerphile",
url: "https://www.youtube.com/watch?v=RzWB5jL5RX0",
rating: 111,
},
{
id: 442452,
title: "Coding Adventure: Chess AI",
url: "https://www.youtube.com/watch?v=U4ogK0MIzqk",
rating: 671,
},
{
id: 536363,
title: "Coding Adventure: Ant and Slime Simulations",
url: "https://www.youtube.com/watch?v=X-iSQQgOd1A",
rating: 76,
},
{
id: 323445,
title: "Why the Tour de France is so brutal",
url: "https://www.youtube.com/watch?v=ZacOS8NBK6U",
rating: 73,
},
];
31 changes: 31 additions & 0 deletions client/src/Video.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from "react";
import CountVotes from "./CountVotes.js";

const Video = ({ video, onDeleteVideo }) => {
let videoID = video.url.split("=")[1];
const handleDelete = () => {
onDeleteVideo(video.id);
};
return (
<div className="video">
<h3>{video.title}</h3>
<iframe
width="560"
height="315"
src={`https://www.youtube.com/embed/${videoID}`}
title="YouTube video player"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
></iframe>

<p> {video.votes}</p>
<CountVotes />
<button className="button" onClick={handleDelete}>
Delete
</button>
</div>
);
};

export default Video;
Loading
Loading