mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 12:31:26 -05:00
Remove debug console logs
This commit is contained in:
@@ -76,7 +76,6 @@ export function AuthButtons() {
|
|||||||
src={profile?.avatar_url || undefined}
|
src={profile?.avatar_url || undefined}
|
||||||
alt={profile?.display_name || profile?.username || user.email || 'User avatar'}
|
alt={profile?.display_name || profile?.username || user.email || 'User avatar'}
|
||||||
onError={(e) => {
|
onError={(e) => {
|
||||||
console.warn('[Avatar] Failed to load image:', profile?.avatar_url);
|
|
||||||
e.currentTarget.src = ''; // Force fallback
|
e.currentTarget.src = ''; // Force fallback
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -99,8 +99,6 @@ export function AuthModal({ open, onOpenChange, defaultTab = 'signin' }: AuthMod
|
|||||||
const postAuthResult = await handlePostAuthFlow(data.session, 'password');
|
const postAuthResult = await handlePostAuthFlow(data.session, 'password');
|
||||||
|
|
||||||
if (postAuthResult.success && postAuthResult.data.shouldRedirect) {
|
if (postAuthResult.success && postAuthResult.data.shouldRedirect) {
|
||||||
console.log('[AuthModal] MFA step-up required');
|
|
||||||
|
|
||||||
// Get the TOTP factor ID
|
// Get the TOTP factor ID
|
||||||
const { data: factors } = await supabase.auth.mfa.listFactors();
|
const { data: factors } = await supabase.auth.mfa.listFactors();
|
||||||
const totpFactor = factors?.totp?.find(f => f.status === 'verified');
|
const totpFactor = factors?.totp?.find(f => f.status === 'verified');
|
||||||
|
|||||||
@@ -125,7 +125,6 @@ export function TOTPSetup() {
|
|||||||
const isOAuthUser = authMethod === 'oauth';
|
const isOAuthUser = authMethod === 'oauth';
|
||||||
|
|
||||||
if (isOAuthUser) {
|
if (isOAuthUser) {
|
||||||
console.log('[TOTPSetup] OAuth user enrolled MFA, triggering step-up...');
|
|
||||||
setStepUpRequired(true, window.location.pathname);
|
setStepUpRequired(true, window.location.pathname);
|
||||||
navigate('/auth/mfa-step-up');
|
navigate('/auth/mfa-step-up');
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -19,69 +19,36 @@ export function PhotoSubmissionDisplay({ submissionId }: PhotoSubmissionDisplayP
|
|||||||
}, [submissionId]);
|
}, [submissionId]);
|
||||||
|
|
||||||
const fetchPhotos = async () => {
|
const fetchPhotos = async () => {
|
||||||
console.log('🖼️ PhotoSubmissionDisplay: Starting fetch for submission:', submissionId);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Check user auth and roles
|
|
||||||
const { data: session } = await supabase.auth.getSession();
|
|
||||||
const userId = session?.session?.user?.id;
|
|
||||||
console.log('👤 Current user ID:', userId);
|
|
||||||
|
|
||||||
if (userId) {
|
|
||||||
const { data: roles } = await supabase
|
|
||||||
.from('user_roles')
|
|
||||||
.select('role')
|
|
||||||
.eq('user_id', userId);
|
|
||||||
console.log('👤 Current user roles:', roles);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 1: Get photo_submission_id from submission_id
|
// Step 1: Get photo_submission_id from submission_id
|
||||||
console.log('📸 Step 1: Querying photo_submissions table...');
|
|
||||||
const { data: photoSubmission, error: photoSubmissionError } = await supabase
|
const { data: photoSubmission, error: photoSubmissionError } = await supabase
|
||||||
.from('photo_submissions')
|
.from('photo_submissions')
|
||||||
.select('id, entity_type, title')
|
.select('id, entity_type, title')
|
||||||
.eq('submission_id', submissionId)
|
.eq('submission_id', submissionId)
|
||||||
.maybeSingle();
|
.maybeSingle();
|
||||||
|
|
||||||
console.log('📸 Photo submission query result:', {
|
|
||||||
photoSubmission,
|
|
||||||
error: photoSubmissionError
|
|
||||||
});
|
|
||||||
|
|
||||||
if (photoSubmissionError) {
|
if (photoSubmissionError) {
|
||||||
console.error('❌ Error fetching photo_submission:', photoSubmissionError);
|
|
||||||
throw photoSubmissionError;
|
throw photoSubmissionError;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!photoSubmission) {
|
if (!photoSubmission) {
|
||||||
console.log('⚠️ No photo_submission found for submission_id:', submissionId);
|
|
||||||
setPhotos([]);
|
setPhotos([]);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('✅ Found photo_submission ID:', photoSubmission.id);
|
|
||||||
|
|
||||||
// Step 2: Get photo items using photo_submission_id
|
// Step 2: Get photo items using photo_submission_id
|
||||||
console.log('🖼️ Step 2: Querying photo_submission_items table...');
|
|
||||||
const { data, error } = await supabase
|
const { data, error } = await supabase
|
||||||
.from('photo_submission_items')
|
.from('photo_submission_items')
|
||||||
.select('*')
|
.select('*')
|
||||||
.eq('photo_submission_id', photoSubmission.id)
|
.eq('photo_submission_id', photoSubmission.id)
|
||||||
.order('order_index');
|
.order('order_index');
|
||||||
|
|
||||||
console.log('🖼️ Photo items query result:', {
|
|
||||||
itemCount: data?.length,
|
|
||||||
error
|
|
||||||
});
|
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error('❌ Error fetching photo_submission_items:', error);
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
setPhotos(data || []);
|
setPhotos(data || []);
|
||||||
console.log(`✅ Successfully loaded ${data?.length || 0} photos`);
|
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMsg = getErrorMessage(error);
|
const errorMsg = getErrorMessage(error);
|
||||||
console.error('❌ PhotoSubmissionDisplay error:', errorMsg);
|
console.error('❌ PhotoSubmissionDisplay error:', errorMsg);
|
||||||
|
|||||||
@@ -27,18 +27,15 @@ export const QueueSortControls = ({
|
|||||||
const validFields: SortField[] = ['created_at', 'submission_type', 'status'];
|
const validFields: SortField[] = ['created_at', 'submission_type', 'status'];
|
||||||
|
|
||||||
if (!validFields.includes(value as SortField)) {
|
if (!validFields.includes(value as SortField)) {
|
||||||
console.warn('⚠️ [SORT] Invalid sort field:', value);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const field = value as SortField;
|
const field = value as SortField;
|
||||||
console.log('🔄 [SORT] Field change:', { from: sortConfig.field, to: field });
|
|
||||||
onSortChange({ ...sortConfig, field });
|
onSortChange({ ...sortConfig, field });
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDirectionToggle = () => {
|
const handleDirectionToggle = () => {
|
||||||
const newDirection = sortConfig.direction === 'asc' ? 'desc' : 'asc';
|
const newDirection = sortConfig.direction === 'asc' ? 'desc' : 'asc';
|
||||||
console.log('🔄 [SORT] Direction toggle:', { from: sortConfig.direction, to: newDirection });
|
|
||||||
onSortChange({
|
onSortChange({
|
||||||
...sortConfig,
|
...sortConfig,
|
||||||
direction: newDirection
|
direction: newDirection
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { Card, CardContent, CardHeader } from '@/components/ui/card';
|
|||||||
import { Textarea } from '@/components/ui/textarea';
|
import { Textarea } from '@/components/ui/textarea';
|
||||||
import { Label } from '@/components/ui/label';
|
import { Label } from '@/components/ui/label';
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||||
|
import { logger } from '@/lib/logger';
|
||||||
import {
|
import {
|
||||||
Pagination,
|
Pagination,
|
||||||
PaginationContent,
|
PaginationContent,
|
||||||
@@ -128,7 +129,7 @@ export const ReportsQueue = forwardRef<ReportsQueueRef>((props, ref) => {
|
|||||||
return JSON.parse(saved);
|
return JSON.parse(saved);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn('Failed to load sort config from localStorage:', error);
|
logger.warn('Failed to load sort config from localStorage');
|
||||||
}
|
}
|
||||||
return { field: 'created_at', direction: 'asc' as ReportSortDirection };
|
return { field: 'created_at', direction: 'asc' as ReportSortDirection };
|
||||||
});
|
});
|
||||||
@@ -153,7 +154,7 @@ export const ReportsQueue = forwardRef<ReportsQueueRef>((props, ref) => {
|
|||||||
try {
|
try {
|
||||||
localStorage.setItem('reportsQueue_sortConfig', JSON.stringify(sortConfig));
|
localStorage.setItem('reportsQueue_sortConfig', JSON.stringify(sortConfig));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn('Failed to save sort config to localStorage:', error);
|
logger.warn('Failed to save sort config to localStorage');
|
||||||
}
|
}
|
||||||
}, [sortConfig]);
|
}, [sortConfig]);
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { Skeleton } from '@/components/ui/skeleton';
|
|||||||
import { Alert, AlertDescription } from '@/components/ui/alert';
|
import { Alert, AlertDescription } from '@/components/ui/alert';
|
||||||
import { AlertCircle, Loader2 } from 'lucide-react';
|
import { AlertCircle, Loader2 } from 'lucide-react';
|
||||||
import type { SubmissionItemData } from '@/types/submissions';
|
import type { SubmissionItemData } from '@/types/submissions';
|
||||||
|
import { logger } from '@/lib/logger';
|
||||||
|
|
||||||
interface SubmissionItemsListProps {
|
interface SubmissionItemsListProps {
|
||||||
submissionId: string;
|
submissionId: string;
|
||||||
@@ -54,7 +55,7 @@ export const SubmissionItemsList = memo(function SubmissionItemsList({
|
|||||||
.eq('submission_id', submissionId);
|
.eq('submission_id', submissionId);
|
||||||
|
|
||||||
if (photoError) {
|
if (photoError) {
|
||||||
console.warn('Error checking photo submissions:', photoError);
|
logger.warn('Error checking photo submissions:', photoError);
|
||||||
}
|
}
|
||||||
|
|
||||||
setItems((itemsData || []) as SubmissionItemData[]);
|
setItems((itemsData || []) as SubmissionItemData[]);
|
||||||
|
|||||||
@@ -85,7 +85,6 @@ export function SearchResults({ query, onClose }: SearchResultsProps) {
|
|||||||
break;
|
break;
|
||||||
case 'company':
|
case 'company':
|
||||||
// Navigate to manufacturer page when implemented
|
// Navigate to manufacturer page when implemented
|
||||||
console.log('Company clicked:', result.data);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -72,9 +72,7 @@ export function PrivacyTab() {
|
|||||||
...parseResult.data
|
...parseResult.data
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.warn('Invalid privacy settings, reinitializing with defaults', {
|
logger.warn('Invalid privacy settings, reinitializing with defaults');
|
||||||
errors: parseResult.error.issues
|
|
||||||
});
|
|
||||||
await initializePreferences();
|
await initializePreferences();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -50,8 +50,6 @@ export function EntityPhotoGallery({
|
|||||||
|
|
||||||
const fetchPhotos = async () => {
|
const fetchPhotos = async () => {
|
||||||
try {
|
try {
|
||||||
console.log('📷 [FETCH PHOTOS] Starting fetch for:', { entityId, entityType });
|
|
||||||
|
|
||||||
// Fetch photos directly from the photos table
|
// Fetch photos directly from the photos table
|
||||||
const { data: photoData, error } = await supabase
|
const { data: photoData, error } = await supabase
|
||||||
.from('photos')
|
.from('photos')
|
||||||
@@ -60,8 +58,6 @@ export function EntityPhotoGallery({
|
|||||||
.eq('entity_id', entityId)
|
.eq('entity_id', entityId)
|
||||||
.order('created_at', { ascending: sortBy === 'oldest' });
|
.order('created_at', { ascending: sortBy === 'oldest' });
|
||||||
|
|
||||||
console.log('📷 [FETCH PHOTOS] Query result:', { photoData, error, count: photoData?.length });
|
|
||||||
|
|
||||||
if (error) throw error;
|
if (error) throw error;
|
||||||
|
|
||||||
// Map to Photo interface
|
// Map to Photo interface
|
||||||
@@ -74,7 +70,6 @@ export function EntityPhotoGallery({
|
|||||||
created_at: photo.created_at,
|
created_at: photo.created_at,
|
||||||
})) || [];
|
})) || [];
|
||||||
|
|
||||||
console.log('📷 [FETCH PHOTOS] Mapped photos:', mappedPhotos);
|
|
||||||
setPhotos(mappedPhotos);
|
setPhotos(mappedPhotos);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
console.error('📷 [FETCH PHOTOS] Error:', error);
|
console.error('📷 [FETCH PHOTOS] Error:', error);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import { getErrorMessage } from '@/lib/errorHandler';
|
|||||||
import { supabase } from '@/integrations/supabase/client';
|
import { supabase } from '@/integrations/supabase/client';
|
||||||
import { invokeWithTracking } from '@/lib/edgeFunctionTracking';
|
import { invokeWithTracking } from '@/lib/edgeFunctionTracking';
|
||||||
import { useAuth } from '@/hooks/useAuth';
|
import { useAuth } from '@/hooks/useAuth';
|
||||||
|
import { logger } from '@/lib/logger';
|
||||||
|
|
||||||
interface PhotoUploadProps {
|
interface PhotoUploadProps {
|
||||||
onUploadComplete?: (urls: string[], imageId?: string) => void;
|
onUploadComplete?: (urls: string[], imageId?: string) => void;
|
||||||
@@ -250,7 +251,7 @@ export function PhotoUpload({
|
|||||||
'DELETE'
|
'DELETE'
|
||||||
);
|
);
|
||||||
} catch (deleteError) {
|
} catch (deleteError) {
|
||||||
console.warn('Failed to delete old avatar:', deleteError);
|
logger.warn('Failed to delete old avatar');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -232,14 +232,6 @@ export function UppyPhotoSubmissionUpload({
|
|||||||
throw itemsError;
|
throw itemsError;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('✅ Photo submission created:', {
|
|
||||||
submission_id: submissionData.id,
|
|
||||||
photo_submission_id: photoSubmissionData.id,
|
|
||||||
entity_type: entityType,
|
|
||||||
entity_id: entityId,
|
|
||||||
photo_count: photoItems.length,
|
|
||||||
});
|
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: 'Submission Successful',
|
title: 'Submission Successful',
|
||||||
description: 'Your photos have been submitted for review. Thank you for contributing!',
|
description: 'Your photos have been submitted for review. Thank you for contributing!',
|
||||||
|
|||||||
@@ -110,7 +110,6 @@ function AuthProviderComponent({ children }: { children: React.ReactNode }) {
|
|||||||
const currentAal = await getSessionAal(session);
|
const currentAal = await getSessionAal(session);
|
||||||
setAal(currentAal);
|
setAal(currentAal);
|
||||||
authLog('[Auth] Current AAL:', currentAal);
|
authLog('[Auth] Current AAL:', currentAal);
|
||||||
console.log('🔐 [Auth] AAL SET:', currentAal); // Explicit console log for debugging
|
|
||||||
} else {
|
} else {
|
||||||
setAal(null);
|
setAal(null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
import { logger } from '@/lib/logger';
|
||||||
|
|
||||||
export function useCaptchaBypass() {
|
export function useCaptchaBypass() {
|
||||||
// Single layer: Check if environment allows bypass
|
// Single layer: Check if environment allows bypass
|
||||||
const bypassEnabled = import.meta.env.VITE_ALLOW_CAPTCHA_BYPASS === 'true';
|
const bypassEnabled = import.meta.env.VITE_ALLOW_CAPTCHA_BYPASS === 'true';
|
||||||
|
|
||||||
// Log warning if bypass is active
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (bypassEnabled && typeof window !== 'undefined') {
|
if (bypassEnabled && typeof window !== 'undefined') {
|
||||||
console.warn(
|
logger.warn(
|
||||||
'⚠️ CAPTCHA BYPASS IS ACTIVE\n' +
|
'⚠️ CAPTCHA BYPASS IS ACTIVE - ' +
|
||||||
'CAPTCHA verification is disabled via VITE_ALLOW_CAPTCHA_BYPASS=true\n' +
|
'This should ONLY be enabled in development/preview environments.'
|
||||||
'This should ONLY be enabled in development/preview environments.\n' +
|
|
||||||
'Ensure VITE_ALLOW_CAPTCHA_BYPASS=false in production!'
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [bypassEnabled]);
|
}, [bypassEnabled]);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { supabase } from '@/integrations/supabase/client';
|
|||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { getErrorMessage } from '@/lib/errorHandler';
|
import { getErrorMessage } from '@/lib/errorHandler';
|
||||||
import type { EntityType, EntityVersion } from '@/types/versioning';
|
import type { EntityType, EntityVersion } from '@/types/versioning';
|
||||||
|
import { logger } from '@/lib/logger';
|
||||||
|
|
||||||
interface FieldChange {
|
interface FieldChange {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -123,7 +124,7 @@ export function useEntityVersions(entityType: EntityType, entityId: string) {
|
|||||||
* @deprecated Use compareVersions() to see field-level changes
|
* @deprecated Use compareVersions() to see field-level changes
|
||||||
*/
|
*/
|
||||||
const fetchFieldHistory = async (versionId: string) => {
|
const fetchFieldHistory = async (versionId: string) => {
|
||||||
console.warn('fetchFieldHistory is deprecated. Use compareVersions() instead for field-level changes.');
|
logger.warn('fetchFieldHistory is deprecated. Use compareVersions() instead for field-level changes.');
|
||||||
setFieldHistory([]);
|
setFieldHistory([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useAuth } from '@/hooks/useAuth';
|
import { useAuth } from '@/hooks/useAuth';
|
||||||
import { useUnitPreferences } from '@/hooks/useUnitPreferences';
|
import { useUnitPreferences } from '@/hooks/useUnitPreferences';
|
||||||
|
import { logger } from '@/lib/logger';
|
||||||
|
|
||||||
function isLocalStorageAvailable(): boolean {
|
function isLocalStorageAvailable(): boolean {
|
||||||
try {
|
try {
|
||||||
@@ -24,11 +25,11 @@ export function useLocationAutoDetect() {
|
|||||||
// Only run auto-detection after preferences have loaded
|
// Only run auto-detection after preferences have loaded
|
||||||
if (loading) return;
|
if (loading) return;
|
||||||
|
|
||||||
// Check if localStorage is available
|
// Check if localStorage is available
|
||||||
if (!isLocalStorageAvailable()) {
|
if (!isLocalStorageAvailable()) {
|
||||||
console.warn('localStorage is not available, skipping location auto-detection');
|
logger.warn('localStorage is not available, skipping location auto-detection');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we've already attempted detection
|
// Check if we've already attempted detection
|
||||||
const hasAttemptedDetection = localStorage.getItem('location_detection_attempted');
|
const hasAttemptedDetection = localStorage.getItem('location_detection_attempted');
|
||||||
|
|||||||
@@ -435,7 +435,6 @@ export const useModerationQueue = (config?: UseModerationQueueConfig) => {
|
|||||||
const releaseAfterAction = useCallback(async (submissionId: string, action: 'approved' | 'rejected'): Promise<void> => {
|
const releaseAfterAction = useCallback(async (submissionId: string, action: 'approved' | 'rejected'): Promise<void> => {
|
||||||
if (currentLock?.submissionId === submissionId) {
|
if (currentLock?.submissionId === submissionId) {
|
||||||
await releaseLock(submissionId, true); // Silent release
|
await releaseLock(submissionId, true); // Silent release
|
||||||
console.log(`🔓 Auto-released lock after ${action} action`);
|
|
||||||
}
|
}
|
||||||
}, [currentLock, releaseLock]);
|
}, [currentLock, releaseLock]);
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,6 @@ export function useProfile(userId: string | undefined) {
|
|||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
if (!userId) return null;
|
if (!userId) return null;
|
||||||
|
|
||||||
console.log('[useProfile] Fetching filtered profile for userId:', userId);
|
|
||||||
|
|
||||||
// Get current viewer ID
|
// Get current viewer ID
|
||||||
const { data: { user } } = await supabase.auth.getUser();
|
const { data: { user } } = await supabase.auth.getUser();
|
||||||
const viewerId = user?.id || null;
|
const viewerId = user?.id || null;
|
||||||
@@ -24,7 +22,6 @@ export function useProfile(userId: string | undefined) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error('[useProfile] Error:', error);
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,11 +43,6 @@ export function useProfile(userId: string | undefined) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('[useProfile] Filtered profile loaded:', {
|
|
||||||
username: profileData.username,
|
|
||||||
has_avatar: !!profileData.avatar_url
|
|
||||||
});
|
|
||||||
|
|
||||||
return profileData;
|
return profileData;
|
||||||
},
|
},
|
||||||
enabled: !!userId,
|
enabled: !!userId,
|
||||||
@@ -61,7 +53,6 @@ export function useProfile(userId: string | undefined) {
|
|||||||
|
|
||||||
const refreshProfile = () => {
|
const refreshProfile = () => {
|
||||||
if (userId) {
|
if (userId) {
|
||||||
console.log('[useProfile] Invalidating profile cache for userId:', userId);
|
|
||||||
queryClient.invalidateQueries({ queryKey: ['profile', userId] });
|
queryClient.invalidateQueries({ queryKey: ['profile', userId] });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useState, useEffect, useMemo, useCallback } from 'react';
|
import { useState, useEffect, useMemo, useCallback } from 'react';
|
||||||
import { supabase } from '@/integrations/supabase/client';
|
import { supabase } from '@/integrations/supabase/client';
|
||||||
import { Park, Ride, Company } from '@/types/database';
|
import { Park, Ride, Company } from '@/types/database';
|
||||||
|
import { logger } from '@/lib/logger';
|
||||||
|
|
||||||
export interface SearchResult {
|
export interface SearchResult {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -67,7 +68,7 @@ export function useSearch(options: UseSearchOptions = {}) {
|
|||||||
setRecentSearches(parsed);
|
setRecentSearches(parsed);
|
||||||
} else {
|
} else {
|
||||||
// Invalid format, clear it
|
// Invalid format, clear it
|
||||||
console.warn('Recent searches data is not an array, clearing');
|
logger.warn('Recent searches data is not an array, clearing');
|
||||||
localStorage.removeItem('thrillwiki_recent_searches');
|
localStorage.removeItem('thrillwiki_recent_searches');
|
||||||
}
|
}
|
||||||
} catch (parseError) {
|
} catch (parseError) {
|
||||||
|
|||||||
@@ -451,8 +451,6 @@ async function checkSlugUniqueness(
|
|||||||
const tableName = getTableNameFromEntityType(entityType);
|
const tableName = getTableNameFromEntityType(entityType);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log(`Checking slug uniqueness for "${slug}" in ${tableName}, excludeId: ${excludeId}`);
|
|
||||||
|
|
||||||
// Query with explicit table name - use simple approach to avoid type instantiation issues
|
// Query with explicit table name - use simple approach to avoid type instantiation issues
|
||||||
let result;
|
let result;
|
||||||
|
|
||||||
@@ -470,34 +468,28 @@ async function checkSlugUniqueness(
|
|||||||
result = await supabase.from('ride_models').select('id').eq('slug', slug).limit(1);
|
result = await supabase.from('ride_models').select('id').eq('slug', slug).limit(1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.error(`Invalid table name: ${tableName}`);
|
|
||||||
return true; // Assume unique on invalid table
|
return true; // Assume unique on invalid table
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data, error } = result;
|
const { data, error } = result;
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error(`Slug uniqueness check failed for ${entityType}:`, error);
|
|
||||||
return true; // Assume unique on error to avoid blocking
|
return true; // Assume unique on error to avoid blocking
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no data, slug is unique
|
// If no data, slug is unique
|
||||||
if (!data || data.length === 0) {
|
if (!data || data.length === 0) {
|
||||||
console.log(`Slug "${slug}" is unique in ${tableName}`);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If excludeId provided and matches, it's the same entity (editing)
|
// If excludeId provided and matches, it's the same entity (editing)
|
||||||
if (excludeId && data[0] && data[0].id === excludeId) {
|
if (excludeId && data[0] && data[0].id === excludeId) {
|
||||||
console.log(`Slug "${slug}" matches current entity (editing mode)`);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Slug is in use by a different entity
|
// Slug is in use by a different entity
|
||||||
console.log(`Slug "${slug}" already exists in ${tableName}`);
|
|
||||||
return false;
|
return false;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Exception during slug uniqueness check:`, error);
|
|
||||||
return true; // Assume unique on error to avoid false positives
|
return true; // Assume unique on error to avoid false positives
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { SubmissionItemWithDeps } from './submissionItemsService';
|
import type { SubmissionItemWithDeps } from './submissionItemsService';
|
||||||
|
import { logger } from './logger';
|
||||||
|
|
||||||
// State definitions using discriminated unions
|
// State definitions using discriminated unions
|
||||||
export type ModerationState =
|
export type ModerationState =
|
||||||
@@ -63,7 +64,7 @@ export function moderationReducer(
|
|||||||
|
|
||||||
case 'LOCK_EXPIRED':
|
case 'LOCK_EXPIRED':
|
||||||
if (state.status !== 'locked' && state.status !== 'reviewing' && state.status !== 'loading_data') {
|
if (state.status !== 'locked' && state.status !== 'reviewing' && state.status !== 'loading_data') {
|
||||||
console.warn(`Lock expired notification in unexpected state: ${state.status}`);
|
logger.warn(`Lock expired notification in unexpected state: ${state.status}`);
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@@ -123,7 +124,7 @@ export function moderationReducer(
|
|||||||
case 'ERROR':
|
case 'ERROR':
|
||||||
// Error can happen from most states
|
// Error can happen from most states
|
||||||
if (state.status === 'idle' || state.status === 'complete') {
|
if (state.status === 'idle' || state.status === 'complete') {
|
||||||
console.warn('Error action in terminal state');
|
logger.warn('Error action in terminal state');
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@@ -135,7 +136,7 @@ export function moderationReducer(
|
|||||||
case 'RELEASE_LOCK':
|
case 'RELEASE_LOCK':
|
||||||
// Can release lock from locked, reviewing, or error states
|
// Can release lock from locked, reviewing, or error states
|
||||||
if (state.status !== 'locked' && state.status !== 'reviewing' && state.status !== 'error' && state.status !== 'lock_expired' && state.status !== 'loading_data') {
|
if (state.status !== 'locked' && state.status !== 'reviewing' && state.status !== 'error' && state.status !== 'lock_expired' && state.status !== 'loading_data') {
|
||||||
console.warn(`Cannot release lock from state: ${state.status}`);
|
logger.warn(`Cannot release lock from state: ${state.status}`);
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
return { status: 'idle' };
|
return { status: 'idle' };
|
||||||
|
|||||||
@@ -379,7 +379,7 @@ export async function detectChanges(
|
|||||||
|
|
||||||
// Add debugging warning if critical data is missing
|
// Add debugging warning if critical data is missing
|
||||||
if (!itemData.entity_name && item.item_type === 'photo_delete') {
|
if (!itemData.entity_name && item.item_type === 'photo_delete') {
|
||||||
console.warn(`[Photo Delete] Missing entity_name for photo_delete item`, {
|
logger.warn('[Photo Delete] Missing entity_name for photo_delete item', {
|
||||||
item_type: item.item_type,
|
item_type: item.item_type,
|
||||||
has_entity_type: !!itemData.entity_type,
|
has_entity_type: !!itemData.entity_type,
|
||||||
has_entity_id: !!itemData.entity_id,
|
has_entity_id: !!itemData.entity_id,
|
||||||
|
|||||||
@@ -1089,10 +1089,12 @@ export async function editSubmissionItem(
|
|||||||
currentItem.submission_id,
|
currentItem.submission_id,
|
||||||
true // isEdit = true
|
true // isEdit = true
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log(`✅ Created version for manual edit of ${currentItem.item_type} ${currentItem.approved_entity_id}`);
|
|
||||||
} catch (versionError) {
|
} catch (versionError) {
|
||||||
console.error('Failed to create version for manual edit:', versionError);
|
logger.error('Failed to create version for manual edit', {
|
||||||
|
action: 'create_version_for_edit',
|
||||||
|
itemType: currentItem.item_type,
|
||||||
|
entityId: currentItem.approved_entity_id
|
||||||
|
});
|
||||||
// Don't fail the entire operation, just log the error
|
// Don't fail the entire operation, just log the error
|
||||||
// The edit itself is still saved, just without version history
|
// The edit itself is still saved, just without version history
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { supabase } from '@/integrations/supabase/client';
|
import { supabase } from '@/integrations/supabase/client';
|
||||||
|
import { logger } from './logger';
|
||||||
|
|
||||||
// Generate anonymous session hash (no PII)
|
// Generate anonymous session hash (no PII)
|
||||||
function getSessionHash(): string {
|
function getSessionHash(): string {
|
||||||
@@ -38,10 +39,8 @@ export async function trackPageView(
|
|||||||
entity_id: entityId,
|
entity_id: entityId,
|
||||||
session_hash: getSessionHash()
|
session_hash: getSessionHash()
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`✅ Tracked view: ${entityType} ${entityId}`);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Fail silently - don't break the page if tracking fails
|
// Fail silently - don't break the page if tracking fails
|
||||||
console.error('Failed to track page view:', error);
|
logger.error('Failed to track page view', { entityType, entityId });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,11 +89,6 @@ export default function Auth() {
|
|||||||
setSignInCaptchaToken(null);
|
setSignInCaptchaToken(null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log('[Auth] Attempting sign in...', {
|
|
||||||
email: formData.email,
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
});
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data,
|
data,
|
||||||
error
|
error
|
||||||
@@ -109,7 +104,6 @@ export default function Auth() {
|
|||||||
|
|
||||||
// Check if MFA is required (user exists but no session)
|
// Check if MFA is required (user exists but no session)
|
||||||
if (data.user && !data.session) {
|
if (data.user && !data.session) {
|
||||||
console.log('[Auth] MFA required');
|
|
||||||
const totpFactor = data.user.factors?.find(f => f.factor_type === 'totp' && f.status === 'verified');
|
const totpFactor = data.user.factors?.find(f => f.factor_type === 'totp' && f.status === 'verified');
|
||||||
|
|
||||||
if (totpFactor) {
|
if (totpFactor) {
|
||||||
@@ -127,8 +121,6 @@ export default function Auth() {
|
|||||||
const postAuthResult = await handlePostAuthFlow(data.session, 'password');
|
const postAuthResult = await handlePostAuthFlow(data.session, 'password');
|
||||||
|
|
||||||
if (postAuthResult.success && postAuthResult.data.shouldRedirect) {
|
if (postAuthResult.success && postAuthResult.data.shouldRedirect) {
|
||||||
console.log('[Auth] MFA step-up required');
|
|
||||||
|
|
||||||
// Get the TOTP factor ID
|
// Get the TOTP factor ID
|
||||||
const { data: factors } = await supabase.auth.mfa.listFactors();
|
const { data: factors } = await supabase.auth.mfa.listFactors();
|
||||||
const totpFactor = factors?.totp?.find(f => f.status === 'verified');
|
const totpFactor = factors?.totp?.find(f => f.status === 'verified');
|
||||||
@@ -140,24 +132,16 @@ export default function Auth() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('[Auth] Sign in successful', {
|
|
||||||
user: data.user?.email,
|
|
||||||
session: !!data.session,
|
|
||||||
sessionExpiry: data.session?.expires_at
|
|
||||||
});
|
|
||||||
|
|
||||||
// Verify session was stored
|
// Verify session was stored
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
const { data: { session } } = await supabase.auth.getSession();
|
const { data: { session } } = await supabase.auth.getSession();
|
||||||
if (!session) {
|
if (!session) {
|
||||||
console.error('[Auth] Session not found after login!');
|
|
||||||
toast({
|
toast({
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
title: "Session Error",
|
title: "Session Error",
|
||||||
description: "Login succeeded but session was not stored. Please check your browser settings and enable cookies/storage."
|
description: "Login succeeded but session was not stored. Please check your browser settings and enable cookies/storage."
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log('[Auth] Session verified after login');
|
|
||||||
toast({
|
toast({
|
||||||
title: "Welcome back!",
|
title: "Welcome back!",
|
||||||
description: "You've been signed in successfully."
|
description: "You've been signed in successfully."
|
||||||
@@ -447,18 +431,9 @@ export default function Auth() {
|
|||||||
<Label>Security Verification</Label>
|
<Label>Security Verification</Label>
|
||||||
<TurnstileCaptcha
|
<TurnstileCaptcha
|
||||||
key={signInCaptchaKey}
|
key={signInCaptchaKey}
|
||||||
onSuccess={(token) => {
|
onSuccess={setSignInCaptchaToken}
|
||||||
console.log('Sign-in CAPTCHA success:', token);
|
onError={() => setSignInCaptchaToken(null)}
|
||||||
setSignInCaptchaToken(token);
|
onExpire={() => setSignInCaptchaToken(null)}
|
||||||
}}
|
|
||||||
onError={(error) => {
|
|
||||||
console.log('Sign-in CAPTCHA error:', error);
|
|
||||||
setSignInCaptchaToken(null);
|
|
||||||
}}
|
|
||||||
onExpire={() => {
|
|
||||||
console.log('Sign-in CAPTCHA expired');
|
|
||||||
setSignInCaptchaToken(null);
|
|
||||||
}}
|
|
||||||
siteKey={import.meta.env.VITE_TURNSTILE_SITE_KEY}
|
siteKey={import.meta.env.VITE_TURNSTILE_SITE_KEY}
|
||||||
theme="auto"
|
theme="auto"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ export default function AuthCallback() {
|
|||||||
// Check if this is a password recovery flow first
|
// Check if this is a password recovery flow first
|
||||||
const hash = window.location.hash;
|
const hash = window.location.hash;
|
||||||
if (hash.includes('type=recovery')) {
|
if (hash.includes('type=recovery')) {
|
||||||
console.log('[AuthCallback] Password recovery detected');
|
|
||||||
setIsRecoveryMode(true);
|
setIsRecoveryMode(true);
|
||||||
setStatus('success'); // Stop the loading spinner
|
setStatus('success'); // Stop the loading spinner
|
||||||
return; // Don't process further
|
return; // Don't process further
|
||||||
@@ -40,19 +39,15 @@ export default function AuthCallback() {
|
|||||||
const { data: { session }, error: sessionError } = await supabase.auth.getSession();
|
const { data: { session }, error: sessionError } = await supabase.auth.getSession();
|
||||||
|
|
||||||
if (sessionError) {
|
if (sessionError) {
|
||||||
console.error('[AuthCallback] Session error:', sessionError);
|
|
||||||
throw sessionError;
|
throw sessionError;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!session) {
|
if (!session) {
|
||||||
console.log('[AuthCallback] No session found, redirecting to auth');
|
|
||||||
navigate('/auth');
|
navigate('/auth');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = session.user;
|
const user = session.user;
|
||||||
console.log('[AuthCallback] User authenticated:', user.id);
|
|
||||||
|
|
||||||
|
|
||||||
// Check if this is a new OAuth user (created within last minute)
|
// Check if this is a new OAuth user (created within last minute)
|
||||||
const createdAt = new Date(user.created_at);
|
const createdAt = new Date(user.created_at);
|
||||||
@@ -63,20 +58,11 @@ export default function AuthCallback() {
|
|||||||
const provider = user.app_metadata?.provider;
|
const provider = user.app_metadata?.provider;
|
||||||
const isOAuthUser = provider === 'google' || provider === 'discord';
|
const isOAuthUser = provider === 'google' || provider === 'discord';
|
||||||
|
|
||||||
console.log('[AuthCallback] User info:', {
|
|
||||||
isNewUser,
|
|
||||||
isOAuthUser,
|
|
||||||
provider,
|
|
||||||
createdAt: user.created_at,
|
|
||||||
});
|
|
||||||
|
|
||||||
// If new OAuth user, process profile
|
// If new OAuth user, process profile
|
||||||
if (isNewUser && isOAuthUser) {
|
if (isNewUser && isOAuthUser) {
|
||||||
setStatus('processing');
|
setStatus('processing');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log('[AuthCallback] Processing OAuth profile...');
|
|
||||||
|
|
||||||
const { data, error, requestId } = await invokeWithTracking(
|
const { data, error, requestId } = await invokeWithTracking(
|
||||||
'process-oauth-profile',
|
'process-oauth-profile',
|
||||||
{},
|
{},
|
||||||
@@ -84,13 +70,9 @@ export default function AuthCallback() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error('[AuthCallback] Profile processing error:', error);
|
|
||||||
// Don't throw - allow sign-in to continue even if profile processing fails
|
// Don't throw - allow sign-in to continue even if profile processing fails
|
||||||
} else {
|
|
||||||
console.log('[AuthCallback] Profile processed:', data);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[AuthCallback] Failed to process profile:', error);
|
|
||||||
// Continue anyway - don't block sign-in
|
// Continue anyway - don't block sign-in
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,16 +82,11 @@ export default function AuthCallback() {
|
|||||||
if (isOAuthUser) {
|
if (isOAuthUser) {
|
||||||
authMethod = 'oauth';
|
authMethod = 'oauth';
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('[AuthCallback] Auth method:', authMethod);
|
|
||||||
|
|
||||||
// Unified post-authentication flow for ALL methods (OAuth, magic link, etc.)
|
// Unified post-authentication flow for ALL methods (OAuth, magic link, etc.)
|
||||||
console.log('[AuthCallback] Running post-auth flow...');
|
|
||||||
const result = await handlePostAuthFlow(session, authMethod);
|
const result = await handlePostAuthFlow(session, authMethod);
|
||||||
|
|
||||||
if (result.success && result.data?.shouldRedirect) {
|
if (result.success && result.data?.shouldRedirect) {
|
||||||
console.log('[AuthCallback] MFA step-up required - showing modal');
|
|
||||||
|
|
||||||
// Get factor ID and show modal instead of redirecting
|
// Get factor ID and show modal instead of redirecting
|
||||||
const { data: factors } = await supabase.auth.mfa.listFactors();
|
const { data: factors } = await supabase.auth.mfa.listFactors();
|
||||||
const totpFactor = factors?.totp?.find(f => f.status === 'verified');
|
const totpFactor = factors?.totp?.find(f => f.status === 'verified');
|
||||||
@@ -138,7 +115,6 @@ export default function AuthCallback() {
|
|||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const errorMsg = getErrorMessage(error);
|
const errorMsg = getErrorMessage(error);
|
||||||
console.error('[AuthCallback] Error:', errorMsg);
|
|
||||||
setStatus('error');
|
setStatus('error');
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
@@ -224,7 +200,6 @@ export default function AuthCallback() {
|
|||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const errorMsg = getErrorMessage(error);
|
const errorMsg = getErrorMessage(error);
|
||||||
console.error('[AuthCallback] Password reset error:', errorMsg);
|
|
||||||
toast({
|
toast({
|
||||||
variant: 'destructive',
|
variant: 'destructive',
|
||||||
title: 'Failed to set password',
|
title: 'Failed to set password',
|
||||||
|
|||||||
Reference in New Issue
Block a user