diff --git a/src/components/auth/AuthButtons.tsx b/src/components/auth/AuthButtons.tsx index b08b6092..9f1cf5c2 100644 --- a/src/components/auth/AuthButtons.tsx +++ b/src/components/auth/AuthButtons.tsx @@ -26,7 +26,7 @@ export function AuthButtons() { description: "You've been signed out successfully." }); navigate('/'); - } catch (error) { + } catch (error: unknown) { const errorMsg = getErrorMessage(error); toast({ variant: "destructive", diff --git a/src/components/auth/MFAChallenge.tsx b/src/components/auth/MFAChallenge.tsx index 0734f2db..0b1d9993 100644 --- a/src/components/auth/MFAChallenge.tsx +++ b/src/components/auth/MFAChallenge.tsx @@ -26,7 +26,7 @@ export function MFAChallenge({ factorId, onSuccess, onCancel }: MFAChallengeProp const { data, error } = await supabase.auth.mfa.challenge({ factorId }); if (error) throw error; setChallengeId(data.id); - } catch (error) { + } catch (error: unknown) { toast({ variant: "destructive", title: "MFA Challenge Failed", @@ -59,7 +59,7 @@ export function MFAChallenge({ factorId, onSuccess, onCancel }: MFAChallengeProp }); onSuccess(); } - } catch (error) { + } catch (error: unknown) { toast({ variant: "destructive", title: "Verification Failed", diff --git a/src/components/auth/TOTPSetup.tsx b/src/components/auth/TOTPSetup.tsx index 2fbf53b7..ccb0ead3 100644 --- a/src/components/auth/TOTPSetup.tsx +++ b/src/components/auth/TOTPSetup.tsx @@ -50,7 +50,7 @@ export function TOTPSetup() { updated_at: factor.updated_at })); setFactors(totpFactors); - } catch (error) { + } catch (error: unknown) { logger.error('Failed to fetch TOTP factors', { userId: user?.id, action: 'fetch_totp_factors', diff --git a/src/components/moderation/ReportsQueue.tsx b/src/components/moderation/ReportsQueue.tsx index ca9d26b5..4755ec33 100644 --- a/src/components/moderation/ReportsQueue.tsx +++ b/src/components/moderation/ReportsQueue.tsx @@ -128,7 +128,7 @@ export const ReportsQueue = forwardRef((props, ref) => { if (saved) { return JSON.parse(saved); } - } catch (error) { + } catch (error: unknown) { logger.warn('Failed to load sort config from localStorage'); } return { field: 'created_at', direction: 'asc' as ReportSortDirection }; @@ -153,7 +153,7 @@ export const ReportsQueue = forwardRef((props, ref) => { useEffect(() => { try { localStorage.setItem('reportsQueue_sortConfig', JSON.stringify(sortConfig)); - } catch (error) { + } catch (error: unknown) { logger.warn('Failed to save sort config to localStorage'); } }, [sortConfig]); diff --git a/src/components/privacy/BlockedUsers.tsx b/src/components/privacy/BlockedUsers.tsx index 34c7d107..2a2ddd16 100644 --- a/src/components/privacy/BlockedUsers.tsx +++ b/src/components/privacy/BlockedUsers.tsx @@ -77,7 +77,7 @@ export function BlockedUsers() { action: 'fetch_blocked_users', count: blockedUsersWithProfiles.length }); - } catch (error) { + } catch (error: unknown) { logger.error('Error fetching blocked users', { userId: user.id, action: 'fetch_blocked_users', @@ -134,7 +134,7 @@ export function BlockedUsers() { }); handleSuccess('User unblocked', `You have unblocked @${username}`); - } catch (error) { + } catch (error: unknown) { logger.error('Error unblocking user', { userId: user.id, action: 'unblock_user', diff --git a/src/components/search/SearchResults.tsx b/src/components/search/SearchResults.tsx index d55f10f7..992309bb 100644 --- a/src/components/search/SearchResults.tsx +++ b/src/components/search/SearchResults.tsx @@ -63,7 +63,7 @@ export function SearchResults({ query, onClose }: SearchResultsProps) { ]; setResults(allResults); - } catch (error) { + } catch (error: unknown) { console.error('Search error:', error); } finally { setLoading(false); diff --git a/src/components/settings/EmailChangeDialog.tsx b/src/components/settings/EmailChangeDialog.tsx index fe08c795..9283629f 100644 --- a/src/components/settings/EmailChangeDialog.tsx +++ b/src/components/settings/EmailChangeDialog.tsx @@ -213,7 +213,7 @@ export function EmailChangeDialog({ open, onOpenChange, currentEmail, userId }: ); setStep('success'); - } catch (error) { + } catch (error: unknown) { const errorMsg = getErrorMessage(error); logger.error('Email change failed', { userId, @@ -221,7 +221,12 @@ export function EmailChangeDialog({ open, onOpenChange, currentEmail, userId }: error: errorMsg, }); - if (error.message?.includes('rate limit') || error.status === 429) { + const hasMessage = error instanceof Error || (typeof error === 'object' && error !== null && 'message' in error); + const hasStatus = typeof error === 'object' && error !== null && 'status' in error; + const errorMessage = hasMessage ? (error as { message: string }).message : ''; + const errorStatus = hasStatus ? (error as { status: number }).status : 0; + + if (errorMessage.includes('rate limit') || errorStatus === 429) { handleError( new AppError( 'Please wait a few minutes before trying again.', @@ -230,7 +235,7 @@ export function EmailChangeDialog({ open, onOpenChange, currentEmail, userId }: ), { action: 'Change email', userId, metadata: { currentEmail, newEmail: data.newEmail } } ); - } else if (error.message?.includes('Invalid login credentials')) { + } else if (errorMessage.includes('Invalid login credentials')) { handleError( new AppError( 'The password you entered is incorrect.', diff --git a/src/components/settings/EmailChangeStatus.tsx b/src/components/settings/EmailChangeStatus.tsx index a311d792..2301c4dd 100644 --- a/src/components/settings/EmailChangeStatus.tsx +++ b/src/components/settings/EmailChangeStatus.tsx @@ -50,7 +50,7 @@ export function EmailChangeStatus({ newEmailVerified: emailData.new_email_verified || false }); } - } catch (error) { + } catch (error: unknown) { handleError(error, { action: 'Check verification status' }); } finally { setLoading(false); @@ -77,7 +77,7 @@ export function EmailChangeStatus({ 'Verification emails resent', 'Check your inbox for the verification links.' ); - } catch (error) { + } catch (error: unknown) { handleError(error, { action: 'Resend verification emails' }); } finally { setResending(false); diff --git a/src/components/settings/PasswordUpdateDialog.tsx b/src/components/settings/PasswordUpdateDialog.tsx index 6b8111e1..513f9152 100644 --- a/src/components/settings/PasswordUpdateDialog.tsx +++ b/src/components/settings/PasswordUpdateDialog.tsx @@ -81,7 +81,7 @@ export function PasswordUpdateDialog({ open, onOpenChange, onSuccess }: Password const hasVerifiedTotp = data?.totp?.some(factor => factor.status === 'verified') || false; setHasMFA(hasVerifiedTotp); - } catch (error) { + } catch (error: unknown) { logger.error('Failed to check MFA status', { action: 'check_mfa_status', error: error instanceof Error ? error.message : String(error) diff --git a/src/hooks/moderation/useModerationActions.ts b/src/hooks/moderation/useModerationActions.ts index 0f77db8f..05e1bbec 100644 --- a/src/hooks/moderation/useModerationActions.ts +++ b/src/hooks/moderation/useModerationActions.ts @@ -241,8 +241,8 @@ export function useModerationActions(config: ModerationActionsConfig): Moderatio }); logger.log(`✅ Action ${action} completed for ${item.id}`); - } catch (error) { - logger.error('❌ Error performing action:', error); + } catch (error: unknown) { + logger.error('❌ Error performing action:', { error: getErrorMessage(error) }); toast({ title: 'Error', description: getErrorMessage(error) || `Failed to ${action} content`, @@ -276,8 +276,8 @@ export function useModerationActions(config: ModerationActionsConfig): Moderatio }); logger.log(`✅ Submission ${item.id} deleted`); - } catch (error) { - logger.error('❌ Error deleting submission:', error); + } catch (error: unknown) { + logger.error('❌ Error deleting submission:', { error: getErrorMessage(error) }); toast({ title: 'Error', description: getErrorMessage(error), @@ -308,8 +308,8 @@ export function useModerationActions(config: ModerationActionsConfig): Moderatio }); logger.log(`✅ Submission ${item.id} reset to pending`); - } catch (error) { - logger.error('❌ Error resetting submission:', error); + } catch (error: unknown) { + logger.error('❌ Error resetting submission:', { error: getErrorMessage(error) }); toast({ title: 'Reset Failed', description: getErrorMessage(error), @@ -361,8 +361,8 @@ export function useModerationActions(config: ModerationActionsConfig): Moderatio }); logger.log(`✅ Retried ${failedItems.length} failed items for ${item.id}`); - } catch (error) { - logger.error('❌ Error retrying items:', error); + } catch (error: unknown) { + logger.error('❌ Error retrying items:', { error: getErrorMessage(error) }); toast({ title: 'Retry Failed', description: getErrorMessage(error) || 'Failed to retry items', diff --git a/src/hooks/moderation/useRealtimeSubscriptions.ts b/src/hooks/moderation/useRealtimeSubscriptions.ts index df7496cc..e112cd6a 100644 --- a/src/hooks/moderation/useRealtimeSubscriptions.ts +++ b/src/hooks/moderation/useRealtimeSubscriptions.ts @@ -310,8 +310,8 @@ export function useRealtimeSubscriptions( ); onNewItem(fullItem); - } catch (error) { - logger.error('Error building new item notification:', error); + } catch (error: unknown) { + logger.error('Error building new item notification:', { error: getErrorMessage(error) }); } }, [ filters, diff --git a/src/hooks/useAuth.tsx b/src/hooks/useAuth.tsx index 8365bbc9..b68075e1 100644 --- a/src/hooks/useAuth.tsx +++ b/src/hooks/useAuth.tsx @@ -61,7 +61,7 @@ function AuthProviderComponent({ children }: { children: React.ReactNode }) { } return true; - } catch (error) { + } catch (error: unknown) { authError('[Auth] Session verification error:', error); return false; } @@ -165,7 +165,7 @@ function AuthProviderComponent({ children }: { children: React.ReactNode }) { }, }); } - } catch (error) { + } catch (error: unknown) { authError('Error updating Novu after email confirmation:', error); } finally { novuUpdateTimeoutRef.current = null; diff --git a/src/hooks/useEntityVersions.ts b/src/hooks/useEntityVersions.ts index c1d8a9c1..147bf07a 100644 --- a/src/hooks/useEntityVersions.ts +++ b/src/hooks/useEntityVersions.ts @@ -107,7 +107,7 @@ export function useEntityVersions(entityType: EntityType, entityId: string) { setCurrentVersion(versionsWithProfiles.find(v => v.is_current) || null); setLoading(false); } - } catch (error) { + } catch (error: unknown) { const errorMsg = getErrorMessage(error); console.error('Error fetching versions:', errorMsg); @@ -139,7 +139,7 @@ export function useEntityVersions(entityType: EntityType, entityId: string) { if (error) throw error; return data; - } catch (error) { + } catch (error: unknown) { const errorMsg = getErrorMessage(error); console.error('Error comparing versions:', errorMsg); if (isMountedRef.current) { @@ -171,7 +171,7 @@ export function useEntityVersions(entityType: EntityType, entityId: string) { await fetchVersions(); } return data; - } catch (error) { + } catch (error: unknown) { const errorMsg = getErrorMessage(error); console.error('Error rolling back version:', errorMsg); if (isMountedRef.current) { @@ -193,7 +193,7 @@ export function useEntityVersions(entityType: EntityType, entityId: string) { if (channelRef.current) { try { supabase.removeChannel(channelRef.current); - } catch (error) { + } catch (error: unknown) { console.error('Error removing previous channel:', error); } finally { channelRef.current = null; diff --git a/src/hooks/useModerationQueue.ts b/src/hooks/useModerationQueue.ts index 38581ee0..2d26a0e3 100644 --- a/src/hooks/useModerationQueue.ts +++ b/src/hooks/useModerationQueue.ts @@ -44,7 +44,7 @@ export const useModerationQueue = (config?: UseModerationQueueConfig) => { const releaseInterval = setInterval(async () => { try { await supabase.rpc('release_expired_locks'); - } catch (error) { + } catch (error: unknown) { console.error('Error auto-releasing expired locks:', error); } }, 120000); // 2 minutes @@ -82,7 +82,7 @@ export const useModerationQueue = (config?: UseModerationQueueConfig) => { avgWaitHours: slaData.length > 0 ? totals.avgWaitHours / slaData.length : 0, }); } - } catch (error) { + } catch (error: unknown) { console.error('Error fetching queue stats:', error); } }, [user]); @@ -164,7 +164,7 @@ export const useModerationQueue = (config?: UseModerationQueueConfig) => { } return false; - } catch (error) { + } catch (error: unknown) { console.error('Error extending lock:', error); toast({ title: 'Error', @@ -227,7 +227,7 @@ export const useModerationQueue = (config?: UseModerationQueueConfig) => { } return data; - } catch (error) { + } catch (error: unknown) { console.error('Error releasing lock:', error); // Always show error toasts even in silent mode @@ -273,7 +273,7 @@ export const useModerationQueue = (config?: UseModerationQueueConfig) => { fetchStats(); return true; - } catch (error) { + } catch (error: unknown) { console.error('Error escalating submission:', error); toast({ title: 'Error', @@ -343,7 +343,7 @@ export const useModerationQueue = (config?: UseModerationQueueConfig) => { } return true; - } catch (error) { + } catch (error: unknown) { console.error('Error claiming submission:', error); toast({ title: 'Failed to Claim Submission', @@ -388,7 +388,7 @@ export const useModerationQueue = (config?: UseModerationQueueConfig) => { fetchStats(); return true; - } catch (error) { + } catch (error: unknown) { console.error('Error reassigning submission:', error); toast({ title: 'Error', diff --git a/src/hooks/useModerationStats.ts b/src/hooks/useModerationStats.ts index 5e28e068..71e8b488 100644 --- a/src/hooks/useModerationStats.ts +++ b/src/hooks/useModerationStats.ts @@ -105,7 +105,8 @@ export const useModerationStats = (options: UseModerationStatsOptions = {}) => { openReports: 0, flaggedContent: 0, }); - } catch (error) { + } catch (error: unknown) { + const errorMsg = getErrorMessage(error); console.error('Error fetching moderation stats:', error); } finally { // Only clear loading if it was set diff --git a/src/hooks/usePhotoSubmissionItems.ts b/src/hooks/usePhotoSubmissionItems.ts index 02945a74..fb134959 100644 --- a/src/hooks/usePhotoSubmissionItems.ts +++ b/src/hooks/usePhotoSubmissionItems.ts @@ -62,7 +62,7 @@ export function usePhotoSubmissionItems( if (itemsError) throw itemsError; setPhotos(data || []); - } catch (error) { + } catch (error: unknown) { const errorMsg = getErrorMessage(error); console.error('Error fetching photo submission items:', errorMsg); setError(errorMsg); diff --git a/src/hooks/useSearch.tsx b/src/hooks/useSearch.tsx index 0bf067e4..433afa1b 100644 --- a/src/hooks/useSearch.tsx +++ b/src/hooks/useSearch.tsx @@ -71,13 +71,13 @@ export function useSearch(options: UseSearchOptions = {}) { logger.warn('Recent searches data is not an array, clearing'); localStorage.removeItem('thrillwiki_recent_searches'); } - } catch (parseError) { + } catch (parseError: unknown) { // JSON parse failed, data is corrupted console.error('Failed to parse recent searches from localStorage:', parseError); localStorage.removeItem('thrillwiki_recent_searches'); } } - } catch (error) { + } catch (error: unknown) { // localStorage access failed console.error('Error accessing localStorage:', error); } @@ -181,7 +181,7 @@ export function useSearch(options: UseSearchOptions = {}) { }); setResults(searchResults.slice(0, limit)); - } catch (error) { + } catch (error: unknown) { console.error('Search error:', error); const errorMessage = error instanceof Error ? error.message : 'Failed to search. Please try again.'; setError(errorMessage); diff --git a/src/hooks/useSessionMonitor.ts b/src/hooks/useSessionMonitor.ts index bae810f0..d975d7b6 100644 --- a/src/hooks/useSessionMonitor.ts +++ b/src/hooks/useSessionMonitor.ts @@ -55,7 +55,7 @@ export function useSessionMonitor() { window.location.href = '/auth'; }, 30000); } - } catch (error) { + } catch (error: unknown) { logger.error('Session monitor check failed', { userId: user.id, action: 'session_monitor', diff --git a/src/hooks/useUnitPreferences.ts b/src/hooks/useUnitPreferences.ts index 8347c71f..b8f74271 100644 --- a/src/hooks/useUnitPreferences.ts +++ b/src/hooks/useUnitPreferences.ts @@ -69,7 +69,7 @@ export function useUnitPreferences() { await autoDetectPreferences(); } } - } catch (error) { + } catch (error: unknown) { logger.error('Error loading unit preferences', { userId: user?.id, action: 'load_unit_preferences', @@ -115,7 +115,7 @@ export function useUnitPreferences() { return newPreferences; } - } catch (error) { + } catch (error: unknown) { logger.error('Error auto-detecting location', { userId: user?.id, action: 'auto_detect_location', @@ -149,7 +149,7 @@ export function useUnitPreferences() { } else { localStorage.setItem('unit_preferences', JSON.stringify(updated)); } - } catch (error) { + } catch (error: unknown) { logger.error('Error saving unit preferences', { userId: user?.id, action: 'save_unit_preferences', diff --git a/src/hooks/useUserRole.ts b/src/hooks/useUserRole.ts index 3a53ef35..0d43f45f 100644 --- a/src/hooks/useUserRole.ts +++ b/src/hooks/useUserRole.ts @@ -51,7 +51,7 @@ export function useUserRole() { } else { setPermissions(permissionsData as unknown as UserPermissions); } - } catch (error) { + } catch (error: unknown) { console.error('Error fetching user roles:', error); setRoles([]); setPermissions(null); diff --git a/src/hooks/useUsernameValidation.ts b/src/hooks/useUsernameValidation.ts index 76d54041..1dfaf294 100644 --- a/src/hooks/useUsernameValidation.ts +++ b/src/hooks/useUsernameValidation.ts @@ -37,7 +37,7 @@ export function useUsernameValidation(username: string, currentUsername?: string isChecking: false, error: isAvailable ? null : 'Username is already taken', }); - } catch (error) { + } catch (error: unknown) { setState({ isValid: false, isAvailable: null,