import React from 'react';
import {
HardDrive,
Database,
FileArchive,
Image,
Clock,
CheckCircle,
AlertCircle,
TrendingUp,
Shield,
Server,
Cloud,
Calendar,
Play,
Loader2,
AlertTriangle,
Info
} from 'lucide-react';
import { format, formatDistanceToNow } from 'date-fns';
import { Card, Button } from '../common';
const StatCard = ({ icon: Icon, label, value, color = 'blue', subtext }) => (
{label}
{value}
{subtext && (
{subtext}
)}
);
const formatBytes = (bytes) => {
if (!bytes) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
};
export const BackupDashboard = ({ status, config, onRunBackup, isBackupRunning }) => {
const lastBackup = status?.lastBackup;
const statistics = lastBackup?.statistics || {};
const isConfigured = config && config.backup_destination_type;
const isEnabled = config?.backup_enabled;
// Calculate backup health score
const getHealthScore = () => {
if (!lastBackup) return { score: 0, status: 'critical', message: 'No backups found' };
const hoursSinceBackup = (Date.now() - new Date(lastBackup.created_at)) / (1000 * 60 * 60);
if (lastBackup.status === 'failed') {
return { score: 0, status: 'critical', message: 'Last backup failed' };
}
if (hoursSinceBackup < 24) {
return { score: 100, status: 'excellent', message: 'Backup is up to date' };
} else if (hoursSinceBackup < 48) {
return { score: 75, status: 'good', message: 'Backup is recent' };
} else if (hoursSinceBackup < 168) { // 1 week
return { score: 50, status: 'warning', message: 'Backup is getting old' };
} else {
return { score: 25, status: 'critical', message: 'Backup is outdated' };
}
};
const health = getHealthScore();
const healthColors = {
excellent: 'green',
good: 'blue',
warning: 'amber',
critical: 'red'
};
return (
{/* Configuration Alert */}
{!isConfigured && (
Backup Not Configured
Please configure backup settings in the Configuration tab before running backups.
)}
{/* Health Score Card */}
Backup Health
{health.status.charAt(0).toUpperCase() + health.status.slice(1)}
{health.message}
{lastBackup && (
Last successful backup: {formatDistanceToNow(new Date(lastBackup.created_at), { addSuffix: true })}
)}
{/* Statistics Grid */}
{/* Recent Activity */}
{status?.recentBackups && status.recentBackups.length > 0 && (
Recent Backup Activity
{status.recentBackups.slice(0, 5).map((backup) => (
{backup.status === 'completed' ? (
) : backup.status === 'failed' ? (
) : (
)}
{backup.backup_type} backup
{format(new Date(backup.created_at), 'PPp')}
{formatBytes(backup.statistics?.total_size || 0)}
{backup.statistics?.files_processed || 0} files
))}
)}
{/* Storage Status */}
Backup Coverage
Database
{statistics.database_backed_up ? 'Backed up' : 'Not backed up'}
Photos
{statistics.photos_backed_up || 0} of {statistics.total_photos || 0}
Archives
{statistics.archives_backed_up || 0} files
Destination Info
{config?.backup_destination_type === 's3' ? (
) : config?.backup_destination_type === 'rsync' ? (
) : (
)}
{config?.backup_destination_type
? config.backup_destination_type.toUpperCase()
: 'Not Configured'}
{config?.backup_destination_type === 's3' && config?.backup_s3_bucket
? `Bucket: ${config.backup_s3_bucket}`
: config?.backup_destination_type === 'local' && config?.backup_destination_path
? `Path: ${config.backup_destination_path}`
: config?.backup_destination_type === 'rsync' && config?.backup_rsync_host
? `Host: ${config.backup_rsync_host}`
: 'No destination set'}
{config?.backup_retention_days && (
Backups retained for {config.backup_retention_days} days
)}
);
};