-
-
Notifications
You must be signed in to change notification settings - Fork 358
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
Closed
Changes from all commits
Commits
Show all changes
34 commits
Select commit
Hold shift + click to select a range
fba498e
Initial commit
ElenaBarker cbc77f3
Level 100 done
ElenaBarker cab558c
Create .gitignore
ElenaBarker 7c9d9de
adding gitignore file
ElenaBarker 6a55f61
removing node modules
ElenaBarker 5e5873d
updated App.js and Video.js
ElenaBarker 4f91344
updates in App.js, Video.js, created new component CountVotes.js
ElenaBarker 42a2d9a
installed "@material-ui/icons", updated CountVotes.js, added CSS
ElenaBarker dbcc61d
Level 200 done
ElenaBarker 3cd83bb
adding express
ElenaBarker a2fec56
installed CORS, made Fetch for all videos
ElenaBarker a330081
added Delete button in video.js component, updated server,.js, Level…
ElenaBarker ddc025e
installed .env and .pg, updated app.js in client, created database, u…
ElenaBarker 2c19af7
installed CORS, made Fetch for all videos
ElenaBarker 586f378
removed merge conflicts
ElenaBarker 2237025
update post endpoint
ElenaBarker 9a5cc7a
small mistake resolved
ElenaBarker b94f33b
moved .env in .gitignore
ElenaBarker 4d08dfc
installed @material-ui/core
ElenaBarker b03bd01
removed background image
ElenaBarker d96a624
changed localhost to link from Render in frontend
ElenaBarker 7330ec5
Update server.js
ElenaBarker af7953a
Update App.css
ElenaBarker 1650206
background color changed
ElenaBarker 8501eee
updated POST and DELETE enpoints
ElenaBarker cb49d7f
updated frontend to be able to delete videos
ElenaBarker d462f56
implemented CSS for buttons
ElenaBarker 1789dba
Updated query for POST endpoint to be able to get Id
ElenaBarker 4d2a688
updated code for Add Video
ElenaBarker 05684ea
added validation to only be able add videos with YouTube URL
ElenaBarker 1b5d964
Update App.js
ElenaBarker 09d71cd
Create data.sql
ElenaBarker 2b62237
Update App.js
ElenaBarker 8a17143
Update App.js
ElenaBarker File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
server/node_modules | ||
client/node_modules | ||
server/.env |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
.App { | ||
text-align: center; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
}, | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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?