79 lines
2.3 KiB
TypeScript
79 lines
2.3 KiB
TypeScript
|
|
'use client';
|
||
|
|
|
||
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||
|
|
import { Badge } from '@/components/ui/badge';
|
||
|
|
import { HardDrive, ShieldAlert, CheckCircle, XCircle, AlertTriangle } from 'lucide-react';
|
||
|
|
|
||
|
|
interface BackupSummaryCardsProps {
|
||
|
|
totalProtectedWorkloads: number;
|
||
|
|
successRate24h: number;
|
||
|
|
failedJobs24h: number;
|
||
|
|
warningJobs24h: number;
|
||
|
|
totalBackupServerJobs: number;
|
||
|
|
totalBackupAgentJobs: number;
|
||
|
|
lastSyncAt: string | null;
|
||
|
|
}
|
||
|
|
|
||
|
|
export function BackupSummaryCards({
|
||
|
|
totalProtectedWorkloads,
|
||
|
|
successRate24h,
|
||
|
|
failedJobs24h,
|
||
|
|
warningJobs24h,
|
||
|
|
totalBackupServerJobs,
|
||
|
|
totalBackupAgentJobs,
|
||
|
|
lastSyncAt,
|
||
|
|
}: BackupSummaryCardsProps) {
|
||
|
|
const cards = [
|
||
|
|
{
|
||
|
|
title: 'Protected Workloads',
|
||
|
|
value: totalProtectedWorkloads,
|
||
|
|
icon: HardDrive,
|
||
|
|
color: 'text-blue-500',
|
||
|
|
},
|
||
|
|
{
|
||
|
|
title: 'Total Jobs',
|
||
|
|
value: totalBackupServerJobs + totalBackupAgentJobs,
|
||
|
|
icon: CheckCircle,
|
||
|
|
color: 'text-green-500',
|
||
|
|
subtitle: `${totalBackupServerJobs} server / ${totalBackupAgentJobs} agent`,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
title: '24h Success Rate',
|
||
|
|
value: `${successRate24h}%`,
|
||
|
|
icon: successRate24h >= 95 ? CheckCircle : AlertTriangle,
|
||
|
|
color: successRate24h >= 95 ? 'text-green-500' : successRate24h >= 80 ? 'text-yellow-500' : 'text-red-500',
|
||
|
|
},
|
||
|
|
{
|
||
|
|
title: 'Failed Jobs (24h)',
|
||
|
|
value: failedJobs24h,
|
||
|
|
icon: XCircle,
|
||
|
|
color: failedJobs24h > 0 ? 'text-red-500' : 'text-green-500',
|
||
|
|
},
|
||
|
|
{
|
||
|
|
title: 'Warnings (24h)',
|
||
|
|
value: warningJobs24h,
|
||
|
|
icon: AlertTriangle,
|
||
|
|
color: warningJobs24h > 0 ? 'text-yellow-500' : 'text-green-500',
|
||
|
|
},
|
||
|
|
];
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="grid gap-4 md:grid-cols-3 lg:grid-cols-5">
|
||
|
|
{cards.map((card) => (
|
||
|
|
<Card key={card.title}>
|
||
|
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||
|
|
<CardTitle className="text-sm font-medium">{card.title}</CardTitle>
|
||
|
|
<card.icon className={`h-4 w-4 ${card.color}`} />
|
||
|
|
</CardHeader>
|
||
|
|
<CardContent>
|
||
|
|
<div className="text-2xl font-bold">{card.value}</div>
|
||
|
|
{card.subtitle && (
|
||
|
|
<p className="text-xs text-muted-foreground mt-1">{card.subtitle}</p>
|
||
|
|
)}
|
||
|
|
</CardContent>
|
||
|
|
</Card>
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|