Files
eve-signaler/src/components/SystemTracker.tsx
2025-06-16 17:06:42 +02:00

135 lines
4.7 KiB
TypeScript

import { useQuery } from "@tanstack/react-query";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { RefreshCw, AlertCircle, Radar } from "lucide-react";
import { SignatureCategories } from "@/components/SignatureCategories";
import { useSignatureCategories } from "@/hooks/useSignatureCategories";
import { toast } from "@/hooks/use-toast";
import { CleanModeToggle } from "@/components/CleanModeToggle";
import pb from "@/lib/pocketbase";
interface SystemTrackerProps {
system: string;
cleanMode: boolean;
onCleanModeToggle: (enabled: boolean) => void;
}
export const SystemTracker = ({ system, cleanMode, onCleanModeToggle }: SystemTrackerProps) => {
const {
data: signaturesData,
refetch: refetchSignatures,
isLoading: signaturesLoading,
error: signaturesError
} = useQuery({
queryKey: ['signatures', system],
queryFn: async () => {
if (!system) return null;
return pb.collection('sigview').getFullList({ batch: 1000, filter: `(system='${system}')` });
},
enabled: !!system,
refetchInterval: 5000, // Poll every 5 seconds
});
const handleRefresh = () => {
refetchSignatures();
toast({
title: "Refreshing Data",
description: "Updating signature information...",
});
};
const signatures = signaturesData || [];
const isLoading = signaturesLoading;
// Sort signatures by date (newest first) and prioritize unknown types
const sortedSignatures = [...signatures].sort((a, b) => {
// First, prioritize unknown types
const aIsUnknown = !a.type || a.type === '';
const bIsUnknown = !b.type || b.type === '';
if (aIsUnknown && !bIsUnknown) return -1;
if (!aIsUnknown && bIsUnknown) return 1;
// If both are unknown or both are known, sort by type
if (a.type !== b.type) {
return a.type.localeCompare(b.type);
}
// If same type, sort by date
const dateA = a.updated || a.created || '';
const dateB = b.updated || b.created || '';
return dateB.localeCompare(dateA);
});
const { categories, toggleCategoryVisibility } = useSignatureCategories(sortedSignatures);
return (
<div className="space-y-6">
{/* System Status Card */}
<Card className="bg-slate-800/50 border-slate-700">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-4">
<CardTitle className="text-xl text-white flex items-center gap-2">
<Radar className="h-5 w-5 text-blue-400" />
{system}
<Badge variant="outline" className="ml-2 bg-blue-900/20 text-blue-400 border-blue-600">
Polling
</Badge>
</CardTitle>
<div className="flex items-center gap-2">
<CleanModeToggle cleanMode={cleanMode} onToggle={onCleanModeToggle} />
<Badge variant="outline" className="bg-slate-700/50 text-slate-300 border-slate-600">
Total: {signatures.length}
</Badge>
<Button
onClick={handleRefresh}
disabled={isLoading}
variant="ghost"
size="icon"
className="h-6 w-6 text-slate-400 hover:text-slate-200 hover:bg-slate-700/50"
>
<RefreshCw className={`h-3 w-3 ${isLoading ? 'animate-spin' : ''}`} />
</Button>
</div>
</CardHeader>
</Card>
{/* Error Display */}
{signaturesError && (
<Card className="bg-red-900/20 border-red-700">
<CardContent className="pt-6">
<div className="flex items-center gap-2 text-red-400">
<AlertCircle className="h-5 w-5" />
<span>Error loading signatures: {signaturesError.message}</span>
</div>
</CardContent>
</Card>
)}
{/* Loading State */}
{signaturesLoading && system && (
<Card className="bg-slate-800/30 border-slate-700">
<CardContent className="pt-6">
<div className="space-y-4">
{[...Array(6)].map((_, i) => (
<div key={i} className="flex items-center gap-4 p-4 animate-pulse">
<div className="h-6 bg-slate-700 rounded w-24"></div>
<div className="h-4 bg-slate-600 rounded flex-1"></div>
<div className="h-4 bg-slate-700 rounded w-16"></div>
</div>
))}
</div>
</CardContent>
</Card>
)}
{/* Signature Categories */}
{system && !signaturesLoading && (
<SignatureCategories
categories={categories}
onToggleCategory={toggleCategoryVisibility}
/>
)}
</div>
);
};