import { DataTable } from '@/components/admin/DataTable.tsx'; import { Badge, Button } from '@/components/ui'; import { useMediaAssets, useDeleteMediaAsset } from '@/hooks/api/useAdminAPI.ts'; import { useTranslation } from '@/hooks/useI18n.tsx'; import type { MediaAsset } from '@/services/admin-api.ts'; import { Edit, Plus, Trash2, Image as ImageIcon } from 'lucide-react'; import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; const MediaLibraryPage = () => { const { t } = useTranslation(); const navigate = useNavigate(); const [currentPage, setCurrentPage] = useState(1); const pageSize = 25; const [typeFilter, setTypeFilter] = useState(); const { data, isLoading } = useMediaAssets({ type: typeFilter }); const { mutate: deleteAsset } = useDeleteMediaAsset(); const handleDelete = (asset: MediaAsset) => { if (window.confirm(t('adminPage.content.media.confirmDelete') || 'Delete this media asset?')) { deleteAsset(asset.id, { onSuccess: () => { // Query will refetch automatically }, }); } }; const formatFileSize = (bytes: number): string => { 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 Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i]; }; const getTypeBadge = (type: string) => { if (type.startsWith('image/')) { return {t('adminPage.content.media.type') || 'Image'}; } if (type.startsWith('video/')) { return {t('adminPage.content.media.type') || 'Video'}; } return {type}; }; const columns = [ { key: 'thumbnail', header: t('adminPage.content.media.table.thumbnail') || 'Thumbnail', render: (asset: MediaAsset) => (
{asset.type?.startsWith('image/') ? ( {asset.altText ) : (
)}
), }, { key: 'name', header: t('adminPage.content.media.table.name') || 'Name', render: (asset: MediaAsset) => {asset.name}, }, { key: 'type', header: t('adminPage.content.media.table.type') || 'Type', render: (asset: MediaAsset) => getTypeBadge(asset.type || 'unknown'), }, { key: 'size', header: t('adminPage.content.media.table.size') || 'Size', render: (asset: MediaAsset) => ( {formatFileSize(asset.size || 0)} ), }, { key: 'uploadedAt', header: t('adminPage.content.media.table.uploaded') || 'Uploaded', render: (asset: MediaAsset) => { try { const date = new Date(asset.uploadedAt || asset.createdAt); return {date.toLocaleDateString()}; } catch { return ; } }, }, ]; const actions = [ { label: t('adminPage.content.media.edit') || 'Edit', icon: , onClick: (asset: MediaAsset) => navigate(`/admin/content/media/${asset.id}/edit`), }, { label: t('adminPage.content.media.delete') || 'Delete', icon: , variant: 'destructive' as const, onClick: (asset: MediaAsset) => handleDelete(asset), }, ]; const assets = data?.assets || []; return (
{/* Header */}

{t('adminPage.content.media.title') || 'Media Library'}

{t('adminPage.content.media.description') || 'Manage uploaded media assets, images, and files'}

{/* Filters */}
{/* Table */} asset.id} isLoading={isLoading} actions={actions} pagination={ assets.length > 0 ? { currentPage, totalPages: Math.ceil(assets.length / pageSize), pageSize, totalItems: assets.length, onPageChange: setCurrentPage, } : undefined } emptyMessage={t('adminPage.content.media.noAssets') || 'No media assets found'} emptyDescription={ t('adminPage.content.media.createFirst') || 'Upload your first media asset to get started' } emptyAction={ } />
); }; export default MediaLibraryPage;