Fix: Approve database migration

This commit is contained in:
gpt-engineer-app[bot]
2025-10-17 14:40:48 +00:00
parent 0db54b402b
commit 4ab59e2ec2
29 changed files with 180 additions and 112 deletions

View File

@@ -15,6 +15,7 @@ import { DatePicker } from '@/components/ui/date-picker';
import { FlexibleDateInput, type DatePrecision } from '@/components/ui/flexible-date-input'; import { FlexibleDateInput, type DatePrecision } from '@/components/ui/flexible-date-input';
import { SlugField } from '@/components/ui/slug-field'; import { SlugField } from '@/components/ui/slug-field';
import { toast } from '@/hooks/use-toast'; import { toast } from '@/hooks/use-toast';
import { getErrorMessage } from '@/lib/errorHandler';
import { MapPin, Save, X, Plus } from 'lucide-react'; import { MapPin, Save, X, Plus } from 'lucide-react';
import { toDateOnly } from '@/lib/dateUtils'; import { toDateOnly } from '@/lib/dateUtils';
import { Badge } from '@/components/ui/badge'; import { Badge } from '@/components/ui/badge';
@@ -192,10 +193,11 @@ export function ParkForm({ onSubmit, onCancel, initialData, isEditing = false }:
? "The park information has been updated successfully." ? "The park information has been updated successfully."
: "The new park has been created successfully." : "The new park has been created successfully."
}); });
} catch (error: any) { } catch (error) {
const errorMsg = getErrorMessage(error);
toast({ toast({
title: "Error", title: "Error",
description: error.message || "Failed to save park information.", description: errorMsg,
variant: "destructive" variant: "destructive"
}); });
} finally { } finally {

View File

@@ -20,6 +20,7 @@ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } f
import { Combobox } from '@/components/ui/combobox'; import { Combobox } from '@/components/ui/combobox';
import { SlugField } from '@/components/ui/slug-field'; import { SlugField } from '@/components/ui/slug-field';
import { toast } from '@/hooks/use-toast'; import { toast } from '@/hooks/use-toast';
import { getErrorMessage } from '@/lib/errorHandler';
import { Plus, Zap, Save, X } from 'lucide-react'; import { Plus, Zap, Save, X } from 'lucide-react';
import { toDateOnly } from '@/lib/dateUtils'; import { toDateOnly } from '@/lib/dateUtils';
import { useUnitPreferences } from '@/hooks/useUnitPreferences'; import { useUnitPreferences } from '@/hooks/useUnitPreferences';
@@ -263,10 +264,11 @@ export function RideForm({ onSubmit, onCancel, initialData, isEditing = false }:
? "Ride, manufacturer, and model submitted for review" ? "Ride, manufacturer, and model submitted for review"
: "Ride submitted for review" : "Ride submitted for review"
}); });
} catch (error: any) { } catch (error) {
const errorMsg = getErrorMessage(error);
toast({ toast({
title: "Error", title: "Error",
description: error.message || "Failed to save ride information.", description: errorMsg,
variant: "destructive" variant: "destructive"
}); });
} finally { } finally {

View File

@@ -8,6 +8,7 @@ import { useAuth } from '@/hooks/useAuth';
import { useProfile } from '@/hooks/useProfile'; import { useProfile } from '@/hooks/useProfile';
import { useToast } from '@/hooks/use-toast'; import { useToast } from '@/hooks/use-toast';
import { useAuthModal } from '@/hooks/useAuthModal'; import { useAuthModal } from '@/hooks/useAuthModal';
import { getErrorMessage } from '@/lib/errorHandler';
export function AuthButtons() { export function AuthButtons() {
const { user, loading: authLoading, signOut } = useAuth(); const { user, loading: authLoading, signOut } = useAuth();
@@ -25,11 +26,12 @@ export function AuthButtons() {
description: "You've been signed out successfully." description: "You've been signed out successfully."
}); });
navigate('/'); navigate('/');
} catch (error: any) { } catch (error) {
const errorMsg = getErrorMessage(error);
toast({ toast({
variant: "destructive", variant: "destructive",
title: "Error signing out", title: "Error signing out",
description: error.message description: errorMsg
}); });
} finally { } finally {
setLoggingOut(false); setLoggingOut(false);

View File

@@ -8,6 +8,7 @@ import { AlertCircle } from 'lucide-react';
import { type DependencyConflict, type SubmissionItemWithDeps } from '@/lib/submissionItemsService'; import { type DependencyConflict, type SubmissionItemWithDeps } from '@/lib/submissionItemsService';
import { useToast } from '@/hooks/use-toast'; import { useToast } from '@/hooks/use-toast';
import { useAuth } from '@/hooks/useAuth'; import { useAuth } from '@/hooks/useAuth';
import { getErrorMessage } from '@/lib/errorHandler';
interface ConflictResolutionDialogProps { interface ConflictResolutionDialogProps {
open: boolean; open: boolean;
@@ -67,10 +68,11 @@ export function ConflictResolutionDialog({
onResolve(); onResolve();
onOpenChange(false); onOpenChange(false);
} catch (error: any) { } catch (error) {
const errorMsg = getErrorMessage(error);
toast({ toast({
title: 'Error', title: 'Error',
description: error.message || 'Failed to resolve conflicts', description: errorMsg,
variant: 'destructive', variant: 'destructive',
}); });
} }

View File

@@ -8,6 +8,7 @@ import { Textarea } from '@/components/ui/textarea';
import { toast } from '@/hooks/use-toast'; import { toast } from '@/hooks/use-toast';
import { useIsMobile } from '@/hooks/use-mobile'; import { useIsMobile } from '@/hooks/use-mobile';
import { useUserRole } from '@/hooks/useUserRole'; import { useUserRole } from '@/hooks/useUserRole';
import { getErrorMessage } from '@/lib/errorHandler';
import { useAuth } from '@/hooks/useAuth'; import { useAuth } from '@/hooks/useAuth';
import { editSubmissionItem, type SubmissionItemWithDeps } from '@/lib/submissionItemsService'; import { editSubmissionItem, type SubmissionItemWithDeps } from '@/lib/submissionItemsService';
import { ParkForm } from '@/components/admin/ParkForm'; import { ParkForm } from '@/components/admin/ParkForm';
@@ -58,10 +59,11 @@ export function ItemEditDialog({ item, open, onOpenChange, onComplete }: ItemEdi
onComplete(); onComplete();
onOpenChange(false); onOpenChange(false);
} catch (error: any) { } catch (error) {
const errorMsg = getErrorMessage(error);
toast({ toast({
title: 'Error', title: 'Error',
description: error.message || 'Failed to save changes', description: errorMsg,
variant: 'destructive', variant: 'destructive',
}); });
} finally { } finally {

View File

@@ -3,6 +3,7 @@ import { supabase } from '@/integrations/supabase/client';
import { PhotoGrid } from '@/components/common/PhotoGrid'; import { PhotoGrid } from '@/components/common/PhotoGrid';
import type { PhotoSubmissionItem } from '@/types/photo-submissions'; import type { PhotoSubmissionItem } from '@/types/photo-submissions';
import type { PhotoItem } from '@/types/photos'; import type { PhotoItem } from '@/types/photos';
import { getErrorMessage } from '@/lib/errorHandler';
interface PhotoSubmissionDisplayProps { interface PhotoSubmissionDisplayProps {
submissionId: string; submissionId: string;
@@ -81,10 +82,11 @@ export function PhotoSubmissionDisplay({ submissionId }: PhotoSubmissionDisplayP
setPhotos(data || []); setPhotos(data || []);
console.log(`✅ Successfully loaded ${data?.length || 0} photos`); console.log(`✅ Successfully loaded ${data?.length || 0} photos`);
} catch (error: any) { } catch (error) {
console.error('❌ PhotoSubmissionDisplay error:', error); const errorMsg = getErrorMessage(error);
console.error('❌ PhotoSubmissionDisplay error:', errorMsg);
setPhotos([]); setPhotos([]);
setError(error.message || 'Failed to load photos'); setError(errorMsg);
} finally { } finally {
setLoading(false); setLoading(false);
} }

View File

@@ -19,6 +19,7 @@ import {
} from '@/components/ui/select'; } from '@/components/ui/select';
import { supabase } from '@/integrations/supabase/client'; import { supabase } from '@/integrations/supabase/client';
import { useToast } from '@/hooks/use-toast'; import { useToast } from '@/hooks/use-toast';
import { getErrorMessage } from '@/lib/errorHandler';
interface Moderator { interface Moderator {
user_id: string; user_id: string;
@@ -87,8 +88,9 @@ export function ReassignDialog({
}); });
setModerators(moderatorsList); setModerators(moderatorsList);
} catch (error: any) { } catch (error) {
console.error('Error fetching moderators:', error); const errorMsg = getErrorMessage(error);
console.error('Error fetching moderators:', errorMsg);
toast({ toast({
title: 'Error', title: 'Error',
description: 'Failed to load moderators list', description: 'Failed to load moderators list',

View File

@@ -2,6 +2,7 @@ import { useState, useEffect, forwardRef, useImperativeHandle } from 'react';
import { supabase } from '@/integrations/supabase/client'; import { supabase } from '@/integrations/supabase/client';
import { useAuth } from '@/hooks/useAuth'; import { useAuth } from '@/hooks/useAuth';
import { useToast } from '@/hooks/use-toast'; import { useToast } from '@/hooks/use-toast';
import { getErrorMessage } from '@/lib/errorHandler';
import { ActivityCard } from './ActivityCard'; import { ActivityCard } from './ActivityCard';
import { Skeleton } from '@/components/ui/skeleton'; import { Skeleton } from '@/components/ui/skeleton';
import { Activity as ActivityIcon } from 'lucide-react'; import { Activity as ActivityIcon } from 'lucide-react';
@@ -150,8 +151,9 @@ export const RecentActivity = forwardRef<RecentActivityRef>((props, ref) => {
// Full replacement for non-silent refreshes or 'replace' strategy // Full replacement for non-silent refreshes or 'replace' strategy
setActivities(recentActivities); setActivities(recentActivities);
} }
} catch (error: any) { } catch (error) {
console.error('Error fetching recent activity:', error); const errorMsg = getErrorMessage(error);
console.error('Error fetching recent activity:', errorMsg);
toast({ toast({
title: "Error", title: "Error",
description: "Failed to load recent activity", description: "Failed to load recent activity",

View File

@@ -7,6 +7,7 @@ import { UserX } from 'lucide-react';
import { supabase } from '@/integrations/supabase/client'; import { supabase } from '@/integrations/supabase/client';
import { useAuth } from '@/hooks/useAuth'; import { useAuth } from '@/hooks/useAuth';
import { useToast } from '@/hooks/use-toast'; import { useToast } from '@/hooks/use-toast';
import { getErrorMessage } from '@/lib/errorHandler';
interface UserBlockButtonProps { interface UserBlockButtonProps {
targetUserId: string; targetUserId: string;
@@ -42,8 +43,9 @@ export function UserBlockButton({ targetUserId, targetUsername, variant = 'outli
}); });
setReason(''); setReason('');
} catch (error: any) { } catch (error) {
console.error('Error blocking user:', error); const errorMsg = getErrorMessage(error);
console.error('Error blocking user:', errorMsg);
toast({ toast({
title: 'Error', title: 'Error',
description: 'Failed to block user', description: 'Failed to block user',

View File

@@ -4,6 +4,7 @@ import { supabase } from '@/integrations/supabase/client';
import { useToast } from '@/hooks/use-toast'; import { useToast } from '@/hooks/use-toast';
import { AlertTriangle, Loader2 } from 'lucide-react'; import { AlertTriangle, Loader2 } from 'lucide-react';
import { useState } from 'react'; import { useState } from 'react';
import { getErrorMessage } from '@/lib/errorHandler';
interface DeletionStatusBannerProps { interface DeletionStatusBannerProps {
scheduledDate: string; scheduledDate: string;
@@ -37,11 +38,12 @@ export function DeletionStatusBanner({ scheduledDate, onCancelled }: DeletionSta
}); });
onCancelled(); onCancelled();
} catch (error: any) { } catch (error) {
const errorMsg = getErrorMessage(error);
toast({ toast({
variant: 'destructive', variant: 'destructive',
title: 'Error', title: 'Error',
description: error.message || 'Failed to cancel deletion', description: errorMsg,
}); });
} finally { } finally {
setLoading(false); setLoading(false);

View File

@@ -20,7 +20,7 @@ import {
} from '@/components/ui/form'; } from '@/components/ui/form';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { handleError, handleSuccess, AppError } from '@/lib/errorHandler'; import { handleError, handleSuccess, AppError, getErrorMessage } from '@/lib/errorHandler';
import { logger } from '@/lib/logger'; import { logger } from '@/lib/logger';
import { supabase } from '@/integrations/supabase/client'; import { supabase } from '@/integrations/supabase/client';
import { Loader2, Mail, CheckCircle2, AlertCircle } from 'lucide-react'; import { Loader2, Mail, CheckCircle2, AlertCircle } from 'lucide-react';
@@ -185,13 +185,12 @@ export function EmailChangeDialog({ open, onOpenChange, currentEmail, userId }:
); );
setStep('success'); setStep('success');
} catch (error: any) { } catch (error) {
const errorMsg = getErrorMessage(error);
logger.error('Email change failed', { logger.error('Email change failed', {
userId, userId,
action: 'email_change', action: 'email_change',
error: error instanceof Error ? error.message : String(error), error: errorMsg,
errorCode: error.code,
errorStatus: error.status
}); });
if (error.message?.includes('rate limit') || error.status === 429) { if (error.message?.includes('rate limit') || error.status === 429) {

View File

@@ -9,6 +9,7 @@ import { useQuery } from '@tanstack/react-query';
import { supabase } from '@/integrations/supabase/client'; import { supabase } from '@/integrations/supabase/client';
import { useAuth } from '@/hooks/useAuth'; import { useAuth } from '@/hooks/useAuth';
import { toast } from 'sonner'; import { toast } from 'sonner';
import { getErrorMessage } from '@/lib/errorHandler';
import { deleteTimelineEvent } from '@/lib/entitySubmissionHelpers'; import { deleteTimelineEvent } from '@/lib/entitySubmissionHelpers';
import type { EntityType, TimelineEvent } from '@/types/timeline'; import type { EntityType, TimelineEvent } from '@/types/timeline';
@@ -113,10 +114,11 @@ export function EntityTimelineManager({
toast.success('Event deleted', { toast.success('Event deleted', {
description: 'Your timeline event has been deleted successfully.' description: 'Your timeline event has been deleted successfully.'
}); });
} catch (error: any) { } catch (error) {
console.error('Delete error:', error); const errorMsg = getErrorMessage(error);
console.error('Delete error:', errorMsg);
toast.error('Failed to delete event', { toast.error('Failed to delete event', {
description: error.message || 'Please try again.' description: errorMsg
}); });
} }
}; };

View File

@@ -46,6 +46,7 @@ import { Loader2, Trash } from 'lucide-react';
import { useAuth } from '@/hooks/useAuth'; import { useAuth } from '@/hooks/useAuth';
import { useToast } from '@/hooks/use-toast'; import { useToast } from '@/hooks/use-toast';
import { submitTimelineEvent, submitTimelineEventUpdate, deleteTimelineEvent } from '@/lib/entitySubmissionHelpers'; import { submitTimelineEvent, submitTimelineEventUpdate, deleteTimelineEvent } from '@/lib/entitySubmissionHelpers';
import { getErrorMessage } from '@/lib/errorHandler';
import type { import type {
EntityType, EntityType,
TimelineEventFormData, TimelineEventFormData,
@@ -195,11 +196,12 @@ export function TimelineEventEditorDialog({
onOpenChange(false); onOpenChange(false);
setShowDeleteConfirm(false); setShowDeleteConfirm(false);
form.reset(); form.reset();
} catch (error: any) { } catch (error) {
console.error('Delete error:', error); const errorMsg = getErrorMessage(error);
console.error('Delete error:', errorMsg);
toast({ toast({
title: 'Failed to delete event', title: 'Failed to delete event',
description: error.message || 'Please try again.', description: errorMsg,
variant: 'destructive', variant: 'destructive',
}); });
} finally { } finally {

View File

@@ -13,6 +13,7 @@ import {
FileImage FileImage
} from 'lucide-react'; } from 'lucide-react';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { getErrorMessage } from '@/lib/errorHandler';
import { supabase } from '@/integrations/supabase/client'; import { supabase } from '@/integrations/supabase/client';
interface PhotoUploadProps { interface PhotoUploadProps {
@@ -266,11 +267,11 @@ export function PhotoUpload({
} }
setUploadProgress(100); setUploadProgress(100);
} catch (error: any) { } catch (error) {
previewUrls.forEach(url => revokeObjectUrl(url)); previewUrls.forEach(url => revokeObjectUrl(url));
const errorMessage = error.message || 'Upload failed'; const errorMsg = getErrorMessage(error);
setError(errorMessage); setError(errorMsg);
onError?.(errorMessage); onError?.(errorMsg);
} finally { } finally {
setUploading(false); setUploading(false);
setUploadProgress(0); setUploadProgress(0);

View File

@@ -1,4 +1,4 @@
import { supabase } from '@/integrations/supabase/client'; import { getErrorMessage } from '@/lib/errorHandler';
import { updateSubmissionItem, type SubmissionItemWithDeps, type DependencyConflict } from './submissionItemsService'; import { updateSubmissionItem, type SubmissionItemWithDeps, type DependencyConflict } from './submissionItemsService';
export interface ResolutionResult { export interface ResolutionResult {
@@ -83,11 +83,12 @@ export async function resolveConflicts(
success: true, success: true,
updatedSelections, updatedSelections,
}; };
} catch (error: any) { } catch (error) {
console.error('Conflict resolution error:', error); const errorMsg = getErrorMessage(error);
console.error('Conflict resolution error:', errorMsg);
return { return {
success: false, success: false,
error: error.message || 'Failed to resolve conflicts', error: errorMsg,
}; };
} }
} }

View File

@@ -346,40 +346,29 @@ async function checkSlugUniqueness(
try { try {
console.log(`Checking slug uniqueness for "${slug}" in ${tableName}, excludeId: ${excludeId}`); console.log(`Checking slug uniqueness for "${slug}" in ${tableName}, excludeId: ${excludeId}`);
// Type-safe queries for each table // Query with explicit table name - use simple approach to avoid type instantiation issues
type ValidTableName = 'parks' | 'rides' | 'companies' | 'ride_models' | 'photos'; let result;
// Validate table name switch (tableName) {
const validTables: ValidTableName[] = ['parks', 'rides', 'companies', 'ride_models', 'photos']; case 'parks':
if (!validTables.includes(tableName as ValidTableName)) { result = await supabase.from('parks').select('id').eq('slug', slug).limit(1);
console.error(`Invalid table name: ${tableName}`); break;
return true; // Assume unique on invalid table case 'rides':
} result = await supabase.from('rides').select('id').eq('slug', slug).limit(1);
break;
// Query with explicit table name case 'companies':
let data, error; result = await supabase.from('companies').select('id').eq('slug', slug).limit(1);
if (tableName === 'parks') { break;
const result = await supabase.from('parks').select('id').eq('slug', slug).limit(1); case 'ride_models':
data = result.data; result = await supabase.from('ride_models').select('id').eq('slug', slug).limit(1);
error = result.error; break;
} else if (tableName === 'rides') { default:
const result = await supabase.from('rides').select('id').eq('slug', slug).limit(1); console.error(`Invalid table name: ${tableName}`);
data = result.data; return true; // Assume unique on invalid table
error = result.error;
} else if (tableName === 'companies') {
const result = await supabase.from('companies').select('id').eq('slug', slug).limit(1);
data = result.data;
error = result.error;
} else if (tableName === 'ride_models') {
const result = await supabase.from('ride_models').select('id').eq('slug', slug).limit(1);
data = result.data;
error = result.error;
} else {
const result = await supabase.from('photos').select('id').eq('slug', slug).limit(1);
data = result.data;
error = result.error;
} }
const { data, error } = result;
if (error) { if (error) {
console.error(`Slug uniqueness check failed for ${entityType}:`, 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

View File

@@ -23,10 +23,11 @@ export async function getUserIdentities(): Promise<UserIdentity[]> {
if (error) throw error; if (error) throw error;
return (data?.identities || []) as UserIdentity[]; return (data?.identities || []) as UserIdentity[];
} catch (error: any) { } catch (error) {
const errorMsg = getErrorMessage(error);
logger.error('Failed to get user identities', { logger.error('Failed to get user identities', {
action: 'get_identities', action: 'get_identities',
error: error.message error: errorMsg
}); });
return []; return [];
} }
@@ -127,15 +128,16 @@ export async function disconnectIdentity(
} }
return { success: true }; return { success: true };
} catch (error: any) { } catch (error) {
const errorMsg = getErrorMessage(error);
logger.error('Failed to disconnect identity', { logger.error('Failed to disconnect identity', {
action: 'identity_disconnect', action: 'identity_disconnect',
provider, provider,
error: error.message error: errorMsg
}); });
return { return {
success: false, success: false,
error: error.message || 'Failed to disconnect identity' error: errorMsg
}; };
} }
} }
@@ -159,15 +161,16 @@ export async function connectIdentity(
if (error) throw error; if (error) throw error;
return { success: true }; return { success: true };
} catch (error: any) { } catch (error) {
const errorMsg = getErrorMessage(error);
logger.error('Failed to connect identity', { logger.error('Failed to connect identity', {
action: 'identity_connect', action: 'identity_connect',
provider, provider,
error: error.message error: errorMsg
}); });
return { return {
success: false, success: false,
error: error.message || `Failed to connect ${provider} account` error: errorMsg
}; };
} }
} }
@@ -229,14 +232,15 @@ export async function addPasswordToAccount(): Promise<IdentityOperationResult> {
needsEmailConfirmation: true, needsEmailConfirmation: true,
email: userEmail email: userEmail
}; };
} catch (error: any) { } catch (error) {
const errorMsg = getErrorMessage(error);
logger.error('Failed to initiate password setup', { logger.error('Failed to initiate password setup', {
action: 'password_setup', action: 'password_setup',
error: error.message error: errorMsg
}); });
return { return {
success: false, success: false,
error: error.message || 'Failed to send password reset email' error: errorMsg
}; };
} }
} }

View File

@@ -224,16 +224,17 @@ export async function approveSubmissionItems(
// Add to dependency map for child items // Add to dependency map for child items
dependencyMap.set(item.id, entityId); dependencyMap.set(item.id, entityId);
} catch (error: any) { } catch (error) {
console.error(`Error approving ${item.item_type} item ${item.id}:`, error); const errorMsg = getErrorMessage(error);
console.error(`Error approving ${item.item_type} item ${item.id}:`, errorMsg);
// Update item with error status // Update item with error status
await updateSubmissionItem(item.id, { await updateSubmissionItem(item.id, {
status: 'rejected', status: 'rejected',
rejection_reason: `Failed to create entity: ${error.message}`, rejection_reason: `Failed to create entity: ${errorMsg}`,
}); });
throw new Error(`Failed to approve ${item.item_type}: ${error.message}`); throw new Error(`Failed to approve ${item.item_type}: ${errorMsg}`);
} }
} }
} }

View File

@@ -10,6 +10,7 @@ import { Card, CardHeader, CardTitle, CardDescription, CardContent } from '@/com
import { Label } from '@/components/ui/label'; import { Label } from '@/components/ui/label';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { getErrorMessage } from '@/lib/errorHandler';
export default function AuthCallback() { export default function AuthCallback() {
const navigate = useNavigate(); const navigate = useNavigate();
@@ -124,14 +125,15 @@ export default function AuthCallback() {
navigate('/'); navigate('/');
}, 500); }, 500);
} catch (error: any) { } catch (error) {
console.error('[AuthCallback] Error:', error); const errorMsg = getErrorMessage(error);
console.error('[AuthCallback] Error:', errorMsg);
setStatus('error'); setStatus('error');
toast({ toast({
variant: 'destructive', variant: 'destructive',
title: 'Sign in error', title: 'Sign in error',
description: error.message || 'An error occurred during sign in. Please try again.', description: errorMsg,
}); });
// Redirect to auth page after error // Redirect to auth page after error
@@ -183,12 +185,13 @@ export default function AuthCallback() {
navigate('/auth'); navigate('/auth');
}, 1500); }, 1500);
} catch (error: any) { } catch (error) {
console.error('[AuthCallback] Password reset error:', 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',
description: error.message || 'Please try again.', description: errorMsg,
}); });
setSettingPassword(false); setSettingPassword(false);
} }

View File

@@ -15,6 +15,7 @@ import { DesignerPhotoGallery } from '@/components/companies/DesignerPhotoGaller
import { useAuth } from '@/hooks/useAuth'; import { useAuth } from '@/hooks/useAuth';
import { useUserRole } from '@/hooks/useUserRole'; import { useUserRole } from '@/hooks/useUserRole';
import { toast } from '@/hooks/use-toast'; import { toast } from '@/hooks/use-toast';
import { getErrorMessage } from '@/lib/errorHandler';
import { submitCompanyUpdate } from '@/lib/companyHelpers'; import { submitCompanyUpdate } from '@/lib/companyHelpers';
import { VersionIndicator } from '@/components/versioning/VersionIndicator'; import { VersionIndicator } from '@/components/versioning/VersionIndicator';
import { EntityHistoryTabs } from '@/components/history/EntityHistoryTabs'; import { EntityHistoryTabs } from '@/components/history/EntityHistoryTabs';
@@ -109,10 +110,11 @@ export default function DesignerDetail() {
}); });
setIsEditModalOpen(false); setIsEditModalOpen(false);
} catch (error: any) { } catch (error) {
const errorMsg = getErrorMessage(error);
toast({ toast({
title: "Error", title: "Error",
description: error.message || "Failed to submit edit.", description: errorMsg,
variant: "destructive" variant: "destructive"
}); });
} }

View File

@@ -16,6 +16,7 @@ import { useUserRole } from '@/hooks/useUserRole';
import { toast } from '@/hooks/use-toast'; import { toast } from '@/hooks/use-toast';
import { submitCompanyCreation } from '@/lib/companyHelpers'; import { submitCompanyCreation } from '@/lib/companyHelpers';
import { useAuthModal } from '@/hooks/useAuthModal'; import { useAuthModal } from '@/hooks/useAuthModal';
import { getErrorMessage } from '@/lib/errorHandler';
export default function Designers() { export default function Designers() {
const navigate = useNavigate(); const navigate = useNavigate();
@@ -36,8 +37,9 @@ export default function Designers() {
description: "Your submission has been sent for review." description: "Your submission has been sent for review."
}); });
setIsCreateModalOpen(false); setIsCreateModalOpen(false);
} catch (error: any) { } catch (error) {
toast({ title: "Error", description: error.message || "Failed to submit designer.", variant: "destructive" }); const errorMsg = getErrorMessage(error);
toast({ title: "Error", description: errorMsg, variant: "destructive" });
} }
}; };

View File

@@ -16,6 +16,7 @@ import { ManufacturerPhotoGallery } from '@/components/companies/ManufacturerPho
import { useAuth } from '@/hooks/useAuth'; import { useAuth } from '@/hooks/useAuth';
import { useUserRole } from '@/hooks/useUserRole'; import { useUserRole } from '@/hooks/useUserRole';
import { toast } from '@/hooks/use-toast'; import { toast } from '@/hooks/use-toast';
import { getErrorMessage } from '@/lib/errorHandler';
import { submitCompanyUpdate } from '@/lib/companyHelpers'; import { submitCompanyUpdate } from '@/lib/companyHelpers';
import { VersionIndicator } from '@/components/versioning/VersionIndicator'; import { VersionIndicator } from '@/components/versioning/VersionIndicator';
import { EntityHistoryTabs } from '@/components/history/EntityHistoryTabs'; import { EntityHistoryTabs } from '@/components/history/EntityHistoryTabs';
@@ -119,10 +120,11 @@ export default function ManufacturerDetail() {
}); });
setIsEditModalOpen(false); setIsEditModalOpen(false);
} catch (error: any) { } catch (error) {
const errorMsg = getErrorMessage(error);
toast({ toast({
title: "Error", title: "Error",
description: error.message || "Failed to submit edit.", description: errorMsg,
variant: "destructive" variant: "destructive"
}); });
} }

View File

@@ -16,6 +16,7 @@ import { useUserRole } from '@/hooks/useUserRole';
import { toast } from '@/hooks/use-toast'; import { toast } from '@/hooks/use-toast';
import { submitCompanyCreation } from '@/lib/companyHelpers'; import { submitCompanyCreation } from '@/lib/companyHelpers';
import { useAuthModal } from '@/hooks/useAuthModal'; import { useAuthModal } from '@/hooks/useAuthModal';
import { getErrorMessage } from '@/lib/errorHandler';
export default function Manufacturers() { export default function Manufacturers() {
const navigate = useNavigate(); const navigate = useNavigate();
@@ -80,10 +81,11 @@ export default function Manufacturers() {
}); });
setIsCreateModalOpen(false); setIsCreateModalOpen(false);
} catch (error: any) { } catch (error) {
const errorMsg = getErrorMessage(error);
toast({ toast({
title: "Error", title: "Error",
description: error.message || "Failed to submit manufacturer.", description: errorMsg,
variant: "destructive" variant: "destructive"
}); });
} }

View File

@@ -17,6 +17,7 @@ import { ParkCard } from '@/components/parks/ParkCard';
import { useAuth } from '@/hooks/useAuth'; import { useAuth } from '@/hooks/useAuth';
import { useUserRole } from '@/hooks/useUserRole'; import { useUserRole } from '@/hooks/useUserRole';
import { toast } from '@/hooks/use-toast'; import { toast } from '@/hooks/use-toast';
import { getErrorMessage } from '@/lib/errorHandler';
import { submitCompanyUpdate } from '@/lib/companyHelpers'; import { submitCompanyUpdate } from '@/lib/companyHelpers';
import { VersionIndicator } from '@/components/versioning/VersionIndicator'; import { VersionIndicator } from '@/components/versioning/VersionIndicator';
import { EntityHistoryTabs } from '@/components/history/EntityHistoryTabs'; import { EntityHistoryTabs } from '@/components/history/EntityHistoryTabs';
@@ -154,10 +155,11 @@ export default function OperatorDetail() {
}); });
setIsEditModalOpen(false); setIsEditModalOpen(false);
} catch (error: any) { } catch (error) {
const errorMsg = getErrorMessage(error);
toast({ toast({
title: "Error", title: "Error",
description: error.message || "Failed to submit edit.", description: errorMsg,
variant: "destructive" variant: "destructive"
}); });
} }

View File

@@ -17,6 +17,7 @@ import { useUserRole } from '@/hooks/useUserRole';
import { toast } from '@/hooks/use-toast'; import { toast } from '@/hooks/use-toast';
import { submitCompanyCreation } from '@/lib/companyHelpers'; import { submitCompanyCreation } from '@/lib/companyHelpers';
import { useAuthModal } from '@/hooks/useAuthModal'; import { useAuthModal } from '@/hooks/useAuthModal';
import { getErrorMessage } from '@/lib/errorHandler';
const Operators = () => { const Operators = () => {
const navigate = useNavigate(); const navigate = useNavigate();
@@ -73,10 +74,11 @@ const Operators = () => {
}); });
setIsCreateModalOpen(false); setIsCreateModalOpen(false);
} catch (error: any) { } catch (error) {
const errorMsg = getErrorMessage(error);
toast({ toast({
title: "Error", title: "Error",
description: error.message || "Failed to submit operator.", description: errorMsg,
variant: "destructive" variant: "destructive"
}); });
} }

View File

@@ -20,6 +20,7 @@ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } f
import { RideForm } from '@/components/admin/RideForm'; import { RideForm } from '@/components/admin/RideForm';
import { ParkForm } from '@/components/admin/ParkForm'; import { ParkForm } from '@/components/admin/ParkForm';
import { toast } from '@/hooks/use-toast'; import { toast } from '@/hooks/use-toast';
import { getErrorMessage } from '@/lib/errorHandler';
import { useUserRole } from '@/hooks/useUserRole'; import { useUserRole } from '@/hooks/useUserRole';
import { Edit } from 'lucide-react'; import { Edit } from 'lucide-react';
import { VersionIndicator } from '@/components/versioning/VersionIndicator'; import { VersionIndicator } from '@/components/versioning/VersionIndicator';
@@ -149,10 +150,11 @@ export default function ParkDetail() {
}); });
setIsAddRideModalOpen(false); setIsAddRideModalOpen(false);
} catch (error: any) { } catch (error) {
const errorMsg = getErrorMessage(error);
toast({ toast({
title: "Submission Failed", title: "Submission Failed",
description: error.message || "Failed to submit ride for review.", description: errorMsg,
variant: "destructive" variant: "destructive"
}); });
} }
@@ -175,10 +177,11 @@ export default function ParkDetail() {
}); });
setIsEditParkModalOpen(false); setIsEditParkModalOpen(false);
} catch (error: any) { } catch (error) {
const errorMsg = getErrorMessage(error);
toast({ toast({
title: "Error", title: "Error",
description: error.message || "Failed to submit park edit.", description: errorMsg,
variant: "destructive" variant: "destructive"
}); });
} }

View File

@@ -17,6 +17,7 @@ import { useUserRole } from '@/hooks/useUserRole';
import { toast } from '@/hooks/use-toast'; import { toast } from '@/hooks/use-toast';
import { submitCompanyCreation } from '@/lib/companyHelpers'; import { submitCompanyCreation } from '@/lib/companyHelpers';
import { useAuthModal } from '@/hooks/useAuthModal'; import { useAuthModal } from '@/hooks/useAuthModal';
import { getErrorMessage } from '@/lib/errorHandler';
const ParkOwners = () => { const ParkOwners = () => {
const navigate = useNavigate(); const navigate = useNavigate();
@@ -73,10 +74,11 @@ const ParkOwners = () => {
}); });
setIsCreateModalOpen(false); setIsCreateModalOpen(false);
} catch (error: any) { } catch (error) {
const errorMsg = getErrorMessage(error);
toast({ toast({
title: "Error", title: "Error",
description: error.message || "Failed to submit property owner.", description: errorMsg,
variant: "destructive" variant: "destructive"
}); });
} }

View File

@@ -14,6 +14,7 @@ import { RideSubmissionData } from '@/types/submission-data';
import { supabase } from '@/integrations/supabase/client'; import { supabase } from '@/integrations/supabase/client';
import { useAuth } from '@/hooks/useAuth'; import { useAuth } from '@/hooks/useAuth';
import { toast } from '@/hooks/use-toast'; import { toast } from '@/hooks/use-toast';
import { getErrorMessage } from '@/lib/errorHandler';
import { useAuthModal } from '@/hooks/useAuthModal'; import { useAuthModal } from '@/hooks/useAuthModal';
export default function ParkRides() { export default function ParkRides() {
@@ -130,10 +131,11 @@ export default function ParkRides() {
}); });
setIsCreateModalOpen(false); setIsCreateModalOpen(false);
} catch (error: any) { } catch (error) {
const errorMsg = getErrorMessage(error);
toast({ toast({
title: "Submission Failed", title: "Submission Failed",
description: error.message || "Failed to submit ride.", description: errorMsg,
variant: "destructive" variant: "destructive"
}); });
} }

View File

@@ -0,0 +1,27 @@
-- Add check constraints to enforce metric-only units in statistics tables
-- This ensures data integrity and compliance with the custom knowledge requirement:
-- "Unit Conversion Rules: Storage: Always metric in DB (km/h, m, cm, kg)"
-- Add constraint to ride_coaster_stats table
ALTER TABLE ride_coaster_stats
ADD CONSTRAINT ride_coaster_stats_metric_unit_check
CHECK (
unit IS NULL OR
unit IN ('km/h', 'm', 'cm', 'kg', 'g', 'G', 'celsius', 'seconds', 'minutes', 'hours', 'count', '%')
);
-- Add constraint to ride_technical_specifications table
ALTER TABLE ride_technical_specifications
ADD CONSTRAINT ride_tech_specs_metric_unit_check
CHECK (
unit IS NULL OR
unit IN ('km/h', 'm', 'cm', 'kg', 'g', 'G', 'celsius', 'seconds', 'minutes', 'hours', 'count', '%')
);
-- Add constraint to ride_model_technical_specifications table
ALTER TABLE ride_model_technical_specifications
ADD CONSTRAINT ride_model_tech_specs_metric_unit_check
CHECK (
unit IS NULL OR
unit IN ('km/h', 'm', 'cm', 'kg', 'g', 'G', 'celsius', 'seconds', 'minutes', 'hours', 'count', '%')
);