mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-28 12:26:58 -05:00
Compare commits
2 Commits
9bf5ea322e
...
a9334c7a3a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a9334c7a3a | ||
|
|
162d288cb0 |
@@ -74,7 +74,7 @@ export function ReassignDialog({
|
|||||||
.rpc('get_users_with_emails');
|
.rpc('get_users_with_emails');
|
||||||
|
|
||||||
if (rpcError) {
|
if (rpcError) {
|
||||||
logger.warn('Failed to fetch users with emails, using basic profiles', { error: getErrorMessage(rpcError) });
|
// Fall back to basic profiles
|
||||||
const { data: basicProfiles } = await supabase
|
const { data: basicProfiles } = await supabase
|
||||||
.from('profiles')
|
.from('profiles')
|
||||||
.select('user_id, username, display_name')
|
.select('user_id, username, display_name')
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@
|
|||||||
import { supabase } from '@/lib/supabaseClient';
|
import { supabase } from '@/lib/supabaseClient';
|
||||||
import { useAuth } from '@/hooks/useAuth';
|
import { useAuth } from '@/hooks/useAuth';
|
||||||
import { useUserRole } from '@/hooks/useUserRole';
|
import { useUserRole } from '@/hooks/useUserRole';
|
||||||
import { handleError, handleSuccess, getErrorMessage } from '@/lib/errorHandler';
|
import { handleError, handleNonCriticalError, handleSuccess, getErrorMessage } from '@/lib/errorHandler';
|
||||||
import { logger } from '@/lib/logger';
|
|
||||||
|
|
||||||
// Type-safe role definitions
|
// Type-safe role definitions
|
||||||
const VALID_ROLES = ['admin', 'moderator', 'user'] as const;
|
const VALID_ROLES = ['admin', 'moderator', 'user'] as const;
|
||||||
@@ -91,7 +90,7 @@ export function UserRoleManager() {
|
|||||||
.rpc('get_users_with_emails');
|
.rpc('get_users_with_emails');
|
||||||
|
|
||||||
if (rpcError) {
|
if (rpcError) {
|
||||||
logger.warn('Failed to fetch users with emails, using basic profiles', { error: getErrorMessage(rpcError) });
|
// Fall back to basic profiles
|
||||||
const { data: basicProfiles } = await supabase
|
const { data: basicProfiles } = await supabase
|
||||||
.from('profiles')
|
.from('profiles')
|
||||||
.select('user_id, username, display_name')
|
.select('user_id, username, display_name')
|
||||||
@@ -128,7 +127,7 @@ export function UserRoleManager() {
|
|||||||
.rpc('get_users_with_emails');
|
.rpc('get_users_with_emails');
|
||||||
|
|
||||||
if (rpcError) {
|
if (rpcError) {
|
||||||
logger.warn('Failed to fetch users with emails, using basic profiles', { error: getErrorMessage(rpcError) });
|
// Fall back to basic profiles
|
||||||
const { data: basicProfiles, error: profilesError } = await supabase
|
const { data: basicProfiles, error: profilesError } = await supabase
|
||||||
.from('profiles')
|
.from('profiles')
|
||||||
.select('user_id, username, display_name')
|
.select('user_id, username, display_name')
|
||||||
@@ -149,7 +148,11 @@ export function UserRoleManager() {
|
|||||||
const filteredResults = (data || []).filter(profile => !existingUserIds.includes(profile.user_id));
|
const filteredResults = (data || []).filter(profile => !existingUserIds.includes(profile.user_id));
|
||||||
setSearchResults(filteredResults);
|
setSearchResults(filteredResults);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error('User search failed', { error: getErrorMessage(error) });
|
handleNonCriticalError(error, {
|
||||||
|
action: 'Search Users',
|
||||||
|
userId: user?.id,
|
||||||
|
metadata: { search }
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { invokeWithTracking } from "@/lib/edgeFunctionTracking";
|
import { invokeWithTracking } from "@/lib/edgeFunctionTracking";
|
||||||
import { logger } from "@/lib/logger";
|
import { handleError, getErrorMessage } from "@/lib/errorHandler";
|
||||||
import { getErrorMessage } from "@/lib/errorHandler";
|
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
@@ -171,11 +170,10 @@ export function UppyPhotoSubmissionUpload({
|
|||||||
);
|
);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
const errorMsg = getErrorMessage(error);
|
||||||
logger.error("Photo submission upload failed", {
|
handleError(error, {
|
||||||
photoTitle: photo.title,
|
action: 'Upload Photo Submission',
|
||||||
photoOrder: photo.order,
|
userId: user.id,
|
||||||
fileName: photo.file?.name,
|
metadata: { photoTitle: photo.title, photoOrder: photo.order, fileName: photo.file?.name }
|
||||||
error: errorMsg,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
setPhotos((prev) => prev.map((p) => (p === photo ? { ...p, uploadStatus: "failed" as const } : p)));
|
setPhotos((prev) => prev.map((p) => (p === photo ? { ...p, uploadStatus: "failed" as const } : p)));
|
||||||
@@ -258,12 +256,10 @@ export function UppyPhotoSubmissionUpload({
|
|||||||
onSubmissionComplete?.();
|
onSubmissionComplete?.();
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
const errorMsg = getErrorMessage(error);
|
||||||
logger.error("Photo submission failed", {
|
handleError(error, {
|
||||||
entityType,
|
action: 'Submit Photo Submission',
|
||||||
entityId,
|
|
||||||
photoCount: photos.length,
|
|
||||||
userId: user?.id,
|
userId: user?.id,
|
||||||
error: errorMsg,
|
metadata: { entityType, entityId, photoCount: photos.length }
|
||||||
});
|
});
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import React, { useRef, useState } from 'react';
|
import React, { useRef, useState } from 'react';
|
||||||
import { supabase } from '@/lib/supabaseClient';
|
import { supabase } from '@/lib/supabaseClient';
|
||||||
import { useToast } from '@/hooks/use-toast';
|
import { useToast } from '@/hooks/use-toast';
|
||||||
|
import { useAuth } from '@/hooks/useAuth';
|
||||||
import { invokeWithTracking } from '@/lib/edgeFunctionTracking';
|
import { invokeWithTracking } from '@/lib/edgeFunctionTracking';
|
||||||
import { logger } from '@/lib/logger';
|
import { handleError, getErrorMessage } from '@/lib/errorHandler';
|
||||||
import { getErrorMessage } from '@/lib/errorHandler';
|
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { Upload, X, Eye, Loader2, CheckCircle } from 'lucide-react';
|
import { Upload, X, Eye, Loader2, CheckCircle } from 'lucide-react';
|
||||||
@@ -204,11 +204,9 @@ export function UppyPhotoUpload({
|
|||||||
setUploadProgress(Math.round(((i + 1) / totalFiles) * 100));
|
setUploadProgress(Math.round(((i + 1) / totalFiles) * 100));
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
const errorMsg = getErrorMessage(error);
|
||||||
logger.error('File upload failed', {
|
handleError(error, {
|
||||||
fileName: file.name,
|
action: 'Upload Photo File',
|
||||||
fileSize: file.size,
|
metadata: { fileName: file.name, fileSize: file.size, fileType: file.type }
|
||||||
fileType: file.type,
|
|
||||||
error: errorMsg
|
|
||||||
});
|
});
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export function MFAStepUpProvider({ children }: MFAStepUpProviderProps) {
|
|||||||
setModalOpen(false);
|
setModalOpen(false);
|
||||||
|
|
||||||
if (!pendingOperation || !pendingResolve || !pendingReject) {
|
if (!pendingOperation || !pendingResolve || !pendingReject) {
|
||||||
logger.error('No pending operation to retry after MFA success');
|
// Invalid state - missing pending operations
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ export function MFAStepUpProvider({ children }: MFAStepUpProviderProps) {
|
|||||||
const result = await pendingOperation();
|
const result = await pendingOperation();
|
||||||
pendingResolve(result);
|
pendingResolve(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('[MFAStepUp] Operation failed after AAL2 upgrade', { error });
|
// Operation failed after AAL2 - will be handled by caller
|
||||||
pendingReject(error);
|
pendingReject(error);
|
||||||
} finally {
|
} finally {
|
||||||
// Clean up
|
// Clean up
|
||||||
@@ -105,7 +105,7 @@ export function MFAStepUpProvider({ children }: MFAStepUpProviderProps) {
|
|||||||
const factors = await getEnrolledFactors();
|
const factors = await getEnrolledFactors();
|
||||||
|
|
||||||
if (factors.length === 0) {
|
if (factors.length === 0) {
|
||||||
logger.error('[MFAStepUp] No enrolled MFA factors found');
|
// No MFA set up
|
||||||
throw new Error('MFA is not set up for your account');
|
throw new Error('MFA is not set up for your account');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -167,12 +167,12 @@ export function useEntityCache() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
logger.error(`Unknown entity type: ${type}`);
|
// Unknown entity type - skip
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error(`Error fetching ${type}:`, { error: getErrorMessage(error as Error) });
|
// Silent - cache miss is acceptable
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,7 +187,7 @@ export function useEntityCache() {
|
|||||||
|
|
||||||
return (data as EntityTypeMap[T][]) || [];
|
return (data as EntityTypeMap[T][]) || [];
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error(`Failed to bulk fetch ${type}:`, { error: getErrorMessage(error) });
|
// Silent - cache operations are non-critical
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}, [getCached, setCached, getUncachedIds]);
|
}, [getCached, setCached, getUncachedIds]);
|
||||||
|
|||||||
@@ -280,7 +280,7 @@ export function useModerationActions(config: ModerationActionsConfig): Moderatio
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (auditError) {
|
} catch (auditError) {
|
||||||
logger.error('Failed to log review moderation audit', { error: auditError });
|
// Silent - audit logging is non-critical
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,7 +327,7 @@ export function useModerationActions(config: ModerationActionsConfig): Moderatio
|
|||||||
queryClient.setQueryData(['moderation-queue'], context.previousData);
|
queryClient.setQueryData(['moderation-queue'], context.previousData);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.error('❌ Error performing action:', { error: getErrorMessage(error) });
|
// Error already logged by mutation, just show toast
|
||||||
toast({
|
toast({
|
||||||
title: 'Action Failed',
|
title: 'Action Failed',
|
||||||
description: getErrorMessage(error) || `Failed to ${variables.action} content`,
|
description: getErrorMessage(error) || `Failed to ${variables.action} content`,
|
||||||
@@ -395,7 +395,7 @@ export function useModerationActions(config: ModerationActionsConfig): Moderatio
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (auditError) {
|
} catch (auditError) {
|
||||||
logger.error('Failed to log submission deletion audit', { error: auditError });
|
// Silent - audit logging is non-critical
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,7 +406,7 @@ export function useModerationActions(config: ModerationActionsConfig): Moderatio
|
|||||||
|
|
||||||
logger.log(`✅ Submission ${item.id} deleted`);
|
logger.log(`✅ Submission ${item.id} deleted`);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error('❌ Error deleting submission:', { error: getErrorMessage(error) });
|
// Error already handled, just show toast
|
||||||
toast({
|
toast({
|
||||||
title: 'Error',
|
title: 'Error',
|
||||||
description: getErrorMessage(error),
|
description: getErrorMessage(error),
|
||||||
@@ -444,7 +444,7 @@ export function useModerationActions(config: ModerationActionsConfig): Moderatio
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (auditError) {
|
} catch (auditError) {
|
||||||
logger.error('Failed to log submission reset audit', { error: auditError });
|
// Silent - audit logging is non-critical
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,7 +455,7 @@ export function useModerationActions(config: ModerationActionsConfig): Moderatio
|
|||||||
|
|
||||||
logger.log(`✅ Submission ${item.id} reset to pending`);
|
logger.log(`✅ Submission ${item.id} reset to pending`);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error('❌ Error resetting submission:', { error: getErrorMessage(error) });
|
// Error already handled, just show toast
|
||||||
toast({
|
toast({
|
||||||
title: 'Reset Failed',
|
title: 'Reset Failed',
|
||||||
description: getErrorMessage(error),
|
description: getErrorMessage(error),
|
||||||
@@ -516,7 +516,7 @@ export function useModerationActions(config: ModerationActionsConfig): Moderatio
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (auditError) {
|
} catch (auditError) {
|
||||||
logger.error('Failed to log submission retry audit', { error: auditError });
|
// Silent - audit logging is non-critical
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -527,7 +527,7 @@ export function useModerationActions(config: ModerationActionsConfig): Moderatio
|
|||||||
|
|
||||||
logger.log(`✅ Retried ${failedItems.length} failed items for ${item.id}`);
|
logger.log(`✅ Retried ${failedItems.length} failed items for ${item.id}`);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error('❌ Error retrying items:', { error: getErrorMessage(error) });
|
// Error already handled, just show toast
|
||||||
toast({
|
toast({
|
||||||
title: 'Retry Failed',
|
title: 'Retry Failed',
|
||||||
description: getErrorMessage(error) || 'Failed to retry items',
|
description: getErrorMessage(error) || 'Failed to retry items',
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ export function useModerationFilters(
|
|||||||
return JSON.parse(saved);
|
return JSON.parse(saved);
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.warn('Failed to load persisted filters', { error, storageKey });
|
// Silent - localStorage failures are non-critical
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -153,7 +153,7 @@ export function useModerationFilters(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.warn('Failed to load persisted sort', { error, storageKey });
|
// Silent - localStorage failures are non-critical
|
||||||
}
|
}
|
||||||
|
|
||||||
return initialSortConfig;
|
return initialSortConfig;
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig):
|
|||||||
// Show error toast when query fails
|
// Show error toast when query fails
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (queueQuery.error) {
|
if (queueQuery.error) {
|
||||||
logger.error('❌ Queue query error:', { error: getErrorMessage(queueQuery.error) });
|
// Error already captured by TanStack Query
|
||||||
toast({
|
toast({
|
||||||
variant: 'destructive',
|
variant: 'destructive',
|
||||||
title: 'Failed to Load Queue',
|
title: 'Failed to Load Queue',
|
||||||
@@ -332,7 +332,7 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig):
|
|||||||
queue.refreshStats();
|
queue.refreshStats();
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
const errorMsg = getErrorMessage(error);
|
||||||
logger.error("Error deleting submission:", { error: errorMsg, itemId: item.id });
|
// Silent - operation handled optimistically
|
||||||
|
|
||||||
setItems((prev) => {
|
setItems((prev) => {
|
||||||
if (prev.some((i) => i.id === item.id)) return prev;
|
if (prev.some((i) => i.id === item.id)) return prev;
|
||||||
@@ -373,7 +373,7 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig):
|
|||||||
setItems((prev) => prev.filter((i) => i.id !== item.id));
|
setItems((prev) => prev.filter((i) => i.id !== item.id));
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
const errorMsg = getErrorMessage(error);
|
||||||
logger.error("Error resetting submission:", { error: errorMsg, itemId: item.id });
|
// Silent - operation handled optimistically
|
||||||
toast({
|
toast({
|
||||||
title: "Reset Failed",
|
title: "Reset Failed",
|
||||||
description: errorMsg,
|
description: errorMsg,
|
||||||
@@ -441,7 +441,7 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig):
|
|||||||
queue.refreshStats();
|
queue.refreshStats();
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
const errorMsg = getErrorMessage(error);
|
||||||
logger.error("Error retrying failed items:", { error: errorMsg, itemId: item.id });
|
// Silent - operation handled optimistically
|
||||||
toast({
|
toast({
|
||||||
title: "Retry Failed",
|
title: "Retry Failed",
|
||||||
description: errorMsg,
|
description: errorMsg,
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ export function usePagination(config: PaginationConfig = {}): PaginationState {
|
|||||||
return JSON.parse(saved);
|
return JSON.parse(saved);
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.warn('Failed to load pagination state', { error, storageKey });
|
// Silent - localStorage failures are non-critical
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ export function useProfileCache() {
|
|||||||
.in('user_id', uncachedIds);
|
.in('user_id', uncachedIds);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('Error fetching profiles:', { error: getErrorMessage(error) });
|
// Silent - cache miss is acceptable
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ export function useProfileCache() {
|
|||||||
avatar_url: profile.avatar_url || undefined
|
avatar_url: profile.avatar_url || undefined
|
||||||
}));
|
}));
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error('Failed to bulk fetch profiles:', { error: getErrorMessage(error) });
|
// Silent - cache operations are non-critical
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}, [getCached, setCached, getUncachedIds]);
|
}, [getCached, setCached, getUncachedIds]);
|
||||||
|
|||||||
@@ -179,14 +179,14 @@ export function useQueueQuery(config: UseQueueQueryConfig): UseQueueQueryReturn
|
|||||||
|
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
const specificMessage = getSpecificErrorMessage(result.error);
|
const specificMessage = getSpecificErrorMessage(result.error);
|
||||||
logger.error('❌ [TanStack Query] Error:', { error: specificMessage });
|
// Error already captured in context
|
||||||
throw new Error(specificMessage);
|
throw new Error(specificMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate data shape before returning
|
// Validate data shape before returning
|
||||||
const validation = validateModerationItems(result.submissions);
|
const validation = validateModerationItems(result.submissions);
|
||||||
if (!validation.success) {
|
if (!validation.success) {
|
||||||
logger.error('❌ Invalid data shape', { error: validation.error });
|
// Invalid data shape
|
||||||
throw new Error(validation.error || 'Invalid data format');
|
throw new Error(validation.error || 'Invalid data format');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ export function useRealtimeSubscriptions(
|
|||||||
.single();
|
.single();
|
||||||
|
|
||||||
if (error || !submission) {
|
if (error || !submission) {
|
||||||
logger.error('Error fetching submission details:', { error: getErrorMessage(error) });
|
// Silent - will retry on next attempt
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,7 +321,7 @@ export function useRealtimeSubscriptions(
|
|||||||
|
|
||||||
onNewItem(fullItem);
|
onNewItem(fullItem);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error('Error building new item notification:', { error: getErrorMessage(error) });
|
// Silent - notifications are non-critical
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
filters,
|
filters,
|
||||||
|
|||||||
@@ -2,8 +2,7 @@ import { useState, useEffect } from 'react';
|
|||||||
import { supabase } from '@/lib/supabaseClient';
|
import { supabase } from '@/lib/supabaseClient';
|
||||||
import { ComboboxOption } from '@/components/ui/combobox';
|
import { ComboboxOption } from '@/components/ui/combobox';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { logger } from '@/lib/logger';
|
import { handleNonCriticalError } from '@/lib/errorHandler';
|
||||||
import { getErrorMessage } from '@/lib/errorHandler';
|
|
||||||
|
|
||||||
export function useCountries() {
|
export function useCountries() {
|
||||||
const [countries, setCountries] = useState<ComboboxOption[]>([]);
|
const [countries, setCountries] = useState<ComboboxOption[]>([]);
|
||||||
@@ -31,8 +30,7 @@ export function useCountries() {
|
|||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
handleNonCriticalError(error, { action: 'Fetch countries' });
|
||||||
logger.error('Failed to fetch countries', { error: errorMsg });
|
|
||||||
toast.error('Failed to load countries', {
|
toast.error('Failed to load countries', {
|
||||||
description: 'Please refresh the page and try again.',
|
description: 'Please refresh the page and try again.',
|
||||||
});
|
});
|
||||||
@@ -80,8 +78,10 @@ export function useStatesProvinces(country?: string) {
|
|||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
handleNonCriticalError(error, {
|
||||||
logger.error('Failed to fetch states/provinces', { country, error: errorMsg });
|
action: 'Fetch states/provinces',
|
||||||
|
metadata: { country },
|
||||||
|
});
|
||||||
toast.error('Failed to load states/provinces', {
|
toast.error('Failed to load states/provinces', {
|
||||||
description: 'Please refresh the page and try again.',
|
description: 'Please refresh the page and try again.',
|
||||||
});
|
});
|
||||||
@@ -120,8 +120,7 @@ export function useManufacturers() {
|
|||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
handleNonCriticalError(error, { action: 'Fetch manufacturers' });
|
||||||
logger.error('Failed to fetch manufacturers', { error: errorMsg });
|
|
||||||
toast.error('Failed to load manufacturers', {
|
toast.error('Failed to load manufacturers', {
|
||||||
description: 'Please refresh the page and try again.',
|
description: 'Please refresh the page and try again.',
|
||||||
});
|
});
|
||||||
@@ -165,8 +164,10 @@ export function useRideModels(manufacturerId?: string) {
|
|||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
handleNonCriticalError(error, {
|
||||||
logger.error('Failed to fetch ride models', { manufacturerId, error: errorMsg });
|
action: 'Fetch ride models',
|
||||||
|
metadata: { manufacturerId },
|
||||||
|
});
|
||||||
toast.error('Failed to load ride models', {
|
toast.error('Failed to load ride models', {
|
||||||
description: 'Please refresh the page and try again.',
|
description: 'Please refresh the page and try again.',
|
||||||
});
|
});
|
||||||
@@ -208,8 +209,7 @@ export function useCompanyHeadquarters() {
|
|||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
handleNonCriticalError(error, { action: 'Fetch headquarters' });
|
||||||
logger.error('Failed to fetch headquarters', { error: errorMsg });
|
|
||||||
toast.error('Failed to load headquarters', {
|
toast.error('Failed to load headquarters', {
|
||||||
description: 'Please refresh the page and try again.',
|
description: 'Please refresh the page and try again.',
|
||||||
});
|
});
|
||||||
@@ -248,8 +248,7 @@ export function useOperators() {
|
|||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
handleNonCriticalError(error, { action: 'Fetch operators' });
|
||||||
logger.error('Failed to fetch operators', { error: errorMsg });
|
|
||||||
toast.error('Failed to load operators', {
|
toast.error('Failed to load operators', {
|
||||||
description: 'Please refresh the page and try again.',
|
description: 'Please refresh the page and try again.',
|
||||||
});
|
});
|
||||||
@@ -288,8 +287,7 @@ export function usePropertyOwners() {
|
|||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
handleNonCriticalError(error, { action: 'Fetch property owners' });
|
||||||
logger.error('Failed to fetch property owners', { error: errorMsg });
|
|
||||||
toast.error('Failed to load property owners', {
|
toast.error('Failed to load property owners', {
|
||||||
description: 'Please refresh the page and try again.',
|
description: 'Please refresh the page and try again.',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ export function useBanCheck() {
|
|||||||
navigate('/');
|
navigate('/');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('Ban check error', { error, userId: user.id });
|
// Silent - ban check failure is non-critical, user proceeds normally
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useState, useEffect, useRef, useCallback } from 'react';
|
import { useState, useEffect, useRef, useCallback } from 'react';
|
||||||
import { supabase } from '@/lib/supabaseClient';
|
import { supabase } from '@/lib/supabaseClient';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { getErrorMessage, handleNonCriticalError } from '@/lib/errorHandler';
|
import { getErrorMessage, handleNonCriticalError, handleError } from '@/lib/errorHandler';
|
||||||
import type { EntityType, EntityVersion } from '@/types/versioning';
|
import type { EntityType, EntityVersion } from '@/types/versioning';
|
||||||
import { logger } from '@/lib/logger';
|
import { logger } from '@/lib/logger';
|
||||||
|
|
||||||
@@ -117,11 +117,13 @@ export function useEntityVersions(entityType: EntityType, entityId: string) {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
handleNonCriticalError(error, {
|
||||||
logger.error('Failed to fetch versions', { entityType, entityId, error: errorMsg });
|
action: 'Fetch entity versions',
|
||||||
|
metadata: { entityType, entityId },
|
||||||
|
});
|
||||||
|
|
||||||
if (isMountedRef.current && currentRequestId === requestCounterRef.current) {
|
if (isMountedRef.current && currentRequestId === requestCounterRef.current) {
|
||||||
toast.error(errorMsg);
|
toast.error(getErrorMessage(error));
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,10 +151,12 @@ export function useEntityVersions(entityType: EntityType, entityId: string) {
|
|||||||
|
|
||||||
return data;
|
return data;
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
handleNonCriticalError(error, {
|
||||||
logger.error('Failed to compare versions', { entityType, fromVersionId, toVersionId, error: errorMsg });
|
action: 'Compare entity versions',
|
||||||
|
metadata: { entityType, fromVersionId, toVersionId },
|
||||||
|
});
|
||||||
if (isMountedRef.current) {
|
if (isMountedRef.current) {
|
||||||
toast.error(errorMsg);
|
toast.error(getErrorMessage(error));
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -187,11 +191,13 @@ export function useEntityVersions(entityType: EntityType, entityId: string) {
|
|||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
handleError(error, {
|
||||||
logger.error('Failed to rollback version', { entityType, entityId, targetVersionId, error: errorMsg });
|
action: 'Rollback entity version',
|
||||||
|
metadata: { entityType, entityId, targetVersionId },
|
||||||
|
});
|
||||||
if (isMountedRef.current) {
|
if (isMountedRef.current) {
|
||||||
toast.error('Failed to restore version', {
|
toast.error('Failed to restore version', {
|
||||||
description: errorMsg
|
description: getErrorMessage(error)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { useState, useEffect, useMemo, useCallback } from 'react';
|
import { useState, useEffect, useMemo, useCallback } from 'react';
|
||||||
import { supabase } from '@/lib/supabaseClient';
|
import { supabase } from '@/lib/supabaseClient';
|
||||||
import { Park, Ride, Company } from '@/types/database';
|
import { Park, Ride, Company } from '@/types/database';
|
||||||
import { logger } from '@/lib/logger';
|
|
||||||
import * as storage from '@/lib/localStorage';
|
import * as storage from '@/lib/localStorage';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { getErrorMessage } from '@/lib/errorHandler';
|
import { handleNonCriticalError } from '@/lib/errorHandler';
|
||||||
|
|
||||||
export interface SearchResult {
|
export interface SearchResult {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -167,11 +166,9 @@ export function useSearch(options: UseSearchOptions = {}) {
|
|||||||
|
|
||||||
setResults(searchResults.slice(0, limit));
|
setResults(searchResults.slice(0, limit));
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
handleNonCriticalError(error, {
|
||||||
logger.error('Search failed', {
|
action: 'Search',
|
||||||
query: searchQuery,
|
metadata: { query: searchQuery, types },
|
||||||
types,
|
|
||||||
error: errorMsg
|
|
||||||
});
|
});
|
||||||
|
|
||||||
toast.error('Search failed', {
|
toast.error('Search failed', {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { useAuth } from './useAuth';
|
|||||||
import { useRequireMFA } from './useRequireMFA';
|
import { useRequireMFA } from './useRequireMFA';
|
||||||
import { getSessionAal } from '@/lib/authService';
|
import { getSessionAal } from '@/lib/authService';
|
||||||
import { logger } from '@/lib/logger';
|
import { logger } from '@/lib/logger';
|
||||||
|
import { handleNonCriticalError } from '@/lib/errorHandler';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Phase 3: Session Monitoring Hook
|
* Phase 3: Session Monitoring Hook
|
||||||
@@ -56,10 +57,9 @@ export function useSessionMonitor() {
|
|||||||
}, 30000);
|
}, 30000);
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error('Session monitor check failed', {
|
handleNonCriticalError(error, {
|
||||||
|
action: 'Session monitor check',
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
action: 'session_monitor',
|
|
||||||
error: error instanceof Error ? error.message : String(error)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, 60000);
|
}, 60000);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { useState, useEffect, useCallback } from 'react';
|
|||||||
import { invokeWithTracking } from '@/lib/edgeFunctionTracking';
|
import { invokeWithTracking } from '@/lib/edgeFunctionTracking';
|
||||||
import { useAuth } from '@/hooks/useAuth';
|
import { useAuth } from '@/hooks/useAuth';
|
||||||
import { supabase } from '@/lib/supabaseClient';
|
import { supabase } from '@/lib/supabaseClient';
|
||||||
import { logger } from '@/lib/logger';
|
import { handleNonCriticalError } from '@/lib/errorHandler';
|
||||||
import { UnitPreferences, getMeasurementSystemFromCountry } from '@/lib/units';
|
import { UnitPreferences, getMeasurementSystemFromCountry } from '@/lib/units';
|
||||||
import type { Json } from '@/integrations/supabase/types';
|
import type { Json } from '@/integrations/supabase/types';
|
||||||
import * as storage from '@/lib/localStorage';
|
import * as storage from '@/lib/localStorage';
|
||||||
@@ -42,11 +42,9 @@ export function useUnitPreferences() {
|
|||||||
.maybeSingle();
|
.maybeSingle();
|
||||||
|
|
||||||
if (error && error.code !== 'PGRST116') {
|
if (error && error.code !== 'PGRST116') {
|
||||||
logger.error('Failed to fetch unit preferences', {
|
handleNonCriticalError(error, {
|
||||||
|
action: 'Fetch unit preferences',
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
action: 'fetch_unit_preferences',
|
|
||||||
error: error.message,
|
|
||||||
errorCode: error.code
|
|
||||||
});
|
});
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
@@ -71,10 +69,9 @@ export function useUnitPreferences() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error('Error loading unit preferences', {
|
handleNonCriticalError(error, {
|
||||||
|
action: 'Load unit preferences',
|
||||||
userId: user?.id,
|
userId: user?.id,
|
||||||
action: 'load_unit_preferences',
|
|
||||||
error: error instanceof Error ? error.message : String(error)
|
|
||||||
});
|
});
|
||||||
await autoDetectPreferences();
|
await autoDetectPreferences();
|
||||||
} finally {
|
} finally {
|
||||||
@@ -106,10 +103,9 @@ export function useUnitPreferences() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('Error saving auto-detected preferences', {
|
handleNonCriticalError(error, {
|
||||||
|
action: 'Save auto-detected preferences',
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
action: 'save_auto_detected_preferences',
|
|
||||||
error: error.message
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -119,10 +115,9 @@ export function useUnitPreferences() {
|
|||||||
return newPreferences;
|
return newPreferences;
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error('Error auto-detecting location', {
|
handleNonCriticalError(error, {
|
||||||
|
action: 'Auto-detect location',
|
||||||
userId: user?.id,
|
userId: user?.id,
|
||||||
action: 'auto_detect_location',
|
|
||||||
error: error instanceof Error ? error.message : String(error)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,19 +139,13 @@ export function useUnitPreferences() {
|
|||||||
updated_at: new Date().toISOString()
|
updated_at: new Date().toISOString()
|
||||||
})
|
})
|
||||||
.eq('user_id', user.id);
|
.eq('user_id', user.id);
|
||||||
|
|
||||||
logger.info('Unit preferences updated', {
|
|
||||||
userId: user.id,
|
|
||||||
action: 'update_unit_preferences'
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
storage.setJSON('unit_preferences', updated);
|
storage.setJSON('unit_preferences', updated);
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error('Error saving unit preferences', {
|
handleNonCriticalError(error, {
|
||||||
|
action: 'Save unit preferences',
|
||||||
userId: user?.id,
|
userId: user?.id,
|
||||||
action: 'save_unit_preferences',
|
|
||||||
error: error instanceof Error ? error.message : String(error)
|
|
||||||
});
|
});
|
||||||
setPreferences(preferences);
|
setPreferences(preferences);
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { useQuery } from '@tanstack/react-query';
|
|||||||
import { supabase } from '@/lib/supabaseClient';
|
import { supabase } from '@/lib/supabaseClient';
|
||||||
import { useAuth } from '@/hooks/useAuth';
|
import { useAuth } from '@/hooks/useAuth';
|
||||||
import { queryKeys } from '@/lib/queryKeys';
|
import { queryKeys } from '@/lib/queryKeys';
|
||||||
import { logger } from '@/lib/logger';
|
import { handleNonCriticalError } from '@/lib/errorHandler';
|
||||||
|
|
||||||
export type UserRole = 'admin' | 'moderator' | 'user' | 'superuser';
|
export type UserRole = 'admin' | 'moderator' | 'user' | 'superuser';
|
||||||
|
|
||||||
@@ -30,7 +30,10 @@ export function useUserRole() {
|
|||||||
.eq('user_id', user.id);
|
.eq('user_id', user.id);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('Error fetching user roles', { error, userId: user.id });
|
handleNonCriticalError(error, {
|
||||||
|
action: 'Fetch user roles',
|
||||||
|
userId: user.id,
|
||||||
|
});
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +54,10 @@ export function useUserRole() {
|
|||||||
.rpc('get_user_management_permissions', { _user_id: user.id });
|
.rpc('get_user_management_permissions', { _user_id: user.id });
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('Error fetching user permissions', { error, userId: user.id });
|
handleNonCriticalError(error, {
|
||||||
|
action: 'Fetch user permissions',
|
||||||
|
userId: user.id,
|
||||||
|
});
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { supabase } from '@/lib/supabaseClient';
|
import { supabase } from '@/lib/supabaseClient';
|
||||||
import { logger } from './logger';
|
import { handleNonCriticalError } from './errorHandler';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write admin audit details to relational table
|
* Write admin audit details to relational table
|
||||||
@@ -27,7 +27,10 @@ export async function writeAdminAuditDetails(
|
|||||||
.insert(entries);
|
.insert(entries);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('Failed to write admin audit details', { error, auditLogId });
|
handleNonCriticalError(error, {
|
||||||
|
action: 'Write admin audit details',
|
||||||
|
metadata: { auditLogId },
|
||||||
|
});
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,7 +56,10 @@ export async function writeModerationAuditMetadata(
|
|||||||
.insert(entries);
|
.insert(entries);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('Failed to write moderation audit metadata', { error, auditLogId });
|
handleNonCriticalError(error, {
|
||||||
|
action: 'Write moderation audit metadata',
|
||||||
|
metadata: { auditLogId },
|
||||||
|
});
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,7 +90,10 @@ export async function writeItemChangeFields(
|
|||||||
.insert(entries);
|
.insert(entries);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('Failed to write item change fields', { error, editHistoryId });
|
handleNonCriticalError(error, {
|
||||||
|
action: 'Write item change fields',
|
||||||
|
metadata: { editHistoryId },
|
||||||
|
});
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,7 +127,10 @@ export async function writeRequestBreadcrumbs(
|
|||||||
.insert(entries);
|
.insert(entries);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('Failed to write request breadcrumbs', { error, requestId });
|
handleNonCriticalError(error, {
|
||||||
|
action: 'Write request breadcrumbs',
|
||||||
|
metadata: { requestId },
|
||||||
|
});
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,7 +147,10 @@ export async function readAdminAuditDetails(
|
|||||||
.eq('audit_log_id', auditLogId);
|
.eq('audit_log_id', auditLogId);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('Failed to read admin audit details', { error, auditLogId });
|
handleNonCriticalError(error, {
|
||||||
|
action: 'Read admin audit details',
|
||||||
|
metadata: { auditLogId },
|
||||||
|
});
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,7 +172,10 @@ export async function readModerationAuditMetadata(
|
|||||||
.eq('audit_log_id', auditLogId);
|
.eq('audit_log_id', auditLogId);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('Failed to read moderation audit metadata', { error, auditLogId });
|
handleNonCriticalError(error, {
|
||||||
|
action: 'Read moderation audit metadata',
|
||||||
|
metadata: { auditLogId },
|
||||||
|
});
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +197,10 @@ export async function readItemChangeFields(
|
|||||||
.eq('edit_history_id', editHistoryId);
|
.eq('edit_history_id', editHistoryId);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('Failed to read item change fields', { error, editHistoryId });
|
handleNonCriticalError(error, {
|
||||||
|
action: 'Read item change fields',
|
||||||
|
metadata: { editHistoryId },
|
||||||
|
});
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,7 +239,10 @@ export async function writeProfileChangeFields(
|
|||||||
.insert(entries);
|
.insert(entries);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('Failed to write profile change fields', { error, auditLogId });
|
handleNonCriticalError(error, {
|
||||||
|
action: 'Write profile change fields',
|
||||||
|
metadata: { auditLogId },
|
||||||
|
});
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -252,7 +276,10 @@ export async function writeConflictDetailFields(
|
|||||||
.insert(entries);
|
.insert(entries);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('Failed to write conflict detail fields', { error, conflictResolutionId });
|
handleNonCriticalError(error, {
|
||||||
|
action: 'Write conflict detail fields',
|
||||||
|
metadata: { conflictResolutionId },
|
||||||
|
});
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import type {
|
|||||||
} from '@/types/auth';
|
} from '@/types/auth';
|
||||||
import { setStepUpRequired, setAuthMethod, clearAllAuthFlags } from './sessionFlags';
|
import { setStepUpRequired, setAuthMethod, clearAllAuthFlags } from './sessionFlags';
|
||||||
import { logger } from './logger';
|
import { logger } from './logger';
|
||||||
import { getErrorMessage } from './errorHandler';
|
import { getErrorMessage, handleNonCriticalError } from './errorHandler';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract AAL level from session using Supabase API
|
* Extract AAL level from session using Supabase API
|
||||||
@@ -37,9 +37,8 @@ export async function getSessionAal(session: Session | null): Promise<AALLevel>
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('[AuthService] Error getting AAL', {
|
handleNonCriticalError(error, {
|
||||||
action: 'get_session_aal',
|
action: 'Get session AAL',
|
||||||
error: error.message
|
|
||||||
});
|
});
|
||||||
return 'aal1';
|
return 'aal1';
|
||||||
}
|
}
|
||||||
@@ -48,10 +47,8 @@ export async function getSessionAal(session: Session | null): Promise<AALLevel>
|
|||||||
logger.log('[AuthService] Returning AAL', { level });
|
logger.log('[AuthService] Returning AAL', { level });
|
||||||
return level;
|
return level;
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMessage = getErrorMessage(error);
|
handleNonCriticalError(error, {
|
||||||
logger.error('[AuthService] Exception getting AAL', {
|
action: 'Get session AAL exception',
|
||||||
action: 'get_session_aal',
|
|
||||||
error: errorMessage
|
|
||||||
});
|
});
|
||||||
return 'aal1';
|
return 'aal1';
|
||||||
}
|
}
|
||||||
@@ -65,9 +62,8 @@ export async function getEnrolledFactors(): Promise<MFAFactor[]> {
|
|||||||
const { data, error } = await supabase.auth.mfa.listFactors();
|
const { data, error } = await supabase.auth.mfa.listFactors();
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('[AuthService] Error listing factors', {
|
handleNonCriticalError(error, {
|
||||||
action: 'get_enrolled_factors',
|
action: 'List MFA factors',
|
||||||
error: error.message
|
|
||||||
});
|
});
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@@ -83,10 +79,8 @@ export async function getEnrolledFactors(): Promise<MFAFactor[]> {
|
|||||||
updated_at: f.updated_at,
|
updated_at: f.updated_at,
|
||||||
}));
|
}));
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMessage = getErrorMessage(error);
|
handleNonCriticalError(error, {
|
||||||
logger.error('[AuthService] Exception listing factors', {
|
action: 'List MFA factors exception',
|
||||||
action: 'get_enrolled_factors',
|
|
||||||
error: errorMessage
|
|
||||||
});
|
});
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@@ -135,21 +129,18 @@ export async function verifyMfaRequired(userId: string): Promise<boolean> {
|
|||||||
.in('role', ['admin', 'moderator']);
|
.in('role', ['admin', 'moderator']);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('[AuthService] Error checking roles', {
|
handleNonCriticalError(error, {
|
||||||
action: 'verify_mfa_required',
|
action: 'Verify MFA required',
|
||||||
userId,
|
userId,
|
||||||
error: error.message
|
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (data?.length || 0) > 0;
|
return (data?.length || 0) > 0;
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMessage = getErrorMessage(error);
|
handleNonCriticalError(error, {
|
||||||
logger.error('[AuthService] Exception checking roles', {
|
action: 'Verify MFA required exception',
|
||||||
action: 'verify_mfa_required',
|
|
||||||
userId,
|
userId,
|
||||||
error: errorMessage
|
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -207,15 +198,13 @@ export async function handlePostAuthFlow(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMessage = getErrorMessage(error);
|
handleNonCriticalError(error, {
|
||||||
logger.error('[AuthService] Error in post-auth flow', {
|
action: 'Handle post-auth flow',
|
||||||
action: 'handle_post_auth_flow',
|
metadata: { authMethod },
|
||||||
authMethod,
|
|
||||||
error: errorMessage
|
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
error: errorMessage,
|
error: getErrorMessage(error),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -234,10 +223,9 @@ export async function verifyMfaUpgrade(session: Session | null): Promise<MFAChal
|
|||||||
const currentAal = await getSessionAal(session);
|
const currentAal = await getSessionAal(session);
|
||||||
|
|
||||||
if (currentAal !== 'aal2') {
|
if (currentAal !== 'aal2') {
|
||||||
logger.error('[AuthService] MFA verification failed', {
|
handleNonCriticalError(new Error('MFA verification failed'), {
|
||||||
action: 'verify_mfa_upgrade',
|
action: 'Verify MFA upgrade',
|
||||||
expectedAal: 'aal2',
|
metadata: { expectedAal: 'aal2', actualAal: currentAal },
|
||||||
actualAal: currentAal
|
|
||||||
});
|
});
|
||||||
await logAuthEvent(session.user.id, 'mfa_verification_failed', {
|
await logAuthEvent(session.user.id, 'mfa_verification_failed', {
|
||||||
expected_aal: 'aal2',
|
expected_aal: 'aal2',
|
||||||
@@ -282,20 +270,15 @@ async function logAuthEvent(
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('[AuthService] Error logging auth event', {
|
handleNonCriticalError(error, {
|
||||||
action: 'log_auth_event',
|
action: 'Log auth event',
|
||||||
eventAction: action,
|
metadata: { eventAction: action, userId },
|
||||||
userId,
|
|
||||||
error: error.message
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMessage = getErrorMessage(error);
|
handleNonCriticalError(error, {
|
||||||
logger.error('[AuthService] Exception logging auth event', {
|
action: 'Log auth event exception',
|
||||||
action: 'log_auth_event',
|
metadata: { eventAction: action, userId },
|
||||||
eventAction: action,
|
|
||||||
userId,
|
|
||||||
error: errorMessage
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,7 @@ import { supabase } from '@/lib/supabaseClient';
|
|||||||
import type { Json } from '@/integrations/supabase/types';
|
import type { Json } from '@/integrations/supabase/types';
|
||||||
import { uploadPendingImages } from './imageUploadHelper';
|
import { uploadPendingImages } from './imageUploadHelper';
|
||||||
import { CompanyFormData, TempCompanyData } from '@/types/company';
|
import { CompanyFormData, TempCompanyData } from '@/types/company';
|
||||||
import { logger } from './logger';
|
import { handleError } from './errorHandler';
|
||||||
import { getErrorMessage } from './errorHandler';
|
|
||||||
|
|
||||||
export type { CompanyFormData, TempCompanyData };
|
export type { CompanyFormData, TempCompanyData };
|
||||||
|
|
||||||
@@ -33,10 +32,9 @@ export async function submitCompanyCreation(
|
|||||||
uploaded: uploadedImages
|
uploaded: uploadedImages
|
||||||
};
|
};
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
handleError(error, {
|
||||||
logger.error('Failed to upload images for company', {
|
action: 'Upload company images',
|
||||||
action: `${companyType}_creation`,
|
metadata: { companyType },
|
||||||
error: errorMsg
|
|
||||||
});
|
});
|
||||||
throw new Error('Failed to upload images. Please check your connection and try again.');
|
throw new Error('Failed to upload images. Please check your connection and try again.');
|
||||||
}
|
}
|
||||||
@@ -120,11 +118,9 @@ export async function submitCompanyUpdate(
|
|||||||
uploaded: uploadedImages
|
uploaded: uploadedImages
|
||||||
};
|
};
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
handleError(error, {
|
||||||
logger.error('Failed to upload images for company update', {
|
action: 'Upload company images for update',
|
||||||
action: `${existingCompany.company_type}_update`,
|
metadata: { companyType: existingCompany.company_type, companyId },
|
||||||
companyId,
|
|
||||||
error: errorMsg
|
|
||||||
});
|
});
|
||||||
throw new Error('Failed to upload images. Please check your connection and try again.');
|
throw new Error('Failed to upload images. Please check your connection and try again.');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { supabase } from '@/lib/supabaseClient';
|
import { supabase } from '@/lib/supabaseClient';
|
||||||
import { getErrorMessage } from '@/lib/errorHandler';
|
import { handleError, handleNonCriticalError } from '@/lib/errorHandler';
|
||||||
import { logger } from '@/lib/logger';
|
|
||||||
import { updateSubmissionItem, type SubmissionItemWithDeps, type DependencyConflict } from './submissionItemsService';
|
import { updateSubmissionItem, type SubmissionItemWithDeps, type DependencyConflict } from './submissionItemsService';
|
||||||
|
|
||||||
export interface ResolutionResult {
|
export interface ResolutionResult {
|
||||||
@@ -86,15 +85,13 @@ export async function resolveConflicts(
|
|||||||
updatedSelections,
|
updatedSelections,
|
||||||
};
|
};
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
handleError(error, {
|
||||||
logger.error('Conflict resolution error', {
|
action: 'Resolve conflicts',
|
||||||
action: 'resolve_conflicts',
|
metadata: { conflictCount: conflicts.length },
|
||||||
conflictCount: conflicts.length,
|
|
||||||
error: errorMsg
|
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
error: errorMsg,
|
error: error instanceof Error ? error.message : 'Unknown error',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -236,11 +233,9 @@ export async function findMatchingEntities(
|
|||||||
|
|
||||||
return [];
|
return [];
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
handleNonCriticalError(error, {
|
||||||
logger.error('Error finding matching entities', {
|
action: 'Find matching entities',
|
||||||
action: 'find_matching_entities',
|
metadata: { itemType },
|
||||||
itemType,
|
|
||||||
error: errorMsg
|
|
||||||
});
|
});
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { supabase } from '@/lib/supabaseClient';
|
import { supabase } from '@/lib/supabaseClient';
|
||||||
import { invokeWithTracking } from '@/lib/edgeFunctionTracking';
|
import { invokeWithTracking } from '@/lib/edgeFunctionTracking';
|
||||||
import { logger } from '@/lib/logger';
|
import { handleNonCriticalError } from '@/lib/errorHandler';
|
||||||
import { getErrorMessage } from '@/lib/errorHandler';
|
|
||||||
|
|
||||||
interface EmailValidationResult {
|
interface EmailValidationResult {
|
||||||
valid: boolean;
|
valid: boolean;
|
||||||
@@ -22,9 +21,8 @@ export async function validateEmailNotDisposable(email: string): Promise<EmailVa
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('Email validation error from backend', {
|
handleNonCriticalError(error, {
|
||||||
action: 'validate_email_backend',
|
action: 'Validate email backend',
|
||||||
error: error.message
|
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
valid: false,
|
valid: false,
|
||||||
@@ -34,10 +32,8 @@ export async function validateEmailNotDisposable(email: string): Promise<EmailVa
|
|||||||
|
|
||||||
return data as EmailValidationResult;
|
return data as EmailValidationResult;
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
handleNonCriticalError(error, {
|
||||||
logger.error('Email validation error', {
|
action: 'Validate email disposable',
|
||||||
action: 'validate_email_disposable',
|
|
||||||
error: errorMsg
|
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
valid: false,
|
valid: false,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import type { ProcessedImage } from './supabaseHelpers';
|
|||||||
import { extractChangedFields } from './submissionChangeDetection';
|
import { extractChangedFields } from './submissionChangeDetection';
|
||||||
import type { CompanyDatabaseRecord, TimelineEventDatabaseRecord } from '@/types/company-data';
|
import type { CompanyDatabaseRecord, TimelineEventDatabaseRecord } from '@/types/company-data';
|
||||||
import { logger } from './logger';
|
import { logger } from './logger';
|
||||||
import { getErrorMessage } from './errorHandler';
|
import { handleError } from './errorHandler';
|
||||||
import type { TimelineEventFormData, EntityType } from '@/types/timeline';
|
import type { TimelineEventFormData, EntityType } from '@/types/timeline';
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
@@ -345,13 +345,11 @@ async function submitCompositeCreation(
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('Composite submission failed', {
|
handleError(error, {
|
||||||
action: 'composite_submission',
|
action: 'Composite submission',
|
||||||
primaryType: uploadedPrimary.type,
|
metadata: { primaryType: uploadedPrimary.type, dependencyCount: dependencies.length },
|
||||||
dependencyCount: dependencies.length,
|
|
||||||
error: getErrorMessage(error)
|
|
||||||
});
|
});
|
||||||
throw new Error(`Failed to create composite submission: ${getErrorMessage(error)}`);
|
throw new Error(`Failed to create composite submission: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { submitted: true, submissionId: result };
|
return { submitted: true, submissionId: result };
|
||||||
@@ -440,12 +438,10 @@ export async function submitParkCreation(
|
|||||||
uploaded: uploadedImages
|
uploaded: uploadedImages
|
||||||
};
|
};
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMessage = getErrorMessage(error);
|
handleError(error, {
|
||||||
logger.error('Park image upload failed', {
|
action: 'Upload park images',
|
||||||
action: 'park_creation',
|
|
||||||
error: errorMessage
|
|
||||||
});
|
});
|
||||||
throw new Error(`Failed to upload images: ${errorMessage}`);
|
throw new Error(`Failed to upload images: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -751,12 +747,10 @@ export async function submitRideCreation(
|
|||||||
uploaded: uploadedImages
|
uploaded: uploadedImages
|
||||||
};
|
};
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMessage = getErrorMessage(error);
|
handleError(error, {
|
||||||
logger.error('Ride image upload failed', {
|
action: 'Upload ride images',
|
||||||
action: 'ride_creation',
|
|
||||||
error: errorMessage
|
|
||||||
});
|
});
|
||||||
throw new Error(`Failed to upload images: ${errorMessage}`);
|
throw new Error(`Failed to upload images: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -972,12 +966,10 @@ export async function submitRideModelCreation(
|
|||||||
uploaded: uploadedImages
|
uploaded: uploadedImages
|
||||||
};
|
};
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMessage = getErrorMessage(error);
|
handleError(error, {
|
||||||
logger.error('Ride model image upload failed', {
|
action: 'Upload ride model images',
|
||||||
action: 'ride_model_creation',
|
|
||||||
error: errorMessage
|
|
||||||
});
|
});
|
||||||
throw new Error(`Failed to upload images: ${errorMessage}`);
|
throw new Error(`Failed to upload images: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1110,12 +1102,10 @@ export async function submitManufacturerCreation(
|
|||||||
const uploadedImages = await uploadPendingImages(data.images.uploaded);
|
const uploadedImages = await uploadPendingImages(data.images.uploaded);
|
||||||
processedImages = { ...data.images, uploaded: uploadedImages };
|
processedImages = { ...data.images, uploaded: uploadedImages };
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMessage = getErrorMessage(error);
|
handleError(error, {
|
||||||
logger.error('Company image upload failed', {
|
action: 'Upload manufacturer images',
|
||||||
action: 'manufacturer_creation',
|
|
||||||
error: errorMessage
|
|
||||||
});
|
});
|
||||||
throw new Error(`Failed to upload images: ${errorMessage}`);
|
throw new Error(`Failed to upload images: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1218,12 +1208,10 @@ export async function submitDesignerCreation(
|
|||||||
const uploadedImages = await uploadPendingImages(data.images.uploaded);
|
const uploadedImages = await uploadPendingImages(data.images.uploaded);
|
||||||
processedImages = { ...data.images, uploaded: uploadedImages };
|
processedImages = { ...data.images, uploaded: uploadedImages };
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMessage = getErrorMessage(error);
|
handleError(error, {
|
||||||
logger.error('Company image upload failed', {
|
action: 'Upload designer images',
|
||||||
action: 'designer_creation',
|
|
||||||
error: errorMessage
|
|
||||||
});
|
});
|
||||||
throw new Error(`Failed to upload images: ${errorMessage}`);
|
throw new Error(`Failed to upload images: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1326,12 +1314,10 @@ export async function submitOperatorCreation(
|
|||||||
const uploadedImages = await uploadPendingImages(data.images.uploaded);
|
const uploadedImages = await uploadPendingImages(data.images.uploaded);
|
||||||
processedImages = { ...data.images, uploaded: uploadedImages };
|
processedImages = { ...data.images, uploaded: uploadedImages };
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMessage = getErrorMessage(error);
|
handleError(error, {
|
||||||
logger.error('Company image upload failed', {
|
action: 'Upload operator images',
|
||||||
action: 'operator_creation',
|
|
||||||
error: errorMessage
|
|
||||||
});
|
});
|
||||||
throw new Error(`Failed to upload images: ${errorMessage}`);
|
throw new Error(`Failed to upload images: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1434,12 +1420,10 @@ export async function submitPropertyOwnerCreation(
|
|||||||
const uploadedImages = await uploadPendingImages(data.images.uploaded);
|
const uploadedImages = await uploadPendingImages(data.images.uploaded);
|
||||||
processedImages = { ...data.images, uploaded: uploadedImages };
|
processedImages = { ...data.images, uploaded: uploadedImages };
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMessage = getErrorMessage(error);
|
handleError(error, {
|
||||||
logger.error('Company image upload failed', {
|
action: 'Upload property owner images',
|
||||||
action: 'property_owner_creation',
|
|
||||||
error: errorMessage
|
|
||||||
});
|
});
|
||||||
throw new Error(`Failed to upload images: ${errorMessage}`);
|
throw new Error(`Failed to upload images: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1602,11 +1586,9 @@ export async function submitTimelineEvent(
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (error || !submissionId) {
|
if (error || !submissionId) {
|
||||||
const errorMessage = getErrorMessage(error);
|
handleError(error || new Error('No submission ID returned'), {
|
||||||
logger.error('Timeline event submission failed', {
|
action: 'Submit timeline event',
|
||||||
action: 'create_timeline_event',
|
|
||||||
userId,
|
userId,
|
||||||
error: errorMessage
|
|
||||||
});
|
});
|
||||||
throw new Error('Failed to submit timeline event for review');
|
throw new Error('Failed to submit timeline event for review');
|
||||||
}
|
}
|
||||||
@@ -1679,11 +1661,9 @@ export async function submitTimelineEventUpdate(
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (rpcError || !result) {
|
if (rpcError || !result) {
|
||||||
const errorMessage = getErrorMessage(rpcError);
|
handleError(rpcError || new Error('No result returned'), {
|
||||||
logger.error('Timeline event update failed', {
|
action: 'Update timeline event',
|
||||||
action: 'update_timeline_event',
|
metadata: { eventId },
|
||||||
eventId,
|
|
||||||
error: errorMessage
|
|
||||||
});
|
});
|
||||||
throw new Error('Failed to submit timeline event update');
|
throw new Error('Failed to submit timeline event update');
|
||||||
}
|
}
|
||||||
@@ -1707,11 +1687,9 @@ export async function deleteTimelineEvent(
|
|||||||
.single();
|
.single();
|
||||||
|
|
||||||
if (fetchError) {
|
if (fetchError) {
|
||||||
const errorMessage = getErrorMessage(fetchError);
|
handleError(fetchError, {
|
||||||
logger.error('Timeline event fetch failed', {
|
action: 'Delete timeline event',
|
||||||
action: 'delete_timeline_event',
|
metadata: { eventId },
|
||||||
eventId,
|
|
||||||
error: errorMessage
|
|
||||||
});
|
});
|
||||||
throw new Error('Timeline event not found');
|
throw new Error('Timeline event not found');
|
||||||
}
|
}
|
||||||
@@ -1736,11 +1714,9 @@ export async function deleteTimelineEvent(
|
|||||||
.eq('id', eventId);
|
.eq('id', eventId);
|
||||||
|
|
||||||
if (deleteError) {
|
if (deleteError) {
|
||||||
const errorMessage = getErrorMessage(deleteError);
|
handleError(deleteError, {
|
||||||
logger.error('Timeline event deletion failed', {
|
action: 'Delete timeline event',
|
||||||
action: 'delete_timeline_event',
|
metadata: { eventId },
|
||||||
eventId,
|
|
||||||
error: errorMessage
|
|
||||||
});
|
});
|
||||||
throw new Error('Failed to delete timeline event');
|
throw new Error('Failed to delete timeline event');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user