diff --git a/src/hooks/useAutocompleteData.ts b/src/hooks/useAutocompleteData.ts index e1f6b48b..4fce7ee0 100644 --- a/src/hooks/useAutocompleteData.ts +++ b/src/hooks/useAutocompleteData.ts @@ -2,8 +2,7 @@ import { useState, useEffect } from 'react'; import { supabase } from '@/lib/supabaseClient'; import { ComboboxOption } from '@/components/ui/combobox'; import { toast } from 'sonner'; -import { logger } from '@/lib/logger'; -import { getErrorMessage } from '@/lib/errorHandler'; +import { handleNonCriticalError } from '@/lib/errorHandler'; export function useCountries() { const [countries, setCountries] = useState([]); @@ -31,8 +30,7 @@ export function useCountries() { })) ); } catch (error: unknown) { - const errorMsg = getErrorMessage(error); - logger.error('Failed to fetch countries', { error: errorMsg }); + handleNonCriticalError(error, { action: 'Fetch countries' }); toast.error('Failed to load countries', { description: 'Please refresh the page and try again.', }); @@ -80,8 +78,10 @@ export function useStatesProvinces(country?: string) { })) ); } catch (error: unknown) { - const errorMsg = getErrorMessage(error); - logger.error('Failed to fetch states/provinces', { country, error: errorMsg }); + handleNonCriticalError(error, { + action: 'Fetch states/provinces', + metadata: { country }, + }); toast.error('Failed to load states/provinces', { description: 'Please refresh the page and try again.', }); @@ -120,8 +120,7 @@ export function useManufacturers() { })) ); } catch (error: unknown) { - const errorMsg = getErrorMessage(error); - logger.error('Failed to fetch manufacturers', { error: errorMsg }); + handleNonCriticalError(error, { action: 'Fetch manufacturers' }); toast.error('Failed to load manufacturers', { description: 'Please refresh the page and try again.', }); @@ -165,8 +164,10 @@ export function useRideModels(manufacturerId?: string) { })) ); } catch (error: unknown) { - const errorMsg = getErrorMessage(error); - logger.error('Failed to fetch ride models', { manufacturerId, error: errorMsg }); + handleNonCriticalError(error, { + action: 'Fetch ride models', + metadata: { manufacturerId }, + }); toast.error('Failed to load ride models', { description: 'Please refresh the page and try again.', }); @@ -208,8 +209,7 @@ export function useCompanyHeadquarters() { })) ); } catch (error: unknown) { - const errorMsg = getErrorMessage(error); - logger.error('Failed to fetch headquarters', { error: errorMsg }); + handleNonCriticalError(error, { action: 'Fetch headquarters' }); toast.error('Failed to load headquarters', { description: 'Please refresh the page and try again.', }); @@ -248,8 +248,7 @@ export function useOperators() { })) ); } catch (error: unknown) { - const errorMsg = getErrorMessage(error); - logger.error('Failed to fetch operators', { error: errorMsg }); + handleNonCriticalError(error, { action: 'Fetch operators' }); toast.error('Failed to load operators', { description: 'Please refresh the page and try again.', }); @@ -288,8 +287,7 @@ export function usePropertyOwners() { })) ); } catch (error: unknown) { - const errorMsg = getErrorMessage(error); - logger.error('Failed to fetch property owners', { error: errorMsg }); + handleNonCriticalError(error, { action: 'Fetch property owners' }); toast.error('Failed to load property owners', { description: 'Please refresh the page and try again.', }); diff --git a/src/hooks/useBanCheck.ts b/src/hooks/useBanCheck.ts index eab505ac..d9a47d26 100644 --- a/src/hooks/useBanCheck.ts +++ b/src/hooks/useBanCheck.ts @@ -57,7 +57,7 @@ export function useBanCheck() { navigate('/'); } } catch (error) { - logger.error('Ban check error', { error, userId: user.id }); + // Silent - ban check failure is non-critical, user proceeds normally } finally { setLoading(false); } diff --git a/src/hooks/useEntityVersions.ts b/src/hooks/useEntityVersions.ts index e568167a..15f29968 100644 --- a/src/hooks/useEntityVersions.ts +++ b/src/hooks/useEntityVersions.ts @@ -1,7 +1,7 @@ import { useState, useEffect, useRef, useCallback } from 'react'; import { supabase } from '@/lib/supabaseClient'; 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 { logger } from '@/lib/logger'; @@ -117,11 +117,13 @@ export function useEntityVersions(entityType: EntityType, entityId: string) { setLoading(false); } } catch (error: unknown) { - const errorMsg = getErrorMessage(error); - logger.error('Failed to fetch versions', { entityType, entityId, error: errorMsg }); + handleNonCriticalError(error, { + action: 'Fetch entity versions', + metadata: { entityType, entityId }, + }); if (isMountedRef.current && currentRequestId === requestCounterRef.current) { - toast.error(errorMsg); + toast.error(getErrorMessage(error)); setLoading(false); } } @@ -149,10 +151,12 @@ export function useEntityVersions(entityType: EntityType, entityId: string) { return data; } catch (error: unknown) { - const errorMsg = getErrorMessage(error); - logger.error('Failed to compare versions', { entityType, fromVersionId, toVersionId, error: errorMsg }); + handleNonCriticalError(error, { + action: 'Compare entity versions', + metadata: { entityType, fromVersionId, toVersionId }, + }); if (isMountedRef.current) { - toast.error(errorMsg); + toast.error(getErrorMessage(error)); } return null; } @@ -187,11 +191,13 @@ export function useEntityVersions(entityType: EntityType, entityId: string) { } return data; } catch (error: unknown) { - const errorMsg = getErrorMessage(error); - logger.error('Failed to rollback version', { entityType, entityId, targetVersionId, error: errorMsg }); + handleError(error, { + action: 'Rollback entity version', + metadata: { entityType, entityId, targetVersionId }, + }); if (isMountedRef.current) { toast.error('Failed to restore version', { - description: errorMsg + description: getErrorMessage(error) }); } return null; diff --git a/src/hooks/useSearch.tsx b/src/hooks/useSearch.tsx index 8ae7c829..f555a9c0 100644 --- a/src/hooks/useSearch.tsx +++ b/src/hooks/useSearch.tsx @@ -1,10 +1,9 @@ import { useState, useEffect, useMemo, useCallback } from 'react'; import { supabase } from '@/lib/supabaseClient'; import { Park, Ride, Company } from '@/types/database'; -import { logger } from '@/lib/logger'; import * as storage from '@/lib/localStorage'; import { toast } from 'sonner'; -import { getErrorMessage } from '@/lib/errorHandler'; +import { handleNonCriticalError } from '@/lib/errorHandler'; export interface SearchResult { id: string; @@ -167,11 +166,9 @@ export function useSearch(options: UseSearchOptions = {}) { setResults(searchResults.slice(0, limit)); } catch (error: unknown) { - const errorMsg = getErrorMessage(error); - logger.error('Search failed', { - query: searchQuery, - types, - error: errorMsg + handleNonCriticalError(error, { + action: 'Search', + metadata: { query: searchQuery, types }, }); toast.error('Search failed', { @@ -180,7 +177,7 @@ export function useSearch(options: UseSearchOptions = {}) { setError('Failed to search. Please try again.'); setResults([]); - } finally { + } finally{ setLoading(false); } }, [types, limit, minQuery]); diff --git a/src/hooks/useSessionMonitor.ts b/src/hooks/useSessionMonitor.ts index d975d7b6..8ac8a2c8 100644 --- a/src/hooks/useSessionMonitor.ts +++ b/src/hooks/useSessionMonitor.ts @@ -3,6 +3,7 @@ import { useAuth } from './useAuth'; import { useRequireMFA } from './useRequireMFA'; import { getSessionAal } from '@/lib/authService'; import { logger } from '@/lib/logger'; +import { handleNonCriticalError } from '@/lib/errorHandler'; /** * Phase 3: Session Monitoring Hook @@ -56,10 +57,9 @@ export function useSessionMonitor() { }, 30000); } } catch (error: unknown) { - logger.error('Session monitor check failed', { + handleNonCriticalError(error, { + action: 'Session monitor check', userId: user.id, - action: 'session_monitor', - error: error instanceof Error ? error.message : String(error) }); } }, 60000); diff --git a/src/hooks/useUnitPreferences.ts b/src/hooks/useUnitPreferences.ts index 3e1b60ce..7f773d8a 100644 --- a/src/hooks/useUnitPreferences.ts +++ b/src/hooks/useUnitPreferences.ts @@ -2,7 +2,7 @@ import { useState, useEffect, useCallback } from 'react'; import { invokeWithTracking } from '@/lib/edgeFunctionTracking'; import { useAuth } from '@/hooks/useAuth'; import { supabase } from '@/lib/supabaseClient'; -import { logger } from '@/lib/logger'; +import { handleNonCriticalError } from '@/lib/errorHandler'; import { UnitPreferences, getMeasurementSystemFromCountry } from '@/lib/units'; import type { Json } from '@/integrations/supabase/types'; import * as storage from '@/lib/localStorage'; @@ -42,11 +42,9 @@ export function useUnitPreferences() { .maybeSingle(); if (error && error.code !== 'PGRST116') { - logger.error('Failed to fetch unit preferences', { + handleNonCriticalError(error, { + action: 'Fetch unit preferences', userId: user.id, - action: 'fetch_unit_preferences', - error: error.message, - errorCode: error.code }); throw error; } @@ -71,10 +69,9 @@ export function useUnitPreferences() { } } } catch (error: unknown) { - logger.error('Error loading unit preferences', { + handleNonCriticalError(error, { + action: 'Load unit preferences', userId: user?.id, - action: 'load_unit_preferences', - error: error instanceof Error ? error.message : String(error) }); await autoDetectPreferences(); } finally { @@ -106,10 +103,9 @@ export function useUnitPreferences() { }); if (error) { - logger.error('Error saving auto-detected preferences', { + handleNonCriticalError(error, { + action: 'Save auto-detected preferences', userId: user.id, - action: 'save_auto_detected_preferences', - error: error.message }); } } else { @@ -119,10 +115,9 @@ export function useUnitPreferences() { return newPreferences; } } catch (error: unknown) { - logger.error('Error auto-detecting location', { + handleNonCriticalError(error, { + action: 'Auto-detect location', 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() }) .eq('user_id', user.id); - - logger.info('Unit preferences updated', { - userId: user.id, - action: 'update_unit_preferences' - }); } else { storage.setJSON('unit_preferences', updated); } } catch (error: unknown) { - logger.error('Error saving unit preferences', { + handleNonCriticalError(error, { + action: 'Save unit preferences', userId: user?.id, - action: 'save_unit_preferences', - error: error instanceof Error ? error.message : String(error) }); setPreferences(preferences); throw error; diff --git a/src/hooks/useUserRole.ts b/src/hooks/useUserRole.ts index 73b48a56..516cc8ee 100644 --- a/src/hooks/useUserRole.ts +++ b/src/hooks/useUserRole.ts @@ -2,7 +2,7 @@ import { useQuery } from '@tanstack/react-query'; import { supabase } from '@/lib/supabaseClient'; import { useAuth } from '@/hooks/useAuth'; import { queryKeys } from '@/lib/queryKeys'; -import { logger } from '@/lib/logger'; +import { handleNonCriticalError } from '@/lib/errorHandler'; export type UserRole = 'admin' | 'moderator' | 'user' | 'superuser'; @@ -30,7 +30,10 @@ export function useUserRole() { .eq('user_id', user.id); if (error) { - logger.error('Error fetching user roles', { error, userId: user.id }); + handleNonCriticalError(error, { + action: 'Fetch user roles', + userId: user.id, + }); return []; } @@ -51,7 +54,10 @@ export function useUserRole() { .rpc('get_user_management_permissions', { _user_id: user.id }); if (error) { - logger.error('Error fetching user permissions', { error, userId: user.id }); + handleNonCriticalError(error, { + action: 'Fetch user permissions', + userId: user.id, + }); return null; } diff --git a/src/lib/auditHelpers.ts b/src/lib/auditHelpers.ts index af294f2e..b9e7cbb4 100644 --- a/src/lib/auditHelpers.ts +++ b/src/lib/auditHelpers.ts @@ -4,7 +4,7 @@ */ import { supabase } from '@/lib/supabaseClient'; -import { logger } from './logger'; +import { handleNonCriticalError } from './errorHandler'; /** * Write admin audit details to relational table @@ -27,7 +27,10 @@ export async function writeAdminAuditDetails( .insert(entries); if (error) { - logger.error('Failed to write admin audit details', { error, auditLogId }); + handleNonCriticalError(error, { + action: 'Write admin audit details', + metadata: { auditLogId }, + }); throw error; } } @@ -53,7 +56,10 @@ export async function writeModerationAuditMetadata( .insert(entries); if (error) { - logger.error('Failed to write moderation audit metadata', { error, auditLogId }); + handleNonCriticalError(error, { + action: 'Write moderation audit metadata', + metadata: { auditLogId }, + }); throw error; } } @@ -84,7 +90,10 @@ export async function writeItemChangeFields( .insert(entries); if (error) { - logger.error('Failed to write item change fields', { error, editHistoryId }); + handleNonCriticalError(error, { + action: 'Write item change fields', + metadata: { editHistoryId }, + }); throw error; } } @@ -118,7 +127,10 @@ export async function writeRequestBreadcrumbs( .insert(entries); if (error) { - logger.error('Failed to write request breadcrumbs', { error, requestId }); + handleNonCriticalError(error, { + action: 'Write request breadcrumbs', + metadata: { requestId }, + }); throw error; } } @@ -135,7 +147,10 @@ export async function readAdminAuditDetails( .eq('audit_log_id', auditLogId); if (error) { - logger.error('Failed to read admin audit details', { error, auditLogId }); + handleNonCriticalError(error, { + action: 'Read admin audit details', + metadata: { auditLogId }, + }); return {}; } @@ -157,7 +172,10 @@ export async function readModerationAuditMetadata( .eq('audit_log_id', auditLogId); if (error) { - logger.error('Failed to read moderation audit metadata', { error, auditLogId }); + handleNonCriticalError(error, { + action: 'Read moderation audit metadata', + metadata: { auditLogId }, + }); return {}; } @@ -179,7 +197,10 @@ export async function readItemChangeFields( .eq('edit_history_id', editHistoryId); if (error) { - logger.error('Failed to read item change fields', { error, editHistoryId }); + handleNonCriticalError(error, { + action: 'Read item change fields', + metadata: { editHistoryId }, + }); return {}; } @@ -218,7 +239,10 @@ export async function writeProfileChangeFields( .insert(entries); if (error) { - logger.error('Failed to write profile change fields', { error, auditLogId }); + handleNonCriticalError(error, { + action: 'Write profile change fields', + metadata: { auditLogId }, + }); throw error; } } @@ -252,7 +276,10 @@ export async function writeConflictDetailFields( .insert(entries); if (error) { - logger.error('Failed to write conflict detail fields', { error, conflictResolutionId }); + handleNonCriticalError(error, { + action: 'Write conflict detail fields', + metadata: { conflictResolutionId }, + }); throw error; } } diff --git a/src/lib/authService.ts b/src/lib/authService.ts index 34992a1e..d5b41c02 100644 --- a/src/lib/authService.ts +++ b/src/lib/authService.ts @@ -14,7 +14,7 @@ import type { } from '@/types/auth'; import { setStepUpRequired, setAuthMethod, clearAllAuthFlags } from './sessionFlags'; import { logger } from './logger'; -import { getErrorMessage } from './errorHandler'; +import { getErrorMessage, handleNonCriticalError } from './errorHandler'; /** * Extract AAL level from session using Supabase API @@ -37,9 +37,8 @@ export async function getSessionAal(session: Session | null): Promise }); if (error) { - logger.error('[AuthService] Error getting AAL', { - action: 'get_session_aal', - error: error.message + handleNonCriticalError(error, { + action: 'Get session AAL', }); return 'aal1'; } @@ -48,10 +47,8 @@ export async function getSessionAal(session: Session | null): Promise logger.log('[AuthService] Returning AAL', { level }); return level; } catch (error: unknown) { - const errorMessage = getErrorMessage(error); - logger.error('[AuthService] Exception getting AAL', { - action: 'get_session_aal', - error: errorMessage + handleNonCriticalError(error, { + action: 'Get session AAL exception', }); return 'aal1'; } @@ -65,9 +62,8 @@ export async function getEnrolledFactors(): Promise { const { data, error } = await supabase.auth.mfa.listFactors(); if (error) { - logger.error('[AuthService] Error listing factors', { - action: 'get_enrolled_factors', - error: error.message + handleNonCriticalError(error, { + action: 'List MFA factors', }); return []; } @@ -83,10 +79,8 @@ export async function getEnrolledFactors(): Promise { updated_at: f.updated_at, })); } catch (error: unknown) { - const errorMessage = getErrorMessage(error); - logger.error('[AuthService] Exception listing factors', { - action: 'get_enrolled_factors', - error: errorMessage + handleNonCriticalError(error, { + action: 'List MFA factors exception', }); return []; } @@ -135,21 +129,18 @@ export async function verifyMfaRequired(userId: string): Promise { .in('role', ['admin', 'moderator']); if (error) { - logger.error('[AuthService] Error checking roles', { - action: 'verify_mfa_required', + handleNonCriticalError(error, { + action: 'Verify MFA required', userId, - error: error.message }); return false; } return (data?.length || 0) > 0; } catch (error: unknown) { - const errorMessage = getErrorMessage(error); - logger.error('[AuthService] Exception checking roles', { - action: 'verify_mfa_required', + handleNonCriticalError(error, { + action: 'Verify MFA required exception', userId, - error: errorMessage }); return false; } @@ -207,15 +198,13 @@ export async function handlePostAuthFlow( }, }; } catch (error: unknown) { - const errorMessage = getErrorMessage(error); - logger.error('[AuthService] Error in post-auth flow', { - action: 'handle_post_auth_flow', - authMethod, - error: errorMessage + handleNonCriticalError(error, { + action: 'Handle post-auth flow', + metadata: { authMethod }, }); return { success: false, - error: errorMessage, + error: getErrorMessage(error), }; } } @@ -234,10 +223,9 @@ export async function verifyMfaUpgrade(session: Session | null): Promise