157 lines
4.7 KiB
TypeScript
157 lines
4.7 KiB
TypeScript
"use client";
|
|
|
|
import { Card, CardContent } from "@/components/ui/card";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Input } from "@/components/ui/input";
|
|
import { Badge } from "@/components/ui/badge";
|
|
import { Upload, Search, Filter, ImageIcon, Film, Music } from "lucide-react";
|
|
import { useState } from "react";
|
|
|
|
const stats = [
|
|
{ title: "Total Files", value: 24 },
|
|
{ title: "Images", value: 18 },
|
|
{ title: "Videos", value: 4 },
|
|
{ title: "Audio", value: 2 },
|
|
];
|
|
|
|
const files = [
|
|
{
|
|
name: "hero-banner.jpg",
|
|
type: "image",
|
|
size: "2.4 MB",
|
|
date: "2024-01-20",
|
|
},
|
|
{
|
|
name: "product-showcase.jpg",
|
|
type: "image",
|
|
size: "2.4 MB",
|
|
date: "2024-01-20",
|
|
},
|
|
{
|
|
name: "company-logo.svg",
|
|
type: "image",
|
|
size: "124 KB",
|
|
date: "2024-01-20",
|
|
},
|
|
{
|
|
name: "promo-video.mp4",
|
|
type: "video",
|
|
size: "2.4 MB",
|
|
date: "2024-01-20",
|
|
},
|
|
];
|
|
|
|
const getFileIcon = (type: string) => {
|
|
switch (type) {
|
|
case "video":
|
|
return <Film className="w-8 h-8 text-purple-500" />;
|
|
case "audio":
|
|
return <Music className="w-8 h-8 text-green-500" />;
|
|
default:
|
|
return <ImageIcon className="w-8 h-8 text-blue-500" />;
|
|
}
|
|
};
|
|
|
|
const getBadgeStyle = (type: string) => {
|
|
switch (type) {
|
|
case "video":
|
|
return "bg-purple-100 text-purple-600";
|
|
case "audio":
|
|
return "bg-green-100 text-green-600";
|
|
default:
|
|
return "bg-blue-100 text-blue-600";
|
|
}
|
|
};
|
|
|
|
export default function MediaLibrary() {
|
|
const [search, setSearch] = useState("");
|
|
|
|
return (
|
|
<div className="space-y-8">
|
|
{/* ================= HEADER ================= */}
|
|
<div>
|
|
<h1 className="text-2xl font-semibold">Media Library</h1>
|
|
<p className="text-sm text-muted-foreground">
|
|
Upload and manage images, videos, and documents
|
|
</p>
|
|
</div>
|
|
|
|
{/* ================= UPLOAD AREA ================= */}
|
|
<Card className="rounded-2xl overflow-hidden p-0">
|
|
<CardContent className="p-0">
|
|
<div className="bg-gradient-to-r from-blue-600 to-blue-700 text-white p-10 text-center space-y-4 rounded-2xl">
|
|
<Upload className="w-10 h-10 mx-auto" />
|
|
<h2 className="text-lg font-semibold">Upload Media Files</h2>
|
|
<p className="text-sm text-blue-100">
|
|
Drag and drop files here, or click to browse
|
|
</p>
|
|
|
|
<Button className="bg-white text-blue-600 hover:bg-blue-100">
|
|
Select Files
|
|
</Button>
|
|
|
|
<p className="text-xs text-blue-200">
|
|
Supports: JPG, PNG, SVG, PDF, MP4 (Max 50MB)
|
|
</p>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* ================= STATS ================= */}
|
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|
{stats.map((item, i) => (
|
|
<Card key={i} className="rounded-xl shadow-sm">
|
|
<CardContent className="p-5">
|
|
<p className="text-2xl font-semibold">{item.value}</p>
|
|
<p className="text-sm text-muted-foreground">{item.title}</p>
|
|
</CardContent>
|
|
</Card>
|
|
))}
|
|
</div>
|
|
|
|
{/* ================= SEARCH + FILTER ================= */}
|
|
<div className="flex flex-col md:flex-row gap-3 md:items-center md:justify-between">
|
|
<div className="relative w-full md:max-w-md">
|
|
<Search className="absolute left-3 top-3 w-4 h-4 text-muted-foreground" />
|
|
<Input
|
|
placeholder="Search media files..."
|
|
className="pl-9"
|
|
value={search}
|
|
onChange={(e) => setSearch(e.target.value)}
|
|
/>
|
|
</div>
|
|
|
|
<Button variant="outline" className="gap-2">
|
|
<Filter className="w-4 h-4" />
|
|
Filters
|
|
</Button>
|
|
</div>
|
|
|
|
{/* ================= FILE GRID ================= */}
|
|
<div className="grid sm:grid-cols-2 lg:grid-cols-4 gap-6">
|
|
{files.map((file, index) => (
|
|
<Card
|
|
key={index}
|
|
className="rounded-2xl overflow-hidden shadow-sm hover:shadow-md transition"
|
|
>
|
|
<div className="bg-slate-100 h-32 flex items-center justify-center">
|
|
{getFileIcon(file.type)}
|
|
</div>
|
|
|
|
<CardContent className="p-4 space-y-2">
|
|
<p className="text-sm font-medium truncate">{file.name}</p>
|
|
|
|
<div className="flex items-center justify-between text-xs text-muted-foreground">
|
|
<Badge className={getBadgeStyle(file.type)}>{file.type}</Badge>
|
|
<span>{file.size}</span>
|
|
</div>
|
|
|
|
<p className="text-xs text-muted-foreground">{file.date}</p>
|
|
</CardContent>
|
|
</Card>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|