Files
vod-system/frontend/src/pages/MyClips.tsx
Dylan De Faoite eab3f8be20
All checks were successful
CI / Maven unit tests (push) Successful in 14s
CI / Build and push images (push) Has been skipped
CI / Deploy to server (push) Has been skipped
restyle the rest of the pages
2026-08-02 16:32:00 +01:00

76 lines
3.0 KiB
TypeScript

import VideoCard from "../components/video/VideoCard";
import PageHeader from "../components/PageHeader";
import NoAccessPage from "../components/NoAccessPage";
import { useEffect, useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import { getClips, deleteClip } from "../utils/api/clips";
import { useAuth } from "../utils/AuthContext";
import type { Clip } from "../utils/types";
const MyClips = () => {
const { user, loading } = useAuth();
const [clips, setClips] = useState<Clip[]>([]);
const [error, setError] = useState<null | string>(null);
const navigate = useNavigate();
useEffect(() => {
if (!user) return;
getClips()
.then((data) => setClips(data.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime())))
.catch((err) => setError(err instanceof Error ? err.message : "Failed to load clips"));
}, [user]);
const handleDelete = async (id: number) => {
try {
await deleteClip(id);
setClips(prev => prev.filter(c => c.id !== id));
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to delete clip");
}
};
if (loading) return null;
if (!user) return <NoAccessPage />;
return (
<div className="mx-auto max-w-[1180px] px-13 pt-10 pb-18">
<PageHeader kicker="Library" title="Clips">
<p className="font-data text-[13px] text-faint-mono pt-6">{clips.length} cut</p>
</PageHeader>
<div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-[18px]">
{clips.map((clip) => (
<VideoCard
key={clip.id}
id={clip.id}
title={clip.title}
duration={clip.duration}
createdAt={clip.createdAt}
width={clip.width}
height={clip.height}
fps={clip.fps}
fileSize={clip.fileSize}
onEdit={() => navigate(`/clips/${clip.id}/edit`)}
onDelete={() => handleDelete(clip.id)}
/>
))}
</div>
{clips.length === 0 && !error && (
<div className="flex flex-col items-center justify-center gap-1.5 py-20 text-center">
<h2 className="font-heading text-[25px]">No clips yet.</h2>
<p className="font-body text-[14.5px] text-muted max-w-[42ch] text-pretty">
Cut one from the stream panel, or{" "}
<Link to="/create" className="text-accent hover:text-accent-hover">upload a file</Link>{" "}
to trim it down here.
</p>
</div>
)}
{error && <p className="font-body text-[13px] text-live-red mt-6">{error}</p>}
</div>
);
}
export default MyClips;