mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-22 23:11:13 -05:00
Enhance alert resolution UX
Implement loading state, confirmation dialog, and related UI changes for resolving rate limit alerts: - Add resolvingAlertId state - Use ConfirmationDialog for safe resolution - Update Resolve button to ghost variant with CheckCircle icon and loading behavior - Wire up loading and disable states during mutation
This commit is contained in:
@@ -17,6 +17,7 @@ import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContaine
|
|||||||
import { Activity, Shield, TrendingUp, Users, Clock, AlertTriangle, Bell, BellOff, CheckCircle } from 'lucide-react';
|
import { Activity, Shield, TrendingUp, Users, Clock, AlertTriangle, Bell, BellOff, CheckCircle } from 'lucide-react';
|
||||||
import { Skeleton } from '@/components/ui/skeleton';
|
import { Skeleton } from '@/components/ui/skeleton';
|
||||||
import { Alert, AlertDescription } from '@/components/ui/alert';
|
import { Alert, AlertDescription } from '@/components/ui/alert';
|
||||||
|
import { ConfirmationDialog } from '@/components/moderation/ConfirmationDialog';
|
||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
|
|
||||||
const COLORS = ['hsl(var(--primary))', 'hsl(var(--secondary))', 'hsl(var(--accent))', 'hsl(var(--muted))', 'hsl(var(--destructive))'];
|
const COLORS = ['hsl(var(--primary))', 'hsl(var(--secondary))', 'hsl(var(--accent))', 'hsl(var(--muted))', 'hsl(var(--destructive))'];
|
||||||
@@ -27,6 +28,7 @@ export default function RateLimitMetrics() {
|
|||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
const { isModerator, loading: rolesLoading } = useUserRole();
|
const { isModerator, loading: rolesLoading } = useUserRole();
|
||||||
const [timeWindow, setTimeWindow] = useState(60000); // 1 minute default
|
const [timeWindow, setTimeWindow] = useState(60000); // 1 minute default
|
||||||
|
const [resolvingAlertId, setResolvingAlertId] = useState<string | null>(null);
|
||||||
|
|
||||||
const { data: stats, isLoading: statsLoading, error: statsError } = useRateLimitStats(timeWindow);
|
const { data: stats, isLoading: statsLoading, error: statsError } = useRateLimitStats(timeWindow);
|
||||||
const { data: recentData, isLoading: recentLoading } = useRecentMetrics(50);
|
const { data: recentData, isLoading: recentLoading } = useRecentMetrics(50);
|
||||||
@@ -401,9 +403,13 @@ export default function RateLimitMetrics() {
|
|||||||
{!alert.resolved_at && (
|
{!alert.resolved_at && (
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="outline"
|
variant="ghost"
|
||||||
onClick={() => resolveAlert.mutate(alert.id)}
|
onClick={() => setResolvingAlertId(alert.id)}
|
||||||
|
loading={resolveAlert.isPending && resolvingAlertId === alert.id}
|
||||||
|
disabled={resolveAlert.isPending}
|
||||||
|
className="gap-2"
|
||||||
>
|
>
|
||||||
|
<CheckCircle className="h-4 w-4" />
|
||||||
Resolve
|
Resolve
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
@@ -417,6 +423,20 @@ export default function RateLimitMetrics() {
|
|||||||
)}
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
<ConfirmationDialog
|
||||||
|
open={resolvingAlertId !== null}
|
||||||
|
onOpenChange={(open) => !open && setResolvingAlertId(null)}
|
||||||
|
title="Resolve Alert"
|
||||||
|
description="Are you sure you want to mark this alert as resolved? This action cannot be undone."
|
||||||
|
confirmLabel="Resolve"
|
||||||
|
onConfirm={() => {
|
||||||
|
if (resolvingAlertId) {
|
||||||
|
resolveAlert.mutate(resolvingAlertId);
|
||||||
|
setResolvingAlertId(null);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
<TabsContent value="config" className="space-y-6">
|
<TabsContent value="config" className="space-y-6">
|
||||||
|
|||||||
Reference in New Issue
Block a user