forked from CodeYourFuture/Full-Stack-Project-Assessment
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' of https://github.com/RbAvci/Full-Stack-Project-A…
…ssessment into ZP/delete-videos-endpoints
- Loading branch information
Showing
12 changed files
with
377 additions
and
16 deletions.
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
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,33 @@ | ||
import React from "react"; | ||
|
||
const DeleteVideoRecommendation = ({ videoId, onDelete }) => { | ||
const handleDelete = () => { | ||
fetch(`/api/videos/${videoId}`, { | ||
method: "DELETE", | ||
headers: { | ||
Accept: "application/json", | ||
"Content-Type": "application/json", | ||
}, | ||
}) | ||
.then((response) => { | ||
if (!response.ok) { | ||
throw new Error("Failed to delete the video"); | ||
} | ||
return response.json(); | ||
}) | ||
.then((data) => { | ||
onDelete(videoId); | ||
}) | ||
.catch((error) => { | ||
console.error(error); | ||
}); | ||
}; | ||
|
||
return ( | ||
<button className="submit-button" onClick={handleDelete}> | ||
Remove Video | ||
</button> | ||
); | ||
}; | ||
|
||
export default DeleteVideoRecommendation; |
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,46 @@ | ||
.form-container { | ||
padding: 20px; | ||
border: 1px solid #ccc; | ||
border-radius: 5px; | ||
max-width: 400px; | ||
margin: auto; | ||
margin-top: 30px; | ||
} | ||
|
||
.form-header { | ||
text-align: center; | ||
margin-bottom: 20px; | ||
} | ||
|
||
.form-body { | ||
display: flex; | ||
flex-direction: column; | ||
} | ||
|
||
.input-group { | ||
margin-bottom: 15px; | ||
} | ||
|
||
.input-group label { | ||
margin-bottom: 5px; | ||
display: block; | ||
} | ||
|
||
.input-group input { | ||
width: 100%; | ||
padding: 8px; | ||
box-sizing: border-box; | ||
} | ||
|
||
.submit-button { | ||
padding: 10px 15px; | ||
background-color: #003b7a; | ||
color: white; | ||
border: none; | ||
border-radius: 3px; | ||
cursor: pointer; | ||
} | ||
|
||
.submit-button:hover { | ||
background-color: #f5ba13; | ||
} |
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 @@ | ||
import React, { useState } from "react"; | ||
import "./NewVideoForm.css"; | ||
|
||
const NewVideoForm = ({ onSubmit }) => { | ||
const [title, setTitle] = useState(""); | ||
const [src, setSrc] = useState(""); | ||
|
||
const handleSubmit = (e) => { | ||
e.preventDefault(); | ||
|
||
fetch("/api/videos", { | ||
method: "POST", | ||
headers: { | ||
Accept: "application/json", | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ title, src }), | ||
}) | ||
.then((response) => response.json()) | ||
.then((data) => { | ||
console.log(JSON.stringify(data)); | ||
}) | ||
.catch((error) => { | ||
console.error(error); | ||
}); | ||
onSubmit(); | ||
setTitle(""); | ||
setSrc(""); | ||
}; | ||
|
||
return ( | ||
<div className="form-container"> | ||
<h2 className="form-header">Add New Video</h2> | ||
<form className="form-body" onSubmit={handleSubmit}> | ||
<div className="input-group"> | ||
<label htmlFor="title">Video Title: </label> | ||
<input | ||
type="text" | ||
id="title" | ||
value={title} | ||
onChange={(e) => setTitle(e.target.value)} | ||
required | ||
/> | ||
</div> | ||
<div className="input-group"> | ||
<label htmlFor="src">Video URL: </label> | ||
<input | ||
type="url" | ||
id="src" | ||
value={src} | ||
onChange={(e) => setSrc(e.target.value)} | ||
required | ||
/> | ||
</div> | ||
<button className="submit-button" type="submit"> | ||
Submit | ||
</button> | ||
</form> | ||
</div> | ||
); | ||
}; | ||
|
||
export default NewVideoForm; |
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,43 @@ | ||
const RatingDisplay = ({ videoId, rating, onUpdate }) => { | ||
const handleRating = (updatedRating) => { | ||
fetch(`/api/videos/${videoId}/rating`, { | ||
method: "PUT", | ||
headers: { | ||
Accept: "application/json", | ||
"Content-Type": "application/json", | ||
}, | ||
|
||
body: JSON.stringify({ | ||
rating: updatedRating, | ||
}), | ||
}) | ||
.then((response) => { | ||
if (!response.ok) { | ||
throw new Error("Failed to update the video rating"); | ||
} | ||
return response.json(); | ||
}) | ||
.then((data) => { | ||
onUpdate(videoId, data.data.rating); | ||
}) | ||
.catch((error) => { | ||
console.error(error); | ||
}); | ||
}; | ||
|
||
return ( | ||
<div> | ||
<div>{rating}</div> | ||
<div> | ||
<button onClick={() => handleRating(rating + 1)}> | ||
Thumbs-up! <i className="fa fa-thumbs-up"></i> | ||
</button> | ||
<button onClick={() => handleRating(rating - 1)}> | ||
Thumbs-down! <i className="fa fa-thumbs-down"></i> | ||
</button> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default RatingDisplay; |
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,44 @@ | ||
:root { | ||
--primary-color: #007bff; | ||
--container-width: 90%; | ||
--gap-size: 20px; | ||
} | ||
|
||
.video-list-container { | ||
padding: 20px; | ||
margin: 0 auto; | ||
width: var(--container-width); | ||
} | ||
|
||
.video-list { | ||
display: grid; | ||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); | ||
gap: var(--gap-size); | ||
} | ||
|
||
.video-item { | ||
padding: 10px; | ||
border: 1px solid #ddd; | ||
border-radius: 5px; | ||
background-color: #f9f9f9; | ||
} | ||
|
||
.video-title { | ||
font-size: 18px; | ||
margin-bottom: 10px; | ||
font-family: Arial, sans-serif; | ||
} | ||
|
||
.video-item iframe { | ||
width: 100%; | ||
height: 200px; /* Adjust height of each video */ | ||
border: none; | ||
} | ||
|
||
.video-title a { | ||
color: var(--primary-color); | ||
} | ||
|
||
.video-title a:hover { | ||
text-decoration: underline; | ||
} |
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,83 @@ | ||
import React, { useState, useEffect } from "react"; | ||
import "./VideoRecommendations.css"; | ||
import DeleteVideoRecommendation from "./DeleteVideoRecommendation"; | ||
import NewVideoForm from "./NewVideoForm.jsx"; | ||
import RatingDisplay from "./RatingDisplay.jsx"; | ||
const VideoList = () => { | ||
const [videos, setVideos] = useState([]); | ||
|
||
function fetchVideos() { | ||
fetch("/api/videos", { | ||
method: "GET", | ||
headers: { | ||
Accept: "application/json", | ||
}, | ||
}) | ||
.then((response) => response.json()) | ||
.then((data) => { | ||
setVideos(data.sort((a, b) => a.id - b.id)); | ||
}) | ||
.catch((error) => { | ||
console.error(error); | ||
}); | ||
} | ||
|
||
useEffect(() => { | ||
fetchVideos(); | ||
}, []); | ||
|
||
const handleDelete = (videoId) => { | ||
setVideos(videos.filter((video) => video.id !== videoId)); | ||
}; | ||
|
||
const handleRatingUpdate = (videoId, rating) => { | ||
const updatedVideos = videos.map((video) => | ||
video.id === videoId ? { ...video, rating: rating } : video | ||
); | ||
setVideos(updatedVideos); | ||
}; | ||
|
||
function changeYTLinkToEmbed(watchLink) { | ||
const embedLink = watchLink.replace("watch?v=", "embed/"); | ||
return embedLink; | ||
} | ||
|
||
return ( | ||
<div className="video-list-container"> | ||
<div className="video-list"> | ||
{videos.map((videoData, i) => { | ||
const embededLink = changeYTLinkToEmbed(videoData.src); | ||
return ( | ||
<div className="video-item" data-testid="video" key={i}> | ||
<div className="video-title"> | ||
<a href={videoData.src}>{videoData.title}</a> | ||
</div> | ||
<div> | ||
<iframe | ||
title={videoData.title} | ||
width="560" | ||
height="315" | ||
src={embededLink} | ||
frameBorder="0" | ||
allowFullScreen | ||
></iframe> | ||
</div> | ||
<DeleteVideoRecommendation | ||
videoId={videoData.id} | ||
onDelete={handleDelete} | ||
/> | ||
<RatingDisplay | ||
videoId={videoData.id} | ||
rating={videoData.rating} | ||
onUpdate={handleRatingUpdate} | ||
/> | ||
</div> | ||
); | ||
})} | ||
</div> | ||
<NewVideoForm onSubmit={fetchVideos} /> | ||
</div> | ||
); | ||
}; | ||
|
||
export default VideoList; |
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,8 +1,18 @@ | ||
html, | ||
body { | ||
margin: 0; | ||
} | ||
|
||
h1 { | ||
text-align: center; | ||
color: #003b7a; | ||
font-family: "Roboto", sans-serif; | ||
font-weight: 700; | ||
font-style: italic; | ||
} | ||
|
||
.app { | ||
display: grid; | ||
margin: auto; | ||
margin-bottom: 7rem; | ||
} | ||
|
||
body { | ||
background-image: url("https://www.transparenttextures.com/patterns/cubes.png"); | ||
} |
Oops, something went wrong.