From e74c2acbd4879fa3a19a9242c0e09df823378c48 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Tue, 4 Nov 2025 19:11:24 +0000 Subject: [PATCH] Refactor: Implement full error logging --- src/components/auth/TOTPSetup.tsx | 20 ++----- src/components/contact/ContactForm.tsx | 6 --- src/components/moderation/ProfileManager.tsx | 19 +++++-- src/components/moderation/ReportsQueue.tsx | 8 ++- src/components/privacy/BlockedUsers.tsx | 43 --------------- src/components/reviews/ReviewForm.tsx | 9 ++-- src/components/reviews/ReviewsList.tsx | 8 +-- src/components/settings/DataExportTab.tsx | 3 +- src/components/settings/LocationTab.tsx | 32 +----------- src/components/settings/NotificationsTab.tsx | 34 +----------- .../settings/PasswordUpdateDialog.tsx | 52 +++---------------- 11 files changed, 48 insertions(+), 186 deletions(-) diff --git a/src/components/auth/TOTPSetup.tsx b/src/components/auth/TOTPSetup.tsx index 932c754b..cffce2d6 100644 --- a/src/components/auth/TOTPSetup.tsx +++ b/src/components/auth/TOTPSetup.tsx @@ -5,7 +5,7 @@ import { Label } from '@/components/ui/label'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Alert, AlertDescription } from '@/components/ui/alert'; import { Badge } from '@/components/ui/badge'; -import { handleError, handleSuccess, handleInfo, AppError, getErrorMessage } from '@/lib/errorHandler'; +import { handleError, handleSuccess, handleInfo, handleNonCriticalError, AppError, getErrorMessage } from '@/lib/errorHandler'; import { logger } from '@/lib/logger'; import { useAuth } from '@/hooks/useAuth'; import { useRequireMFA } from '@/hooks/useRequireMFA'; @@ -51,10 +51,10 @@ export function TOTPSetup() { })); setFactors(totpFactors); } catch (error: unknown) { - logger.error('Failed to fetch TOTP factors', { + handleNonCriticalError(error, { + action: 'Fetch TOTP factors', userId: user?.id, - action: 'fetch_totp_factors', - error: getErrorMessage(error) + metadata: { context: 'initial_load' } }); } }; @@ -76,11 +76,6 @@ export function TOTPSetup() { setFactorId(data.id); setEnrolling(true); } catch (error: unknown) { - logger.error('Failed to start TOTP enrollment', { - userId: user?.id, - action: 'totp_enroll_start', - error: getErrorMessage(error) - }); handleError( new AppError( getErrorMessage(error) || 'Failed to start TOTP enrollment', @@ -148,13 +143,6 @@ export function TOTPSetup() { }, 2000); } } catch (error: unknown) { - logger.error('TOTP verification failed', { - userId: user?.id, - action: 'totp_verify', - error: getErrorMessage(error), - factorId - }); - handleError( new AppError( getErrorMessage(error) || 'Invalid verification code. Please try again.', diff --git a/src/components/contact/ContactForm.tsx b/src/components/contact/ContactForm.tsx index 4db68f7d..05593662 100644 --- a/src/components/contact/ContactForm.tsx +++ b/src/components/contact/ContactForm.tsx @@ -148,13 +148,7 @@ export function ContactForm() { setCaptchaToken(''); setCaptchaKey((prev) => prev + 1); - logger.info('Contact form submitted successfully', { - submissionId: result?.submissionId, - }); } catch (error) { - logger.error('Failed to submit contact form', { - error: error instanceof Error ? error.message : String(error), - }); handleError(error, { action: 'submit_contact_form', metadata: { category: data.category }, diff --git a/src/components/moderation/ProfileManager.tsx b/src/components/moderation/ProfileManager.tsx index 417f0b4d..ed1bbcb4 100644 --- a/src/components/moderation/ProfileManager.tsx +++ b/src/components/moderation/ProfileManager.tsx @@ -12,8 +12,7 @@ import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; -import { handleError, handleSuccess, getErrorMessage } from '@/lib/errorHandler'; -import { logger } from '@/lib/logger'; +import { handleError, handleSuccess, handleNonCriticalError, getErrorMessage } from '@/lib/errorHandler'; interface UserProfile { id: string; @@ -131,7 +130,13 @@ export function ProfileManager() { } }); - if (logError) logger.error('Failed to log admin action', { error: getErrorMessage(logError) }); + if (logError) { + handleNonCriticalError(logError, { + action: 'Log admin action (ban/unban)', + userId: user?.id, + metadata: { targetUserId, ban, banReason } + }); + } handleSuccess( 'Success', @@ -211,7 +216,13 @@ export function ProfileManager() { _details: { role: newRole, previous_roles: currentRoles } }); - if (logError) logger.error('Failed to log admin action', { error: getErrorMessage(logError) }); + if (logError) { + handleNonCriticalError(logError, { + action: 'Log admin action (role change)', + userId: user?.id, + metadata: { targetUserId, newRole, previousRoles: currentRoles } + }); + } handleSuccess('Success', 'User role updated successfully.'); diff --git a/src/components/moderation/ReportsQueue.tsx b/src/components/moderation/ReportsQueue.tsx index 8865b1c4..d64bb540 100644 --- a/src/components/moderation/ReportsQueue.tsx +++ b/src/components/moderation/ReportsQueue.tsx @@ -23,7 +23,7 @@ import { useAdminSettings } from '@/hooks/useAdminSettings'; import { useAuth } from '@/hooks/useAuth'; import { useIsMobile } from '@/hooks/use-mobile'; import { smartMergeArray } from '@/lib/smartStateUpdate'; -import { handleError, handleSuccess } from '@/lib/errorHandler'; +import { handleError, handleSuccess, handleNonCriticalError } from '@/lib/errorHandler'; // Type-safe reported content interfaces interface ReportedReview { @@ -383,7 +383,11 @@ export const ReportsQueue = forwardRef((props, ref) => { } }); } catch (auditError) { - logger.error('Failed to log report action audit', { error: auditError }); + handleNonCriticalError(auditError, { + action: 'Log report action audit', + userId: user?.id, + metadata: { reportId, action } + }); } } diff --git a/src/components/privacy/BlockedUsers.tsx b/src/components/privacy/BlockedUsers.tsx index eeb1e9db..4f4e3818 100644 --- a/src/components/privacy/BlockedUsers.tsx +++ b/src/components/privacy/BlockedUsers.tsx @@ -32,12 +32,6 @@ export function BlockedUsers() { .order('created_at', { ascending: false }); if (blocksError) { - logger.error('Failed to fetch user blocks', { - userId: user.id, - action: 'fetch_blocked_users', - error: blocksError.message, - errorCode: blocksError.code - }); throw blocksError; } @@ -54,12 +48,6 @@ export function BlockedUsers() { .in('user_id', blockedIds); if (profilesError) { - logger.error('Failed to fetch blocked user profiles', { - userId: user.id, - action: 'fetch_blocked_user_profiles', - error: profilesError.message, - errorCode: profilesError.code - }); throw profilesError; } @@ -73,18 +61,7 @@ export function BlockedUsers() { setBlockedUsers(blockedUsersWithProfiles as UserBlock[]); - logger.info('Blocked users fetched successfully', { - userId: user.id, - action: 'fetch_blocked_users', - count: blockedUsersWithProfiles.length - }); } catch (error: unknown) { - logger.error('Error fetching blocked users', { - userId: user.id, - action: 'fetch_blocked_users', - error: error instanceof Error ? error.message : String(error) - }); - handleError(error, { action: 'Load blocked users', userId: user.id @@ -104,13 +81,6 @@ export function BlockedUsers() { .eq('id', blockId); if (error) { - logger.error('Failed to unblock user', { - userId: user.id, - action: 'unblock_user', - targetUserId: blockedUserId, - error: error.message, - errorCode: error.code - }); throw error; } @@ -128,21 +98,8 @@ export function BlockedUsers() { setBlockedUsers(prev => prev.filter(block => block.id !== blockId)); - logger.info('User unblocked successfully', { - userId: user.id, - action: 'unblock_user', - targetUserId: blockedUserId - }); - handleSuccess('User unblocked', `You have unblocked @${username}`); } catch (error: unknown) { - logger.error('Error unblocking user', { - userId: user.id, - action: 'unblock_user', - targetUserId: blockedUserId, - error: error instanceof Error ? error.message : String(error) - }); - handleError(error, { action: 'Unblock user', userId: user.id, diff --git a/src/components/reviews/ReviewForm.tsx b/src/components/reviews/ReviewForm.tsx index e983d869..9a24f0d4 100644 --- a/src/components/reviews/ReviewForm.tsx +++ b/src/components/reviews/ReviewForm.tsx @@ -15,8 +15,7 @@ import { toast } from '@/hooks/use-toast'; import { PhotoUpload } from '@/components/upload/PhotoUpload'; import { StarRating } from './StarRating'; import { toDateOnly, parseDateOnly } from '@/lib/dateUtils'; -import { getErrorMessage } from '@/lib/errorHandler'; -import { logger } from '@/lib/logger'; +import { getErrorMessage, handleNonCriticalError } from '@/lib/errorHandler'; const reviewSchema = z.object({ rating: z.number().min(0.5).max(5).multipleOf(0.5), title: z.string().optional(), @@ -109,7 +108,11 @@ export function ReviewForm({ .insert(photoRecords); if (photosError) { - logger.error('Failed to insert review photos', { error: getErrorMessage(photosError) }); + handleNonCriticalError(photosError, { + action: 'Insert review photos', + userId: user?.id, + metadata: { reviewId: review.id, photoCount: photos.length } + }); // Don't throw - review is already created } } diff --git a/src/components/reviews/ReviewsList.tsx b/src/components/reviews/ReviewsList.tsx index 4da21619..7c58f6ca 100644 --- a/src/components/reviews/ReviewsList.tsx +++ b/src/components/reviews/ReviewsList.tsx @@ -6,8 +6,7 @@ import { Star, ThumbsUp, Calendar, MapPin } from 'lucide-react'; import { supabase } from '@/lib/supabaseClient'; import { ReportButton } from '@/components/moderation/ReportButton'; import { StarRating } from './StarRating'; -import { getErrorMessage } from '@/lib/errorHandler'; -import { logger } from '@/lib/logger'; +import { getErrorMessage, handleNonCriticalError } from '@/lib/errorHandler'; interface ReviewWithProfile { id: string; @@ -65,7 +64,10 @@ export function ReviewsList({ entityType, entityId, entityName }: ReviewsListPro const { data } = await query; setReviews((data || []) as ReviewWithProfile[]); } catch (error: unknown) { - logger.error('Failed to fetch reviews', { error: getErrorMessage(error), entityType, entityId }); + handleNonCriticalError(error, { + action: 'Fetch reviews', + metadata: { entityType, entityId } + }); } finally { setLoading(false); } diff --git a/src/components/settings/DataExportTab.tsx b/src/components/settings/DataExportTab.tsx index d37d0d3f..6ee4d64a 100644 --- a/src/components/settings/DataExportTab.tsx +++ b/src/components/settings/DataExportTab.tsx @@ -9,8 +9,7 @@ import { Label } from '@/components/ui/label'; import { useAuth } from '@/hooks/useAuth'; import { useProfile } from '@/hooks/useProfile'; import { supabase } from '@/lib/supabaseClient'; -import { handleError, handleSuccess, AppError } from '@/lib/errorHandler'; -import { logger } from '@/lib/logger'; +import { handleError, handleSuccess, handleNonCriticalError, AppError } from '@/lib/errorHandler'; import { Download, Activity, BarChart3, AlertCircle, Clock } from 'lucide-react'; import type { UserStatistics, diff --git a/src/components/settings/LocationTab.tsx b/src/components/settings/LocationTab.tsx index 9a64afe9..f48c315b 100644 --- a/src/components/settings/LocationTab.tsx +++ b/src/components/settings/LocationTab.tsx @@ -14,8 +14,7 @@ import { useAuth } from '@/hooks/useAuth'; import { useProfile } from '@/hooks/useProfile'; import { useUnitPreferences } from '@/hooks/useUnitPreferences'; import { supabase } from '@/lib/supabaseClient'; -import { handleError, handleSuccess, AppError } from '@/lib/errorHandler'; -import { logger } from '@/lib/logger'; +import { handleError, handleSuccess, handleNonCriticalError, AppError } from '@/lib/errorHandler'; import { MapPin, Calendar, Accessibility, Ruler } from 'lucide-react'; import type { LocationFormData, AccessibilityOptions, ParkOption } from '@/types/location'; import { @@ -75,12 +74,6 @@ export function LocationTab() { .order('name'); if (error) { - logger.error('Failed to fetch parks list', { - userId: user.id, - action: 'fetch_parks', - error: error.message, - errorCode: error.code - }); throw error; } @@ -198,12 +191,6 @@ export function LocationTab() { .eq('user_id', user.id); if (profileError) { - logger.error('Failed to update profile', { - userId: user.id, - action: 'update_profile_location', - error: profileError.message, - errorCode: profileError.code - }); throw profileError; } @@ -216,12 +203,6 @@ export function LocationTab() { .eq('user_id', user.id); if (accessibilityError) { - logger.error('Failed to update accessibility preferences', { - userId: user.id, - action: 'update_accessibility_preferences', - error: accessibilityError.message, - errorCode: accessibilityError.code - }); throw accessibilityError; } @@ -246,22 +227,11 @@ export function LocationTab() { await refreshProfile(); - logger.info('Location and info settings updated', { - userId: user.id, - action: 'update_location_info' - }); - handleSuccess( 'Settings saved', 'Your location, personal information, accessibility, and unit preferences have been updated.' ); } catch (error: unknown) { - logger.error('Error saving location settings', { - userId: user.id, - action: 'save_location_settings', - error: error instanceof Error ? error.message : String(error) - }); - if (error instanceof z.ZodError) { handleError( new AppError( diff --git a/src/components/settings/NotificationsTab.tsx b/src/components/settings/NotificationsTab.tsx index 8535d8ff..02f9d47a 100644 --- a/src/components/settings/NotificationsTab.tsx +++ b/src/components/settings/NotificationsTab.tsx @@ -9,8 +9,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@ import { Separator } from "@/components/ui/separator"; import { Badge } from "@/components/ui/badge"; import { Skeleton } from "@/components/ui/skeleton"; -import { handleError, handleSuccess, handleInfo } from "@/lib/errorHandler"; -import { logger } from "@/lib/logger"; +import { handleError, handleSuccess, handleInfo, handleNonCriticalError } from "@/lib/errorHandler"; import { notificationService } from "@/lib/notificationService"; import type { NotificationPreferences, @@ -53,18 +52,7 @@ export function NotificationsTab() { setWorkflowPreferences(preferences.workflowPreferences); setFrequencySettings(preferences.frequencySettings); } - - logger.info('Notification preferences loaded', { - action: 'load_notification_preferences', - userId: user.id - }); } catch (error: unknown) { - logger.error('Failed to load notification preferences', { - action: 'load_notification_preferences', - userId: user.id, - error: error instanceof Error ? error.message : String(error) - }); - handleError(error, { action: 'Load notification preferences', userId: user.id @@ -92,20 +80,8 @@ export function NotificationsTab() { if (Object.keys(initialPrefs).length > 0) { setWorkflowPreferences((prev) => ({ ...prev, ...initialPrefs })); } - - logger.info('Notification templates loaded', { - action: 'load_notification_templates', - userId: user.id, - count: templateData.length - }); } catch (error: unknown) { - logger.error('Failed to load notification templates', { - action: 'load_notification_templates', - userId: user.id, - error: error instanceof Error ? error.message : String(error) - }); - - handleError(error, { + handleNonCriticalError(error, { action: 'Load notification templates', userId: user.id }); @@ -185,12 +161,6 @@ export function NotificationsTab() { ); } } catch (error: unknown) { - logger.error('Error requesting push permission', { - action: 'request_push_permission', - userId: user?.id, - error: error instanceof Error ? error.message : String(error) - }); - handleError(error, { action: 'Enable push notifications', userId: user?.id diff --git a/src/components/settings/PasswordUpdateDialog.tsx b/src/components/settings/PasswordUpdateDialog.tsx index 860a3eec..718dbb86 100644 --- a/src/components/settings/PasswordUpdateDialog.tsx +++ b/src/components/settings/PasswordUpdateDialog.tsx @@ -13,7 +13,7 @@ import { import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; -import { handleError, handleSuccess, AppError, getErrorMessage } from '@/lib/errorHandler'; +import { handleError, handleSuccess, handleNonCriticalError, AppError, getErrorMessage } from '@/lib/errorHandler'; import { logger } from '@/lib/logger'; import { supabase } from '@/lib/supabaseClient'; import { Loader2, Shield, CheckCircle2 } from 'lucide-react'; @@ -82,9 +82,10 @@ export function PasswordUpdateDialog({ open, onOpenChange, onSuccess }: Password const hasVerifiedTotp = data?.totp?.some(factor => factor.status === 'verified') || false; setHasMFA(hasVerifiedTotp); } catch (error: unknown) { - logger.error('Failed to check MFA status', { - action: 'check_mfa_status', - error: error instanceof Error ? error.message : String(error) + handleNonCriticalError(error, { + action: 'Check MFA status', + userId, + metadata: { context: 'password_change_dialog' } }); } }; @@ -142,13 +143,6 @@ export function PasswordUpdateDialog({ open, onOpenChange, onSuccess }: Password setCaptchaToken(''); setCaptchaKey(prev => prev + 1); - logger.error('Password authentication failed', { - userId, - action: 'password_change_auth', - error: signInError.message, - errorCode: signInError.code - }); - throw signInError; } @@ -169,18 +163,6 @@ export function PasswordUpdateDialog({ open, onOpenChange, onSuccess }: Password await updatePasswordWithNonce(data.newPassword, generatedNonce); } } catch (error: unknown) { - const errorDetails = isErrorWithCode(error) ? { - errorCode: error.code, - errorStatus: error.status - } : {}; - - logger.error('Password change failed', { - userId, - action: 'password_change', - error: getErrorMessage(error), - ...errorDetails - }); - const errorMessage = getErrorMessage(error); const errorStatus = isErrorWithCode(error) ? error.status : undefined; @@ -238,12 +220,6 @@ export function PasswordUpdateDialog({ open, onOpenChange, onSuccess }: Password }); if (challengeError) { - logger.error('MFA challenge creation failed', { - userId, - action: 'password_change_mfa_challenge', - error: challengeError.message, - errorCode: challengeError.code - }); throw challengeError; } @@ -255,24 +231,12 @@ export function PasswordUpdateDialog({ open, onOpenChange, onSuccess }: Password }); if (verifyError) { - logger.error('MFA verification failed', { - userId, - action: 'password_change_mfa', - error: verifyError.message, - errorCode: verifyError.code - }); throw verifyError; } // TOTP verified, now update password await updatePasswordWithNonce(newPassword, nonce); } catch (error: unknown) { - logger.error('MFA verification failed', { - userId, - action: 'password_change_mfa', - error: getErrorMessage(error) - }); - handleError( new AppError( getErrorMessage(error) || 'Invalid authentication code', @@ -325,10 +289,10 @@ export function PasswordUpdateDialog({ open, onOpenChange, onSuccess }: Password user.id ); } catch (notifError) { - logger.error('Failed to send password change notification', { + handleNonCriticalError(notifError, { + action: 'Send password change notification', userId: user!.id, - action: 'password_change_notification', - error: getErrorMessage(notifError) + metadata: { context: 'post_password_change' } }); // Don't fail the password update if notification fails }