Files
checkcle/application/src/components/services/ServiceUptimeHistory.tsx
T

143 lines
4.9 KiB
TypeScript

import { useQuery } from "@tanstack/react-query";
import { UptimeData, Service } from "@/types/service.types";
import { uptimeService } from "@/services/uptimeService";
import { format, parseISO } from "date-fns";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Badge } from "@/components/ui/badge";
import { useTheme } from "@/contexts/ThemeContext";
import { Check, X, AlertTriangle, Pause } from "lucide-react";
interface ServiceUptimeHistoryProps {
serviceId: string;
serviceType: string; // Add service type to determine collection
startDate?: Date;
endDate?: Date;
}
export function ServiceUptimeHistory({
serviceId,
serviceType,
startDate = new Date(Date.now() - 24 * 60 * 60 * 1000),
endDate = new Date()
}: ServiceUptimeHistoryProps) {
const { theme } = useTheme();
const { data: uptimeHistory, isLoading, error } = useQuery({
queryKey: ['uptimeHistory', serviceId, serviceType, startDate?.toISOString(), endDate?.toISOString()],
queryFn: () => {
// console.log(`ServiceUptimeHistory: Fetching for service ${serviceId} of type ${serviceType}`);
return uptimeService.getUptimeHistory(serviceId, 200, startDate, endDate, serviceType);
},
enabled: !!serviceId && !!serviceType,
refetchInterval: 5000, // Refresh UI every 5 seconds
});
if (isLoading) {
return (
<div className="py-4 text-center">
<p>Loading uptime history...</p>
</div>
);
}
if (error) {
return (
<div className="py-4 text-center">
<p>Error loading uptime history.</p>
</div>
);
}
if (!uptimeHistory || uptimeHistory.length === 0) {
return (
<div className="py-4 text-center">
<p>No uptime history available for the selected time period.</p>
</div>
);
}
// Function to get appropriate status badge styling
const getStatusBadge = (status: string) => {
switch(status) {
case 'up':
return {
variant: 'default' as const,
className: 'bg-emerald-800 text-white hover:bg-emerald-700',
icon: <Check className="h-3 w-3 mr-1" />
};
case 'warning':
return {
variant: 'outline' as const,
className: 'bg-yellow-800/80 text-yellow-300 border-yellow-700 hover:bg-yellow-800',
icon: <AlertTriangle className="h-3 w-3 mr-1" />
};
case 'paused':
return {
variant: 'outline' as const,
className: 'bg-gray-800/50 text-gray-400 border-gray-700 hover:bg-gray-800',
icon: <Pause className="h-3 w-3 mr-1" />
};
default:
return {
variant: 'destructive' as const,
className: '',
icon: <X className="h-3 w-3 mr-1" />
};
}
};
return (
<div className="mt-4 bg-card rounded-lg overflow-hidden">
<Table>
<TableHeader>
<TableRow className="border-b border-border">
<TableHead className="text-muted-foreground font-medium">Time</TableHead>
<TableHead className="text-muted-foreground font-medium">Status</TableHead>
<TableHead className="text-muted-foreground font-medium">Response Time</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{uptimeHistory.map((record) => {
const statusBadge = getStatusBadge(record.status);
const isResponseTimeHigh = record.responseTime >= 1000;
return (
<TableRow key={record.id} className="border-b border-border">
<TableCell>
{format(parseISO(record.timestamp), 'yyyy-MM-dd HH:mm:ss')}
</TableCell>
<TableCell>
<Badge
variant={statusBadge.variant}
className={statusBadge.className}
>
<span className="flex items-center">
{statusBadge.icon}
{record.status === 'up' ? 'Up' :
record.status === 'down' ? 'Down' :
record.status === 'warning' ? 'Warning' : 'Paused'}
</span>
</Badge>
</TableCell>
<TableCell>
<div className="font-mono flex items-center gap-1.5">
{record.responseTime > 0 ? (
<>
<span className={isResponseTimeHigh ? "text-amber-500 font-semibold" : ""}>
{record.responseTime}ms
</span>
{isResponseTimeHigh && (
<AlertTriangle className="h-3 w-3 text-amber-500" />
)}
</>
) : 'N/A'}
</div>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</div>
);
}