mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 23:31:12 -05:00
126 lines
4.2 KiB
TypeScript
126 lines
4.2 KiB
TypeScript
/**
|
|
* Pipeline Health Alerts Component
|
|
*
|
|
* Displays critical pipeline alerts on the admin error monitoring dashboard.
|
|
* Shows top 10 active alerts with severity-based styling and resolution actions.
|
|
*/
|
|
|
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
|
import { useSystemAlerts } from '@/hooks/useSystemHealth';
|
|
import { Badge } from '@/components/ui/badge';
|
|
import { Button } from '@/components/ui/button';
|
|
import { AlertTriangle, CheckCircle, XCircle, AlertCircle } from 'lucide-react';
|
|
import { format } from 'date-fns';
|
|
import { supabase } from '@/lib/supabaseClient';
|
|
import { toast } from 'sonner';
|
|
|
|
const SEVERITY_CONFIG = {
|
|
critical: { color: 'destructive', icon: XCircle },
|
|
high: { color: 'destructive', icon: AlertCircle },
|
|
medium: { color: 'default', icon: AlertTriangle },
|
|
low: { color: 'secondary', icon: CheckCircle },
|
|
} as const;
|
|
|
|
const ALERT_TYPE_LABELS: Record<string, string> = {
|
|
failed_submissions: 'Failed Submissions',
|
|
high_ban_rate: 'High Ban Attempt Rate',
|
|
temp_ref_error: 'Temp Reference Error',
|
|
orphaned_images: 'Orphaned Images',
|
|
slow_approval: 'Slow Approvals',
|
|
submission_queue_backlog: 'Queue Backlog',
|
|
ban_attempt: 'Ban Attempt',
|
|
upload_timeout: 'Upload Timeout',
|
|
high_error_rate: 'High Error Rate',
|
|
validation_error: 'Validation Error',
|
|
stale_submissions: 'Stale Submissions',
|
|
circular_dependency: 'Circular Dependency',
|
|
rate_limit_violation: 'Rate Limit Violation',
|
|
};
|
|
|
|
export function PipelineHealthAlerts() {
|
|
const { data: criticalAlerts } = useSystemAlerts('critical');
|
|
const { data: highAlerts } = useSystemAlerts('high');
|
|
const { data: mediumAlerts } = useSystemAlerts('medium');
|
|
|
|
const allAlerts = [
|
|
...(criticalAlerts || []),
|
|
...(highAlerts || []),
|
|
...(mediumAlerts || [])
|
|
].slice(0, 10);
|
|
|
|
const resolveAlert = async (alertId: string) => {
|
|
const { error } = await supabase
|
|
.from('system_alerts')
|
|
.update({ resolved_at: new Date().toISOString() })
|
|
.eq('id', alertId);
|
|
|
|
if (error) {
|
|
toast.error('Failed to resolve alert');
|
|
} else {
|
|
toast.success('Alert resolved');
|
|
}
|
|
};
|
|
|
|
if (!allAlerts.length) {
|
|
return (
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<CheckCircle className="w-5 h-5 text-green-500" />
|
|
Pipeline Health: All Systems Operational
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<p className="text-sm text-muted-foreground">No active alerts. The sacred pipeline is flowing smoothly.</p>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>🚨 Active Pipeline Alerts</CardTitle>
|
|
<CardDescription>
|
|
Critical issues requiring attention ({allAlerts.length} active)
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent className="space-y-3">
|
|
{allAlerts.map((alert) => {
|
|
const config = SEVERITY_CONFIG[alert.severity];
|
|
const Icon = config.icon;
|
|
const label = ALERT_TYPE_LABELS[alert.alert_type] || alert.alert_type;
|
|
|
|
return (
|
|
<div
|
|
key={alert.id}
|
|
className="flex items-start justify-between p-3 border rounded-lg hover:bg-accent transition-colors"
|
|
>
|
|
<div className="flex items-start gap-3 flex-1">
|
|
<Icon className="w-5 h-5 mt-0.5 flex-shrink-0" />
|
|
<div className="flex-1 min-w-0">
|
|
<div className="flex items-center gap-2 mb-1">
|
|
<Badge variant={config.color as any}>{alert.severity.toUpperCase()}</Badge>
|
|
<span className="text-sm font-medium">{label}</span>
|
|
</div>
|
|
<p className="text-sm text-muted-foreground">{alert.message}</p>
|
|
<p className="text-xs text-muted-foreground mt-1">
|
|
{format(new Date(alert.created_at), 'PPp')}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<Button
|
|
variant="outline"
|
|
size="sm"
|
|
onClick={() => resolveAlert(alert.id)}
|
|
>
|
|
Resolve
|
|
</Button>
|
|
</div>
|
|
);
|
|
})}
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|