Skip to content

Commit

Permalink
feat: add previews to add page, chore: clean up admin pages, chore: f…
Browse files Browse the repository at this point in the history
…ix centering
  • Loading branch information
Mooshay105 committed Feb 7, 2025
1 parent 1b5fc5e commit 37579af
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 96 deletions.
7 changes: 1 addition & 6 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,7 @@ function App() {
}
/>
<Route path="/search" element={<Search />} />
<Route
path="/admin"
element={
<Admin movies={movies} documentaries={documentaries} tvshows={tvshows} />
}
/>
<Route path="/admin" element={<Admin allVideos={videos} />} />
<Route path="/admin/add" element={<Add />} />
{renderAdminDeletePages(videos)}
{renderAdminEditPages(videos)}
Expand Down
25 changes: 24 additions & 1 deletion src/assets/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,23 @@ footer {
width: 100vw;
}

.centerVertical {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
text-align: center;
height: 100vh;
}

.centerHorizontal {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
width: 100vw;
}

.buttons {
display: flex;
flex-direction: row;
Expand Down Expand Up @@ -248,7 +265,6 @@ footer {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}

.addVideoInput {
Expand Down Expand Up @@ -297,3 +313,10 @@ footer {
margin-top: 5px;
margin-bottom: 5px;
}

.addVideoPreview {
height: 200px;
margin-bottom: 10px;
border-radius: 12px;
box-shadow: 0px 8px 15px rgba(0, 0, 0, 0.3);
}
112 changes: 59 additions & 53 deletions src/pages/admin/Add.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,88 +3,82 @@ import GlobalFooter from "../../components/GlobalFooter";
import CustomBreak from "../../components/CustomBreak";
import { useState } from "react";
import { UploadButton } from "../../utils/uploadthing";
import { postJSONData } from "../../utils/api";

/* TODO: Clean Up */
import { addVideo } from "../../utils/videoManipulation";
import { Video } from "../../utils/types";

function Add() {
document.title = "Hexagon TV Add | Add Video";

const [thumbnailURL, setThumbnailURL] = useState("");
const [videoURL, setVideoURL] = useState("");
const [name, setName] = useState("");
const [description, setDescription] = useState("");
const [urlName, setUrlName] = useState("");
const [ageRating, setAgeRating] = useState("");
const [category, setCategory] = useState("");
const [video, setVideo] = useState<Video>({
id: 0,
name: "",
description: "",
category: "",
thumbnailURL: "",
videoURL: "",
date: "",
rating: "",
ratingInfo: "",
urlName: "",
});
const [alert, setAlert] = useState("");

async function handleSubmit() {
const VITE_PUBLIC_API_URL = import.meta.env.VITE_PUBLIC_API_URL;
const VITE_PUBLIC_CLERK_SIGN_IN_URL = import.meta.env.VITE_PUBLIC_CLERK_SIGN_IN_URL;
async function handleAddVideo() {
if (
!name ||
!description ||
!category ||
!thumbnailURL ||
!videoURL ||
!urlName ||
!ageRating
!video.name ||
!video.description ||
!video.category ||
!video.thumbnailURL ||
!video.videoURL
) {
setAlert("Please fill out all fields!");
return;
}
const data = await postJSONData(`${VITE_PUBLIC_API_URL}/videoAPI/add`, {
userId: localStorage.getItem("userId") || "",
sessionId: localStorage.getItem("sessionId") || "",
name,
description,
category,
thumbnailURL,
videoURL,
urlName,
ageRating,
});
if (data.status !== "success") {
window.location.href = VITE_PUBLIC_CLERK_SIGN_IN_URL;
return;
}
window.location.href = "/admin";
addVideo(video);
}

return (
<div className="main">
<GlobalNavBar />
<CustomBreak height={1} />
<div className="center">
<CustomBreak height={2} />
<div className="centerHorizontal">
<div className="addVideoPage">
<h1 style={{ textAlign: "center" }}>Add A Video</h1>
{alert && <p style={{ color: "red" }}>{alert}</p>}
<div className="addVideoPageForm">
<h2 style={{ textAlign: "center", marginBottom: "10px" }}>
Upload Thumbnail
</h2>
{video.thumbnailURL ? (
<img src={video.thumbnailURL} alt="Thumbnail" className="addVideoPreview" />
) : null}
<UploadButton
endpoint="thumbnail"
onUploadError={(error) => {
console.error("ERROR:", error, error.cause);
}}
onClientUploadComplete={(data: any) => {
setThumbnailURL(data[0].url);
setVideo((prevState: any) => ({
...prevState,
thumbnailURL: data[0].url,
}));
}}
headers={{
sessionId: localStorage.getItem("sessionId") || "",
userId: localStorage.getItem("userId") || "",
}}
/>
<h2 style={{ textAlign: "center", marginBottom: "10px" }}>Upload Video</h2>
{video.videoURL ? (
<video src={video.videoURL} controls className="addVideoPreview" />
) : null}
<UploadButton
endpoint="video"
onUploadError={(error) => {
console.error("ERROR:", error, error.cause);
}}
onClientUploadComplete={(data: any) => {
setVideoURL(data[0].url);
setVideo((prevState: any) => ({ ...prevState, videoURL: data[0].url }));
}}
headers={{
sessionId: localStorage.getItem("sessionId") || "",
Expand All @@ -95,35 +89,47 @@ function Add() {
className="addVideoInput"
type="text"
placeholder="Name"
value={name}
onChange={(e) => setName(e.target.value)}
value={video.name}
onChange={(e) =>
setVideo((prevState: any) => ({ ...prevState, name: e.target.value }))
}
/>
<input
className="addVideoInput"
type="text"
placeholder="Description"
value={description}
onChange={(e) => setDescription(e.target.value)}
value={video.description}
onChange={(e) =>
setVideo((prevState: any) => ({
...prevState,
description: e.target.value,
}))
}
/>
<input
className="addVideoInput"
type="text"
placeholder="urlName"
value={urlName}
onChange={(e) => setUrlName(e.target.value)}
value={video.urlName}
onChange={(e) =>
setVideo((prevState: any) => ({ ...prevState, urlName: e.target.value }))
}
/>
<input
className="addVideoInput"
type="text"
placeholder="ageRating"
value={ageRating}
onChange={(e) => setAgeRating(e.target.value)}
value={video.rating}
onChange={(e) =>
setVideo((prevState: any) => ({ ...prevState, rating: e.target.value }))
}
/>
{/* dropdown */}
<select
id="category"
value={category || "none"}
onChange={(e) => setCategory(e.target.value)}
value={video.category || "none"}
onChange={(e) =>
setVideo((prevState: any) => ({ ...prevState, category: e.target.value }))
}
className="addVideoDropdown"
>
<option value="none" disabled hidden>
Expand All @@ -133,8 +139,8 @@ function Add() {
<option value="tvshows">TV Show</option>
<option value="documentaries">Documentaries</option>
</select>
<button className="addVideoButton" onClick={() => handleSubmit()}>
Submit
<button className="addVideoButton" onClick={() => handleAddVideo()}>
Add
</button>
</div>
</div>
Expand Down
12 changes: 4 additions & 8 deletions src/pages/admin/Admin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,12 @@ import CustomBreak from "../../components/CustomBreak";
import { Video } from "../../utils/types";

interface AdminProps {
movies: any;
documentaries: any;
tvshows: any;
allVideos: Video[];
}

function Admin({ movies, documentaries, tvshows }: AdminProps) {
movies;
documentaries;
tvshows;
function Admin({ allVideos }: AdminProps) {
document.title = "Hexagon TV Admin | Home";

return (
<div className="main">
<GlobalNavBar />
Expand All @@ -30,7 +26,7 @@ function Admin({ movies, documentaries, tvshows }: AdminProps) {
</div>
<CustomBreak height={1} />
<div className="adminPageCardsWrapper">
{movies
{allVideos
.slice()
.reverse()
.map((video: Video) => (
Expand Down
34 changes: 6 additions & 28 deletions src/pages/admin/Delete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,12 @@ import GlobalFooter from "../../components/GlobalFooter";
import { Video } from "../../utils/types";
import CustomBreak from "../../components/CustomBreak";
import { useState } from "react";
import { deleteJSONData } from "../../utils/api";
import { deleteVideo } from "../../utils/videoManipulation";

interface DeleteProps {
video: Video;
}

function handleCancel() {
window.location.href = "/admin";
}

async function handleRemove(urlName: string, setStatus: any) {
const VITE_PUBLIC_API_URL = import.meta.env.VITE_PUBLIC_API_URL;
const userId = localStorage.getItem("userId");
const sessionId = localStorage.getItem("sessionId");
setStatus("Removing...");
try {
const responce = await deleteJSONData(`${VITE_PUBLIC_API_URL}/videoAPI/delete`, {
urlName: urlName,
userId: userId,
sessionId: sessionId,
});
if (responce.status === "success") {
window.location.href = "/";
} else {
setStatus("Failed to remove!");
}
} catch (e: any) {
setStatus("Failed to remove!");
}
}

function Delete({ video }: DeleteProps) {
document.title = "Hexagon TV Admin | Delete " + video.name;
const [status, setStatus] = useState("Remove");
Expand All @@ -48,11 +23,14 @@ function Delete({ video }: DeleteProps) {
<button
className="redButton"
style={{ width: "fit-content" }}
onClick={() => handleRemove(video.urlName, setStatus)}
onClick={() => deleteVideo(video.urlName, setStatus)}
>
{status}
</button>
<button className="whiteButton" onClick={() => handleCancel()}>
<button
className="whiteButton"
onClick={() => (window.location.href = "/admin")}
>
Cancel
</button>
</div>
Expand Down
53 changes: 53 additions & 0 deletions src/utils/videoManipulation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { deleteJSONData, postJSONData } from "./api";
import { Video } from "./types";

async function addVideo(video: Video) {
const VITE_PUBLIC_API_URL = import.meta.env.VITE_PUBLIC_API_URL;
const VITE_PUBLIC_CLERK_SIGN_IN_URL = import.meta.env.VITE_PUBLIC_CLERK_SIGN_IN_URL;
const name = video.name;
const description = video.description;
const category = video.category;
const thumbnailURL = video.thumbnailURL;
const videoURL = video.videoURL;
const urlName = video.urlName;
const ageRating = video.rating;
const data = await postJSONData(`${VITE_PUBLIC_API_URL}/videoAPI/add`, {
userId: localStorage.getItem("userId") || "",
sessionId: localStorage.getItem("sessionId") || "",
name,
description,
category,
thumbnailURL,
videoURL,
urlName,
ageRating,
});
if (data.status !== "success") {
window.location.href = VITE_PUBLIC_CLERK_SIGN_IN_URL;
return;
}
window.location.href = "/admin";
}

async function deleteVideo(urlName: string, setStatus: any) {
const VITE_PUBLIC_API_URL = import.meta.env.VITE_PUBLIC_API_URL;
const userId = localStorage.getItem("userId");
const sessionId = localStorage.getItem("sessionId");
setStatus("Removing...");
try {
const responce = await deleteJSONData(`${VITE_PUBLIC_API_URL}/videoAPI/delete`, {
urlName: urlName,
userId: userId,
sessionId: sessionId,
});
if (responce.status === "success") {
window.location.href = "/admin";
} else {
setStatus("Failed to remove!");
}
} catch (e: any) {
setStatus("Failed to remove!");
}
}

export { addVideo, deleteVideo };

0 comments on commit 37579af

Please sign in to comment.