import clsx from "clsx"; import { formatTime, stringToDate, dateToTimeAgo } from "../../utils/utils.ts"; import { Link } from "react-router-dom"; import { useEffect, useRef, useState } from "react"; import { isThumbnailAvailable } from "../../utils/api/client.ts"; import { MoreVertical, Pencil, Trash2 } from "lucide-react"; type VideoCardProps = { id: number, title: string, duration: number, createdAt: string, onEdit?: () => void, onDelete?: () => void, className?: string, mediaApiPath?: string, playerPath?: string, itemLabel?: string, } const fallbackThumbnail = "../../../public/default_thumbnail.png"; const API_URL = import.meta.env.VITE_API_URL; const VideoCard = ({ id, title, duration, createdAt, onEdit, onDelete, className, mediaApiPath = '/api/v1/clips', playerPath = '/video', itemLabel = 'clip' }: VideoCardProps) => { const [timeAgo, setTimeAgo] = useState(dateToTimeAgo(stringToDate(createdAt))); const [thumbnailAvailable, setThumbnailAvailable] = useState(true); const [menuOpen, setMenuOpen] = useState(false); const [confirmDelete, setConfirmDelete] = useState(false); const menuRef = useRef(null); const thumbnailUrl = `${API_URL}${mediaApiPath}/${id}/thumbnail`; useEffect(() => { const interval = setInterval(() => { setTimeAgo(dateToTimeAgo(stringToDate(createdAt))); }, 1000); return () => clearInterval(interval); }, [createdAt]); useEffect(() => { isThumbnailAvailable(thumbnailUrl) .then(setThumbnailAvailable) .catch(() => setThumbnailAvailable(false)); }, [thumbnailUrl]); useEffect(() => { if (!menuOpen) return; const handleClickOutside = (e: MouseEvent) => { if (menuRef.current && !menuRef.current.contains(e.target as Node)) { setMenuOpen(false); setConfirmDelete(false); } }; document.addEventListener("mousedown", handleClickOutside); return () => document.removeEventListener("mousedown", handleClickOutside); }, [menuOpen]); const stopAndRun = (e: React.MouseEvent, fn: () => void) => { e.preventDefault(); e.stopPropagation(); fn(); }; return (
Video Thumbnail {formatTime(duration)} {(onEdit || onDelete) && (
e.preventDefault()} > {menuOpen && (
{!confirmDelete && (<> {onEdit && ( )} {onDelete && ( )} )} {confirmDelete && (

Delete this {itemLabel}?

)}
)}
)}

{title === "" ? "(No Title)" : title}

{timeAgo}

); } export default VideoCard;