mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-23 20:11:12 -05:00
Refactor: Implement logging and JSONB cleanup
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { Analytics } from "@vercel/analytics/react";
|
||||
import { Component, ReactNode } from "react";
|
||||
import { logger } from "@/lib/logger";
|
||||
|
||||
class AnalyticsErrorBoundary extends Component<
|
||||
{ children: ReactNode },
|
||||
@@ -16,7 +17,7 @@ class AnalyticsErrorBoundary extends Component<
|
||||
|
||||
componentDidCatch(error: Error) {
|
||||
// Silently fail - analytics should never break the app
|
||||
console.info('[Analytics] Failed to load, continuing without analytics');
|
||||
logger.info('Analytics failed to load, continuing without analytics', { error: error.message });
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { UserTopList, UserTopListItem, Park, Ride, Company } from "@/types/datab
|
||||
import { supabase } from "@/integrations/supabase/client";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { handleError } from "@/lib/errorHandler";
|
||||
|
||||
interface ListDisplayProps {
|
||||
list: UserTopList;
|
||||
@@ -31,7 +32,10 @@ export function ListDisplay({ list }: ListDisplayProps) {
|
||||
.order("position", { ascending: true });
|
||||
|
||||
if (itemsError) {
|
||||
console.error("Error fetching items:", itemsError);
|
||||
handleError(itemsError, {
|
||||
action: 'Fetch List Items',
|
||||
metadata: { listId: list.id }
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { Plus, Trash2, Edit, Eye, EyeOff } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
import { ListItemEditor } from "./ListItemEditor";
|
||||
import { ListDisplay } from "./ListDisplay";
|
||||
import { handleError } from "@/lib/errorHandler";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -62,8 +63,10 @@ export function UserListManager() {
|
||||
.order("created_at", { ascending: false });
|
||||
|
||||
if (error) {
|
||||
toast.error("Failed to load lists");
|
||||
console.error(error);
|
||||
handleError(error, {
|
||||
action: 'Load User Lists',
|
||||
userId: user.id
|
||||
});
|
||||
} else {
|
||||
// Map Supabase data to UserTopList interface
|
||||
const mappedLists: UserTopList[] = (data || []).map((list: any) => ({
|
||||
@@ -101,8 +104,11 @@ export function UserListManager() {
|
||||
.single();
|
||||
|
||||
if (error) {
|
||||
toast.error("Failed to create list");
|
||||
console.error(error);
|
||||
handleError(error, {
|
||||
action: 'Create List',
|
||||
userId: user.id,
|
||||
metadata: { title: newListTitle }
|
||||
});
|
||||
} else {
|
||||
toast.success("List created successfully");
|
||||
const newList: UserTopList = {
|
||||
@@ -132,8 +138,11 @@ export function UserListManager() {
|
||||
.eq("id", listId);
|
||||
|
||||
if (error) {
|
||||
toast.error("Failed to delete list");
|
||||
console.error(error);
|
||||
handleError(error, {
|
||||
action: 'Delete List',
|
||||
userId: user?.id,
|
||||
metadata: { listId }
|
||||
});
|
||||
} else {
|
||||
toast.success("List deleted");
|
||||
setLists(lists.filter(l => l.id !== listId));
|
||||
@@ -147,8 +156,11 @@ export function UserListManager() {
|
||||
.eq("id", list.id);
|
||||
|
||||
if (error) {
|
||||
toast.error("Failed to update list");
|
||||
console.error(error);
|
||||
handleError(error, {
|
||||
action: 'Toggle List Visibility',
|
||||
userId: user?.id,
|
||||
metadata: { listId: list.id }
|
||||
});
|
||||
} else {
|
||||
toast.success(`List is now ${!list.is_public ? "public" : "private"}`);
|
||||
setLists(lists.map(l =>
|
||||
|
||||
@@ -72,7 +72,6 @@ export const QueueItemActions = memo(({
|
||||
() => {
|
||||
// Extra guard against race conditions
|
||||
if (actionLoading === item.id) {
|
||||
console.warn('⚠️ Action already in progress, ignoring duplicate request');
|
||||
return;
|
||||
}
|
||||
onApprove(item, 'approved', notes[item.id]);
|
||||
@@ -84,7 +83,6 @@ export const QueueItemActions = memo(({
|
||||
const handleReject = useDebouncedCallback(
|
||||
() => {
|
||||
if (actionLoading === item.id) {
|
||||
console.warn('⚠️ Action already in progress, ignoring duplicate request');
|
||||
return;
|
||||
}
|
||||
onApprove(item, 'rejected', notes[item.id]);
|
||||
@@ -128,7 +126,6 @@ export const QueueItemActions = memo(({
|
||||
const handleReverseApprove = useDebouncedCallback(
|
||||
() => {
|
||||
if (actionLoading === item.id) {
|
||||
console.warn('⚠️ Action already in progress, ignoring duplicate request');
|
||||
return;
|
||||
}
|
||||
onApprove(item, 'approved', notes[`reverse-${item.id}`]);
|
||||
@@ -140,7 +137,6 @@ export const QueueItemActions = memo(({
|
||||
const handleReverseReject = useDebouncedCallback(
|
||||
() => {
|
||||
if (actionLoading === item.id) {
|
||||
console.warn('⚠️ Action already in progress, ignoring duplicate request');
|
||||
return;
|
||||
}
|
||||
onApprove(item, 'rejected', notes[`reverse-${item.id}`]);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { logger } from '@/lib/logger';
|
||||
|
||||
interface UserAvatarProps {
|
||||
avatarUrl?: string | null;
|
||||
@@ -43,7 +44,7 @@ export function UserAvatar({
|
||||
}, [avatarUrl]);
|
||||
|
||||
const handleImageError = () => {
|
||||
console.warn('[UserAvatar] Image load failed:', imageUrl, 'Retry count:', retryCount);
|
||||
logger.debug('UserAvatar image load failed', { imageUrl, retryCount });
|
||||
|
||||
if (retryCount < MAX_RETRIES && avatarUrl) {
|
||||
// Add cache-busting parameter and retry
|
||||
@@ -52,19 +53,19 @@ export function UserAvatar({
|
||||
? `${avatarUrl}&retry=${retryCount + 1}&t=${Date.now()}`
|
||||
: `${avatarUrl}${cacheBuster}`;
|
||||
|
||||
console.log('[UserAvatar] Retrying with cache buster:', urlWithCacheBuster);
|
||||
logger.debug('UserAvatar retrying with cache buster', { urlWithCacheBuster });
|
||||
setRetryCount(prev => prev + 1);
|
||||
setImageUrl(urlWithCacheBuster);
|
||||
} else {
|
||||
// All retries exhausted, show fallback
|
||||
console.warn('[UserAvatar] All retries exhausted, showing fallback');
|
||||
logger.debug('UserAvatar all retries exhausted, showing fallback');
|
||||
setHasError(true);
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleImageLoad = () => {
|
||||
console.log('[UserAvatar] Image loaded successfully:', imageUrl);
|
||||
logger.debug('UserAvatar image loaded successfully', { imageUrl });
|
||||
setIsLoading(false);
|
||||
setHasError(false);
|
||||
};
|
||||
|
||||
@@ -522,7 +522,6 @@ export function PhotoUpload({
|
||||
alt={`Existing photo ${index + 1}`}
|
||||
className="w-full aspect-square object-cover rounded-lg border"
|
||||
onError={(e) => {
|
||||
console.error('Failed to load existing image:', url);
|
||||
e.currentTarget.src = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiBmaWxsPSIjZjNmNGY2Ii8+CjxwYXRoIGQ9Im0xNSAxMi0zLTMtMy4wMDEgM0w2IDlsNi02aDZ2NloiIGZpbGw9IiM5Y2EzYWYiLz4KPC9zdmc+';
|
||||
}}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user