mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-23 03:11:12 -05:00
Implement monitoring and alert-resolve UI improvements: - Enhance useAlertGroupActions with robust error handling and breadcrumb logging - Add loading state visuals to GroupedAlertsPanel and Resolve All button - Integrate loading indicator (Loader2) for better user feedback during resolves
143 lines
4.3 KiB
TypeScript
143 lines
4.3 KiB
TypeScript
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
import { supabase } from '@/lib/supabaseClient';
|
|
import { queryKeys } from '@/lib/queryKeys';
|
|
import { toast } from 'sonner';
|
|
import { breadcrumb } from '@/lib/errorBreadcrumbs';
|
|
import type { GroupedAlert } from './useGroupedAlerts';
|
|
|
|
export function useResolveAlertGroup() {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: async ({
|
|
alertIds,
|
|
source
|
|
}: {
|
|
alertIds: string[];
|
|
source: 'system' | 'rate_limit';
|
|
}) => {
|
|
const table = source === 'system' ? 'system_alerts' : 'rate_limit_alerts';
|
|
|
|
// Log breadcrumb for debugging
|
|
breadcrumb.userAction(`resolve-alerts`, 'AlertGroupActions', {
|
|
alertIds,
|
|
source,
|
|
count: alertIds.length,
|
|
});
|
|
|
|
const { data, error } = await supabase
|
|
.from(table)
|
|
.update({ resolved_at: new Date().toISOString() })
|
|
.in('id', alertIds)
|
|
.select();
|
|
|
|
if (error) {
|
|
// Enhanced error handling with specific messages
|
|
if (error.code === '42501') {
|
|
throw new Error('Permission denied. You do not have access to resolve these alerts.');
|
|
} else if (error.code === 'PGRST116') {
|
|
throw new Error('No alerts found to resolve. They may have already been resolved.');
|
|
} else {
|
|
console.error('Supabase error details:', error);
|
|
throw new Error(`Failed to resolve alerts: ${error.message}`);
|
|
}
|
|
}
|
|
|
|
return { count: alertIds.length, updatedAlerts: data };
|
|
},
|
|
onMutate: async ({ alertIds }) => {
|
|
// Cancel any outgoing refetches
|
|
await queryClient.cancelQueries({
|
|
queryKey: queryKeys.monitoring.groupedAlerts()
|
|
});
|
|
|
|
const previousData = queryClient.getQueryData(
|
|
queryKeys.monitoring.groupedAlerts()
|
|
);
|
|
|
|
// Optimistically update to the new value
|
|
queryClient.setQueryData(
|
|
queryKeys.monitoring.groupedAlerts(),
|
|
(old: GroupedAlert[] | undefined) => {
|
|
if (!old) return old;
|
|
return old.map(alert => {
|
|
const hasMatchingIds = alert.alert_ids.some(id =>
|
|
alertIds.includes(id)
|
|
);
|
|
if (hasMatchingIds) {
|
|
return {
|
|
...alert,
|
|
unresolved_count: 0,
|
|
has_resolved: true,
|
|
};
|
|
}
|
|
return alert;
|
|
});
|
|
}
|
|
);
|
|
|
|
return { previousData };
|
|
},
|
|
onSuccess: (data) => {
|
|
toast.success(`Resolved ${data.count} alert${data.count > 1 ? 's' : ''}`);
|
|
},
|
|
onError: (error: Error, variables, context) => {
|
|
// Rollback on error
|
|
if (context?.previousData) {
|
|
queryClient.setQueryData(
|
|
queryKeys.monitoring.groupedAlerts(),
|
|
context.previousData
|
|
);
|
|
}
|
|
|
|
// Show detailed error message
|
|
toast.error(error.message || 'Failed to resolve alerts', {
|
|
description: 'Please try again or contact support if the issue persists.',
|
|
duration: 5000,
|
|
});
|
|
|
|
// Log to error tracking system
|
|
breadcrumb.apiCall('resolve-alerts', 'POST', 500);
|
|
console.error('Error resolving alert group:', error, {
|
|
alertIds: variables.alertIds,
|
|
source: variables.source,
|
|
});
|
|
},
|
|
onSettled: () => {
|
|
queryClient.invalidateQueries({
|
|
queryKey: queryKeys.monitoring.groupedAlerts()
|
|
});
|
|
queryClient.invalidateQueries({
|
|
queryKey: queryKeys.monitoring.combinedAlerts()
|
|
});
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useSnoozeAlertGroup() {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: async ({
|
|
groupKey,
|
|
duration
|
|
}: {
|
|
groupKey: string;
|
|
duration: number;
|
|
}) => {
|
|
const snoozedAlerts = JSON.parse(
|
|
localStorage.getItem('snoozed_alerts') || '{}'
|
|
);
|
|
snoozedAlerts[groupKey] = Date.now() + duration;
|
|
localStorage.setItem('snoozed_alerts', JSON.stringify(snoozedAlerts));
|
|
return { groupKey, until: snoozedAlerts[groupKey] };
|
|
},
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({
|
|
queryKey: queryKeys.monitoring.groupedAlerts()
|
|
});
|
|
toast.success('Alert group snoozed');
|
|
},
|
|
});
|
|
}
|