import React, { useState } from 'react'; import { Archive, Download, Search, Calendar, HardDrive, FileArchive, AlertCircle, RotateCcw, Trash2, ChevronLeft, ChevronRight } from 'lucide-react'; import { format, parseISO, isValid } from 'date-fns'; import { toast } from 'react-toastify'; import { Button, Input, Card, Loading } from '../../components/common'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { archiveService } from '../../services/archive.service'; import { useTranslation } from 'react-i18next'; // import { useNavigate } from 'react-router-dom'; export const ArchivesPage: React.FC = () => { const { t } = useTranslation(); const [searchTerm, setSearchTerm] = useState(''); const [filterType, setFilterType] = useState('all'); const [sortBy, setSortBy] = useState<'date' | 'size' | 'name'>('date'); const [currentPage, setCurrentPage] = useState(1); // const navigate = useNavigate(); const queryClient = useQueryClient(); // Helper function to safely format dates const formatDate = (dateString: string | null | undefined, formatStr: string): string => { if (!dateString) return ''; try { const date = parseISO(dateString); return isValid(date) ? format(date, formatStr) : ''; } catch { return ''; } }; // Fetch archives from API const { data: archivesData, isLoading } = useQuery({ queryKey: ['admin-archives', currentPage], queryFn: () => archiveService.getArchives(currentPage, 20), }); const archives = archivesData?.archives || []; const filteredArchives = archives.filter(archive => { if (filterType !== 'all' && archive.eventType !== filterType) { return false; } if (searchTerm) { const term = searchTerm.toLowerCase(); return archive.eventName.toLowerCase().includes(term); } return true; }).sort((a, b) => { switch (sortBy) { case 'name': return a.eventName.localeCompare(b.eventName); case 'size': return b.archiveSize - a.archiveSize; case 'date': default: const dateA = a.archivedAt ? new Date(a.archivedAt).getTime() : 0; const dateB = b.archivedAt ? new Date(b.archivedAt).getTime() : 0; return dateB - dateA; } }); const getTotalSize = () => { return archives.reduce((sum, archive) => sum + archive.archiveSize, 0); }; // Mutations const restoreMutation = useMutation({ mutationFn: (id: number) => archiveService.restoreArchive(id), onSuccess: () => { toast.success(t('archives.restoreSuccess')); queryClient.invalidateQueries({ queryKey: ['admin-archives'] }); }, onError: () => { toast.error(t('errors.somethingWentWrong')); } }); const deleteMutation = useMutation({ mutationFn: (id: number) => archiveService.deleteArchive(id), onSuccess: () => { toast.success(t('archives.deleteSuccess')); queryClient.invalidateQueries({ queryKey: ['admin-archives'] }); }, onError: () => { toast.error(t('errors.somethingWentWrong')); } }); const handleDownload = async (archive: typeof archives[0]) => { try { toast.info(t('gallery.downloading', { count: 1 }).replace('photo', 'archive')); await archiveService.downloadArchive(archive.id, `${archive.slug}-archive.zip`); toast.success(t('common.download')); } catch (error) { toast.error(t('errors.somethingWentWrong')); } }; const handleRestore = (archive: typeof archives[0]) => { if (confirm(t('archives.confirmRestore').replace('{{name}}', archive.eventName))) { restoreMutation.mutate(archive.id); } }; const handleDelete = (archive: typeof archives[0]) => { if (confirm(t('archives.confirmDelete').replace('{{name}}', archive.eventName))) { deleteMutation.mutate(archive.id); } }; // Details view not implemented yet // const handleViewDetails = (archive: typeof archives[0]) => { // navigate(`/admin/archives/${archive.id}`); // }; if (isLoading) { return (
); } return (
{/* Page Header */}

{t('archives.title')}

{t('archives.subtitle')}

{/* Statistics Cards */}

{t('archives.totalArchives')}

{archives.length}

{t('archives.storageUsed')}

{archiveService.formatBytes(getTotalSize())}

{t('archives.totalPhotos')}

{(() => { const total = archives.reduce((sum, a) => sum + (parseInt(String(a.photoCount)) || 0), 0); return total === 0 ? '0' : total.toLocaleString(); })()}

{t('archives.avgArchiveSize')}

{archives.length > 0 ? archiveService.formatBytes(getTotalSize() / archives.length) : '0 Bytes' }

{/* Filters and Search */}
} value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} />
{/* Archives Table */}
{filteredArchives.length === 0 ? ( ) : ( filteredArchives.map((archive) => ( )) )}
{t('archives.tableHeaders.event')} {t('archives.tableHeaders.type')} {t('archives.tableHeaders.archivedDate')} {t('archives.tableHeaders.size')} {t('archives.tableHeaders.photos')} {t('archives.tableHeaders.actions')}
{t('archives.noArchivesFound')}

{archive.eventName}

{t('archives.eventDateNA').replace('N/A', formatDate(archive.eventDate, 'MMM d, yyyy') || 'N/A')}

{archive.eventType}

{formatDate(archive.archivedAt, 'MMM d, yyyy') || t('archives.processing')}

{formatDate(archive.archivedAt, 'h:mm a')}

{archiveService.formatBytes(archive.archiveSize)} {archive.photoCount}
{/* Details view not implemented yet */}
{/* Pagination */} {archivesData?.pagination && archivesData.pagination.totalPages > 1 && (
{t('archives.showing', { from: ((currentPage - 1) * archivesData.pagination.limit) + 1, to: Math.min(currentPage * archivesData.pagination.limit, archivesData.pagination.total), total: archivesData.pagination.total })}
{t('archives.page', { current: currentPage, total: archivesData.pagination.totalPages })}
)} {/* Storage Warning */}

{t('archives.storageManagement')}

{t('archives.storageInfo')}

); };