94 lines
2.6 KiB
TypeScript
94 lines
2.6 KiB
TypeScript
|
|
"use client";
|
|
|
|
import { useState, useEffect } from "react";
|
|
import {
|
|
Card,
|
|
CardContent,
|
|
CardDescription,
|
|
CardHeader,
|
|
CardTitle,
|
|
} from "@/components/ui/card";
|
|
import { Header } from "@/components/ui/header";
|
|
|
|
interface Video {
|
|
id: number;
|
|
title: string;
|
|
path: string;
|
|
size: number;
|
|
thumbnail: string;
|
|
}
|
|
|
|
const VideosPage = () => {
|
|
const [videos, setVideos] = useState<Video[]>([]);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
fetchVideos();
|
|
}, []);
|
|
|
|
const fetchVideos = async () => {
|
|
try {
|
|
const res = await fetch("/api/videos");
|
|
const data = await res.json();
|
|
setVideos(data);
|
|
} catch (error) {
|
|
console.error('Error fetching videos:', error);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
const formatFileSize = (bytes: number) => {
|
|
if (bytes === 0) return '0 Bytes';
|
|
const k = 1024;
|
|
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
};
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="flex items-center justify-center h-full">
|
|
<div className="text-lg">Loading videos...</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="p-6">
|
|
<Header title="Videos" />
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-6">
|
|
{videos.map((video) => (
|
|
<Card key={video.id} className="overflow-hidden rounded-lg shadow-lg hover:shadow-xl transition-shadow duration-300 ease-in-out">
|
|
<CardContent className="p-0">
|
|
<img
|
|
src={video.thumbnail || "/placeholder.svg"}
|
|
alt={video.title}
|
|
className="w-full h-48 object-cover"
|
|
onError={(e) => {
|
|
(e.target as HTMLImageElement).src = '/placeholder.svg';
|
|
}}
|
|
/>
|
|
</CardContent>
|
|
<CardHeader className="p-4">
|
|
<CardTitle className="text-sm font-semibold truncate">{video.title}</CardTitle>
|
|
<CardDescription className="text-xs">
|
|
<span className="block">Size: {formatFileSize(video.size)}</span>
|
|
<span className="block truncate">Path: {video.path}</span>
|
|
</CardDescription>
|
|
</CardHeader>
|
|
</Card>
|
|
))}
|
|
</div>
|
|
{videos.length === 0 && (
|
|
<div className="text-center py-12">
|
|
<p className="text-gray-500">No videos found. Add media libraries to scan for videos.</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default VideosPage;
|