ADD functionality to fetch and display user clips in MyClips component

This commit is contained in:
2025-07-09 22:57:54 +02:00
parent a78aecdfb6
commit c001a2a1a6
5 changed files with 75 additions and 25 deletions

View File

@@ -4,28 +4,28 @@ import {Link} from "react-router-dom";
type VideoCardProps = { type VideoCardProps = {
title: string, title: string,
length: number, duration: number,
thumbnailUrl: string, thumbnailPath: string,
videoUrl: string, videoPath: string,
className?: string className?: string
} }
const VideoCard = ({ const VideoCard = ({
title, title,
length, duration,
thumbnailUrl, thumbnailPath,
videoUrl, videoPath,
className}: VideoCardProps) => { className}: VideoCardProps) => {
return ( return (
<Link <Link
to={videoUrl} to={videoPath}
> >
<div className={clsx("flex flex-col", className)}> <div className={clsx("flex flex-col", className)}>
<img src={thumbnailUrl} alt="Video Thumbnail" /> <img src={thumbnailPath} alt="Video Thumbnail" />
<div className={"flex flex-row justify-between items-center p-2"}> <div className={"flex flex-row justify-between items-center p-2"}>
<p>{title}</p> <p>{title}</p>
<p>{formatTime(length)}</p> <p>{formatTime(duration)}</p>
</div> </div>
</div> </div>

View File

@@ -1,17 +1,30 @@
import VideoCard from "../components/video/VideoCard"; import VideoCard from "../components/video/VideoCard";
import {useEffect, useState} from "react";
import { getClips } from "../utils/endpoints";
import type { Clip } from "../utils/types";
const MyClips = () => { const MyClips = () => {
const [clips, setClips] = useState<Clip[]>([]);
const [error, setError] = useState<null | string>(null);
useEffect(() => {
getClips(setError).then((data) => setClips(data));
}, []);
return ( return (
<div> <div className={"flex flex-row"}>
{clips.map((clip) => (
<VideoCard <VideoCard
title={"My First Clip"} key={clip.videoPath}
length={120} title={clip.title}
thumbnailUrl={"https://upload.wikimedia.org/wikipedia/commons/1/19/Billy_Joel_Shankbone_NYC_2009.jpg"} duration={clip.duration}
videoUrl={"https://www.youtube.com/watch?v=dQw4w9WgXcQ"} thumbnailPath={clip.thumbnailPath}
className={"w-40"} videoPath={clip.videoPath}
className={"w-30 p-5"}
/> />
))}
{error}
</div> </div>
); );
} }

View File

@@ -1,4 +1,4 @@
import type {VideoMetadata, APIResponse, User} from "./types.ts"; import type {VideoMetadata, APIResponse, User, Clip} from "./types.ts";
/** /**
* Uploads a file to the backend. * Uploads a file to the backend.
@@ -65,7 +65,9 @@ const editFile = async (
/** /**
* Triggers file processing. * Triggers file processing.
*/ */
const processFile = async (uuid: string, setError: Function): Promise<boolean> => { const processFile = async (
uuid: string,
setError: Function): Promise<boolean> => {
try { try {
const response = await fetch(`/api/v1/process/${uuid}`); const response = await fetch(`/api/v1/process/${uuid}`);
@@ -85,7 +87,8 @@ const processFile = async (uuid: string, setError: Function): Promise<boolean> =
/** /**
* Fetches the processing progress percentage. * Fetches the processing progress percentage.
*/ */
const getProgress = async (uuid: string): Promise<number> => { const getProgress = async (
uuid: string): Promise<number> => {
try { try {
const response = await fetch(`/api/v1/progress/${uuid}`); const response = await fetch(`/api/v1/progress/${uuid}`);
@@ -105,7 +108,8 @@ const getProgress = async (uuid: string): Promise<number> => {
/** /**
* Fetches original metadata from the backend. * Fetches original metadata from the backend.
*/ */
const getMetadata = async (uuid: string): Promise<VideoMetadata> => { const getMetadata = async (
uuid: string): Promise<VideoMetadata> => {
try { try {
const response = await fetch(`/api/v1/metadata/original/${uuid}`); const response = await fetch(`/api/v1/metadata/original/${uuid}`);
@@ -143,11 +147,32 @@ const getUser = async (): Promise<null | User > => {
} }
} }
const getClips = async (setError: Function): Promise< Clip[]> => {
try {
const response = await fetch('/api/v1/clips/', {credentials: "include",});
if (!response.ok) {
const errorResult: APIResponse = await response.json();
setError(errorResult.message);
return [];
}
const result: APIResponse = await response.json();
return result.data;
} catch (error: unknown) {
console.error('Error fetching clips:', error);
setError('Failed to fetch clips');
return [];
}
}
export { export {
uploadFile, uploadFile,
editFile, editFile,
processFile, processFile,
getProgress, getProgress,
getMetadata, getMetadata,
getUser getUser,
getClips
}; };

View File

@@ -21,8 +21,21 @@ type User = {
profilePicture: string profilePicture: string
} }
type Clip = {
title: string,
description: string,
duration: number,
thumbnailPath: string,
videoPath: string,
fps: number,
width: number,
height: number,
createdAt: string,
}
export type { export type {
APIResponse, APIResponse,
VideoMetadata, VideoMetadata,
User User,
Clip
} }

View File

@@ -4,7 +4,6 @@ import com.ddf.vodsystem.entities.APIResponse;
import com.ddf.vodsystem.entities.Clip; import com.ddf.vodsystem.entities.Clip;
import com.ddf.vodsystem.exceptions.NotAuthenticated; import com.ddf.vodsystem.exceptions.NotAuthenticated;
import com.ddf.vodsystem.services.ClipService; import com.ddf.vodsystem.services.ClipService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.security.oauth2.core.user.OAuth2User;