diff --git a/src/components/moderation/PhotoComparison.tsx b/src/components/moderation/PhotoComparison.tsx
new file mode 100644
index 00000000..746c8acc
--- /dev/null
+++ b/src/components/moderation/PhotoComparison.tsx
@@ -0,0 +1,159 @@
+import { Badge } from '@/components/ui/badge';
+import { ImageIcon, Trash2, Edit } from 'lucide-react';
+
+interface PhotoAdditionPreviewProps {
+ photos: Array<{
+ url: string;
+ title?: string;
+ caption?: string;
+ }>;
+ compact?: boolean;
+}
+
+export function PhotoAdditionPreview({ photos, compact = false }: PhotoAdditionPreviewProps) {
+ if (compact) {
+ return (
+
+
+ +{photos.length} Photo{photos.length > 1 ? 's' : ''}
+
+ );
+ }
+
+ return (
+
+
+
+ Adding {photos.length} Photo{photos.length > 1 ? 's' : ''}
+
+
+
+ {photos.slice(0, 6).map((photo, idx) => (
+
+

+ {(photo.title || photo.caption) && (
+
+ {photo.title || photo.caption}
+
+ )}
+
+ ))}
+ {photos.length > 6 && (
+
+
+ +{photos.length - 6} more
+
+
+ )}
+
+
+ );
+}
+
+interface PhotoEditPreviewProps {
+ photo: {
+ url: string;
+ oldCaption?: string;
+ newCaption?: string;
+ oldTitle?: string;
+ newTitle?: string;
+ };
+ compact?: boolean;
+}
+
+export function PhotoEditPreview({ photo, compact = false }: PhotoEditPreviewProps) {
+ if (compact) {
+ return (
+
+
+ Photo Edit
+
+ );
+ }
+
+ return (
+
+
+
+ Photo Metadata Edit
+
+
+
+

+
+
+ {photo.oldTitle !== photo.newTitle && (
+
+
Title:
+
{photo.oldTitle || 'None'}
+
{photo.newTitle || 'None'}
+
+ )}
+
+ {photo.oldCaption !== photo.newCaption && (
+
+
Caption:
+
{photo.oldCaption || 'None'}
+
{photo.newCaption || 'None'}
+
+ )}
+
+
+
+ );
+}
+
+interface PhotoDeletionPreviewProps {
+ photo: {
+ url: string;
+ title?: string;
+ caption?: string;
+ };
+ compact?: boolean;
+}
+
+export function PhotoDeletionPreview({ photo, compact = false }: PhotoDeletionPreviewProps) {
+ if (compact) {
+ return (
+
+
+ Delete Photo
+
+ );
+ }
+
+ return (
+
+
+
+ Deleting Photo
+
+
+
+

+
+ {(photo.title || photo.caption) && (
+
+ {photo.title &&
{photo.title}
}
+ {photo.caption &&
{photo.caption}
}
+
+ )}
+
+
+ );
+}
diff --git a/src/components/moderation/ReportsQueue.tsx b/src/components/moderation/ReportsQueue.tsx
index a42ba1be..b07642f4 100644
--- a/src/components/moderation/ReportsQueue.tsx
+++ b/src/components/moderation/ReportsQueue.tsx
@@ -1,4 +1,4 @@
-import { useState, useEffect } from 'react';
+import { useState, useEffect, forwardRef, useImperativeHandle } from 'react';
import { CheckCircle, XCircle, ExternalLink, Calendar, User, Flag } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
@@ -8,6 +8,8 @@ import { Label } from '@/components/ui/label';
import { supabase } from '@/integrations/supabase/client';
import { useToast } from '@/hooks/use-toast';
import { format } from 'date-fns';
+import { useAdminSettings } from '@/hooks/useAdminSettings';
+import { useAuth } from '@/hooks/useAuth';
interface Report {
id: string;
@@ -38,14 +40,35 @@ const STATUS_COLORS = {
dismissed: 'outline',
} as const;
-export function ReportsQueue() {
+export interface ReportsQueueRef {
+ refresh: () => void;
+}
+
+export const ReportsQueue = forwardRef
((props, ref) => {
const [reports, setReports] = useState([]);
const [loading, setLoading] = useState(true);
+ const [isInitialLoad, setIsInitialLoad] = useState(true);
const [actionLoading, setActionLoading] = useState(null);
const { toast } = useToast();
+ const { user } = useAuth();
- const fetchReports = async () => {
+ // Get admin settings for polling configuration
+ const { getAdminPanelRefreshMode, getAdminPanelPollInterval } = useAdminSettings();
+ const refreshMode = getAdminPanelRefreshMode();
+ const pollInterval = getAdminPanelPollInterval();
+
+ // Expose refresh method via ref
+ useImperativeHandle(ref, () => ({
+ refresh: () => fetchReports(false) // Manual refresh shows loading
+ }), []);
+
+ const fetchReports = async (silent = false) => {
try {
+ // Only show loading on initial load
+ if (!silent) {
+ setLoading(true);
+ }
+
const { data, error } = await supabase
.from('reports')
.select(`
@@ -106,13 +129,35 @@ export function ReportsQueue() {
variant: "destructive",
});
} finally {
- setLoading(false);
+ // Only clear loading if it was set
+ if (!silent) {
+ setLoading(false);
+ }
+ if (isInitialLoad) {
+ setIsInitialLoad(false);
+ }
}
};
+ // Initial fetch on mount
useEffect(() => {
- fetchReports();
- }, []);
+ if (user) {
+ fetchReports(false); // Show loading
+ }
+ }, [user]);
+
+ // Polling for auto-refresh
+ useEffect(() => {
+ if (!user || refreshMode !== 'auto' || isInitialLoad) return;
+
+ const interval = setInterval(() => {
+ fetchReports(true); // Silent refresh
+ }, pollInterval);
+
+ return () => {
+ clearInterval(interval);
+ };
+ }, [user, refreshMode, pollInterval, isInitialLoad]);
const handleReportAction = async (reportId: string, action: 'reviewed' | 'dismissed') => {
setActionLoading(reportId);
@@ -258,4 +303,4 @@ export function ReportsQueue() {
))}
);
-}
\ No newline at end of file
+});
\ No newline at end of file
diff --git a/src/components/moderation/SpecialFieldDisplay.tsx b/src/components/moderation/SpecialFieldDisplay.tsx
new file mode 100644
index 00000000..296d0f24
--- /dev/null
+++ b/src/components/moderation/SpecialFieldDisplay.tsx
@@ -0,0 +1,327 @@
+import { useState } from 'react';
+import { Badge } from '@/components/ui/badge';
+import { MeasurementDisplay } from '@/components/ui/measurement-display';
+import { SpeedDisplay } from '@/components/ui/speed-display';
+import { MapPin, ArrowRight, Calendar, ExternalLink } from 'lucide-react';
+import type { FieldChange } from '@/lib/submissionChangeDetection';
+import { formatFieldValue } from '@/lib/submissionChangeDetection';
+
+interface SpecialFieldDisplayProps {
+ change: FieldChange;
+ compact?: boolean;
+}
+
+export function SpecialFieldDisplay({ change, compact = false }: SpecialFieldDisplayProps) {
+ const fieldName = change.field.toLowerCase();
+
+ // Detect field type
+ if (fieldName.includes('speed') || fieldName === 'max_speed_kmh') {
+ return
;
+ }
+
+ if (fieldName.includes('height') || fieldName.includes('length') ||
+ fieldName === 'max_height_meters' || fieldName === 'length_meters' ||
+ fieldName === 'drop_height_meters') {
+ return
;
+ }
+
+ if (fieldName === 'status') {
+ return
;
+ }
+
+ if (fieldName.includes('date') && !fieldName.includes('updated') && !fieldName.includes('created')) {
+ return
;
+ }
+
+ if (fieldName.includes('_id') && fieldName !== 'id' && fieldName !== 'user_id') {
+ return
;
+ }
+
+ if (fieldName === 'latitude' || fieldName === 'longitude') {
+ return
;
+ }
+
+ // Fallback to null, will be handled by regular FieldDiff
+ return null;
+}
+
+function SpeedFieldDisplay({ change, compact }: { change: FieldChange; compact: boolean }) {
+ if (compact) {
+ return (
+
+ Speed
+
+ );
+ }
+
+ const formatFieldName = (name: string) =>
+ name.replace(/_/g, ' ').replace(/([A-Z])/g, ' $1').trim()
+ .replace(/^./, str => str.toUpperCase());
+
+ return (
+
+
{formatFieldName(change.field)}
+
+ {change.changeType === 'modified' && (
+
+ )}
+
+ {change.changeType === 'added' && (
+
+ +
+
+ )}
+
+ {change.changeType === 'removed' && (
+
+
+
+ )}
+
+ );
+}
+
+function MeasurementFieldDisplay({ change, compact }: { change: FieldChange; compact: boolean }) {
+ if (compact) {
+ return (
+
+ Measurement
+
+ );
+ }
+
+ const formatFieldName = (name: string) =>
+ name.replace(/_/g, ' ').replace(/([A-Z])/g, ' $1').trim()
+ .replace(/^./, str => str.toUpperCase());
+
+ return (
+
+
{formatFieldName(change.field)}
+
+ {change.changeType === 'modified' && (
+
+ )}
+
+ {change.changeType === 'added' && (
+
+ +
+
+ )}
+
+ {change.changeType === 'removed' && (
+
+
+
+ )}
+
+ );
+}
+
+function StatusFieldDisplay({ change, compact }: { change: FieldChange; compact: boolean }) {
+ const getStatusColor = (status: string) => {
+ const statusLower = String(status).toLowerCase();
+ if (statusLower === 'operating' || statusLower === 'active') return 'bg-green-500/10 text-green-600 dark:text-green-400 border-green-500/20';
+ if (statusLower === 'closed' || statusLower === 'inactive') return 'bg-red-500/10 text-red-600 dark:text-red-400 border-red-500/20';
+ if (statusLower === 'under_construction' || statusLower === 'pending') return 'bg-amber-500/10 text-amber-600 dark:text-amber-400 border-amber-500/20';
+ return 'bg-muted/30 text-muted-foreground';
+ };
+
+ if (compact) {
+ return (
+
+ Status
+
+ );
+ }
+
+ const formatFieldName = (name: string) =>
+ name.replace(/_/g, ' ').replace(/([A-Z])/g, ' $1').trim()
+ .replace(/^./, str => str.toUpperCase());
+
+ return (
+
+
{formatFieldName(change.field)}
+
+ {change.changeType === 'modified' && (
+
+
+ {formatFieldValue(change.oldValue)}
+
+
+
+ {formatFieldValue(change.newValue)}
+
+
+ )}
+
+ {change.changeType === 'added' && (
+
+ {formatFieldValue(change.newValue)}
+
+ )}
+
+ {change.changeType === 'removed' && (
+
+ {formatFieldValue(change.oldValue)}
+
+ )}
+
+ );
+}
+
+function DateFieldDisplay({ change, compact }: { change: FieldChange; compact: boolean }) {
+ if (compact) {
+ return (
+
+
+ Date
+
+ );
+ }
+
+ const formatFieldName = (name: string) =>
+ name.replace(/_/g, ' ').replace(/([A-Z])/g, ' $1').trim()
+ .replace(/^./, str => str.toUpperCase());
+
+ return (
+
+
+
+ {formatFieldName(change.field)}
+
+
+ {change.changeType === 'modified' && (
+
+
+ {formatFieldValue(change.oldValue)}
+
+
+
+ {formatFieldValue(change.newValue)}
+
+
+ )}
+
+ {change.changeType === 'added' && (
+
+ + {formatFieldValue(change.newValue)}
+
+ )}
+
+ {change.changeType === 'removed' && (
+
+ {formatFieldValue(change.oldValue)}
+
+ )}
+
+ );
+}
+
+function RelationshipFieldDisplay({ change, compact }: { change: FieldChange; compact: boolean }) {
+ // This would ideally fetch entity names, but for now we show IDs with better formatting
+ const formatFieldName = (name: string) =>
+ name.replace(/_id$/, '').replace(/_/g, ' ').trim()
+ .replace(/^./, str => str.toUpperCase());
+
+ if (compact) {
+ return (
+
+ {formatFieldName(change.field)}
+
+ );
+ }
+
+ return (
+
+
{formatFieldName(change.field)}
+
+ {change.changeType === 'modified' && (
+
+
+ {String(change.oldValue).slice(0, 8)}...
+
+
+
+ {String(change.newValue).slice(0, 8)}...
+
+
+ )}
+
+ {change.changeType === 'added' && (
+
+ + {String(change.newValue).slice(0, 8)}...
+
+ )}
+
+ {change.changeType === 'removed' && (
+
+ {String(change.oldValue).slice(0, 8)}...
+
+ )}
+
+ );
+}
+
+function CoordinateFieldDisplay({ change, compact }: { change: FieldChange; compact: boolean }) {
+ if (compact) {
+ return (
+
+
+ Coordinates
+
+ );
+ }
+
+ const formatFieldName = (name: string) =>
+ name.replace(/_/g, ' ').replace(/([A-Z])/g, ' $1').trim()
+ .replace(/^./, str => str.toUpperCase());
+
+ return (
+
+
+
+ {formatFieldName(change.field)}
+
+
+ {change.changeType === 'modified' && (
+
+
+ {Number(change.oldValue).toFixed(6)}°
+
+
+
+ {Number(change.newValue).toFixed(6)}°
+
+
+ )}
+
+ {change.changeType === 'added' && (
+
+ + {Number(change.newValue).toFixed(6)}°
+
+ )}
+
+ {change.changeType === 'removed' && (
+
+ {Number(change.oldValue).toFixed(6)}°
+
+ )}
+
+ );
+}
diff --git a/src/components/moderation/SubmissionChangesDisplay.tsx b/src/components/moderation/SubmissionChangesDisplay.tsx
new file mode 100644
index 00000000..31de9e96
--- /dev/null
+++ b/src/components/moderation/SubmissionChangesDisplay.tsx
@@ -0,0 +1,230 @@
+import { useState, useEffect } from 'react';
+import { Badge } from '@/components/ui/badge';
+import { Skeleton } from '@/components/ui/skeleton';
+import { FieldDiff, ImageDiff, LocationDiff } from './FieldComparison';
+import { PhotoAdditionPreview, PhotoEditPreview, PhotoDeletionPreview } from './PhotoComparison';
+import { detectChanges, type ChangesSummary } from '@/lib/submissionChangeDetection';
+import type { SubmissionItemData } from '@/types/submissions';
+import type { SubmissionItemWithDeps } from '@/lib/submissionItemsService';
+import { Building2, Train, MapPin, Building, User, ImageIcon, Trash2, Edit, Plus, AlertTriangle } from 'lucide-react';
+
+interface SubmissionChangesDisplayProps {
+ item: SubmissionItemData | SubmissionItemWithDeps;
+ view?: 'summary' | 'detailed';
+ showImages?: boolean;
+ submissionId?: string;
+}
+
+// Helper to determine change magnitude
+function getChangeMagnitude(totalChanges: number, hasImages: boolean, action: string) {
+ if (action === 'delete') return { label: 'Deletion', variant: 'destructive' as const, icon: AlertTriangle };
+ if (action === 'create') return { label: 'New', variant: 'default' as const, icon: Plus };
+ if (hasImages) return { label: 'Major', variant: 'default' as const, icon: Edit };
+ if (totalChanges >= 5) return { label: 'Major', variant: 'default' as const, icon: Edit };
+ if (totalChanges >= 3) return { label: 'Moderate', variant: 'secondary' as const, icon: Edit };
+ return { label: 'Minor', variant: 'outline' as const, icon: Edit };
+}
+
+export function SubmissionChangesDisplay({
+ item,
+ view = 'summary',
+ showImages = true,
+ submissionId
+}: SubmissionChangesDisplayProps) {
+ const [changes, setChanges] = useState
(null);
+ const [loading, setLoading] = useState(true);
+
+ useEffect(() => {
+ const loadChanges = async () => {
+ setLoading(true);
+ const detectedChanges = await detectChanges(item, submissionId);
+ setChanges(detectedChanges);
+ setLoading(false);
+ };
+ loadChanges();
+ }, [item, submissionId]);
+
+ if (loading || !changes) {
+ return ;
+ }
+
+ // Get appropriate icon for entity type
+ const getEntityIcon = () => {
+ const iconClass = "h-4 w-4";
+ switch (item.item_type) {
+ case 'park': return ;
+ case 'ride': return ;
+ case 'manufacturer':
+ case 'operator':
+ case 'property_owner':
+ case 'designer': return ;
+ case 'photo': return ;
+ default: return ;
+ }
+ };
+
+ // Get action badge
+ const getActionBadge = () => {
+ switch (changes.action) {
+ case 'create':
+ return New;
+ case 'edit':
+ return Edit;
+ case 'delete':
+ return Delete;
+ }
+ };
+
+ const magnitude = getChangeMagnitude(
+ changes.totalChanges,
+ changes.imageChanges.length > 0,
+ changes.action
+ );
+
+ if (view === 'summary') {
+ return (
+
+
+ {getEntityIcon()}
+ {changes.entityName}
+ {getActionBadge()}
+ {changes.action === 'edit' && (
+
+ {magnitude.label} Change
+
+ )}
+
+
+ {changes.action === 'edit' && changes.totalChanges > 0 && (
+
+ {changes.fieldChanges.slice(0, 5).map((change, idx) => (
+
+ ))}
+ {changes.imageChanges.map((change, idx) => (
+
+ ))}
+ {changes.photoChanges.map((change, idx) => {
+ if (change.type === 'added' && change.photos) {
+ return
;
+ }
+ if (change.type === 'edited' && change.photo) {
+ return
;
+ }
+ if (change.type === 'deleted' && change.photo) {
+ return
;
+ }
+ return null;
+ })}
+ {changes.hasLocationChange && (
+
+ Location
+
+ )}
+ {changes.totalChanges > 5 && (
+
+ +{changes.totalChanges - 5} more
+
+ )}
+
+ )}
+
+ {changes.action === 'create' && item.item_data?.description && (
+
+ {item.item_data.description}
+
+ )}
+
+ {changes.action === 'delete' && (
+
+ Marked for deletion
+
+ )}
+
+ );
+ }
+
+ // Detailed view
+ return (
+
+
+ {getEntityIcon()}
+
{changes.entityName}
+ {getActionBadge()}
+
+
+ {changes.action === 'create' && (
+
+ Creating new {item.item_type}
+
+ )}
+
+ {changes.action === 'delete' && (
+
+ This {item.item_type} will be deleted
+
+ )}
+
+ {changes.action === 'edit' && changes.totalChanges > 0 && (
+ <>
+ {changes.fieldChanges.length > 0 && (
+
+
Field Changes ({changes.fieldChanges.length})
+
+ {changes.fieldChanges.map((change, idx) => (
+
+ ))}
+
+
+ )}
+
+ {showImages && changes.imageChanges.length > 0 && (
+
+
Image Changes
+
+ {changes.imageChanges.map((change, idx) => (
+
+ ))}
+
+
+ )}
+
+ {showImages && changes.photoChanges.length > 0 && (
+
+
Photo Changes
+
+ {changes.photoChanges.map((change, idx) => {
+ if (change.type === 'added' && change.photos) {
+ return
;
+ }
+ if (change.type === 'edited' && change.photo) {
+ return
;
+ }
+ if (change.type === 'deleted' && change.photo) {
+ return
;
+ }
+ return null;
+ })}
+
+
+ )}
+
+ {changes.hasLocationChange && (
+
+
Location Change
+
+
+ )}
+ >
+ )}
+
+ {changes.action === 'edit' && changes.totalChanges === 0 && (
+
+ No changes detected
+
+ )}
+
+ );
+}
diff --git a/src/components/moderation/SubmissionItemsList.tsx b/src/components/moderation/SubmissionItemsList.tsx
new file mode 100644
index 00000000..a9e52a7e
--- /dev/null
+++ b/src/components/moderation/SubmissionItemsList.tsx
@@ -0,0 +1,112 @@
+import { useState, useEffect } from 'react';
+import { supabase } from '@/integrations/supabase/client';
+import { SubmissionChangesDisplay } from './SubmissionChangesDisplay';
+import { PhotoSubmissionDisplay } from './PhotoSubmissionDisplay';
+import { Skeleton } from '@/components/ui/skeleton';
+import { Alert, AlertDescription } from '@/components/ui/alert';
+import { AlertCircle } from 'lucide-react';
+import type { SubmissionItemData } from '@/types/submissions';
+
+interface SubmissionItemsListProps {
+ submissionId: string;
+ view?: 'summary' | 'detailed';
+ showImages?: boolean;
+}
+
+export function SubmissionItemsList({
+ submissionId,
+ view = 'summary',
+ showImages = true
+}: SubmissionItemsListProps) {
+ const [items, setItems] = useState([]);
+ const [hasPhotos, setHasPhotos] = useState(false);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
+
+ useEffect(() => {
+ fetchSubmissionItems();
+ }, [submissionId]);
+
+ const fetchSubmissionItems = async () => {
+ try {
+ setLoading(true);
+ setError(null);
+
+ // Fetch submission items
+ const { data: itemsData, error: itemsError } = await supabase
+ .from('submission_items')
+ .select('*')
+ .eq('submission_id', submissionId)
+ .order('order_index');
+
+ if (itemsError) throw itemsError;
+
+ // Check for photo submissions (using array query to avoid 406)
+ const { data: photoData, error: photoError } = await supabase
+ .from('photo_submissions')
+ .select('id')
+ .eq('submission_id', submissionId);
+
+ if (photoError) {
+ console.warn('Error checking photo submissions:', photoError);
+ }
+
+ setItems((itemsData || []) as SubmissionItemData[]);
+ setHasPhotos(photoData && photoData.length > 0);
+ } catch (err) {
+ console.error('Error fetching submission items:', err);
+ setError('Failed to load submission details');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ if (loading) {
+ return (
+
+
+ {view === 'detailed' && }
+
+ );
+ }
+
+ if (error) {
+ return (
+
+
+ {error}
+
+ );
+ }
+
+ if (items.length === 0 && !hasPhotos) {
+ return (
+
+ No items found for this submission
+
+ );
+ }
+
+ return (
+
+ {/* Show regular submission items */}
+ {items.map((item) => (
+
+
+
+ ))}
+
+ {/* Show photo submission if exists */}
+ {hasPhotos && (
+
+ )}
+
+ );
+}
diff --git a/src/components/moderation/SubmissionReviewManager.tsx b/src/components/moderation/SubmissionReviewManager.tsx
index 6529dd03..e7500253 100644
--- a/src/components/moderation/SubmissionReviewManager.tsx
+++ b/src/components/moderation/SubmissionReviewManager.tsx
@@ -2,7 +2,6 @@ import { useState, useEffect } from 'react';
import { useToast } from '@/hooks/use-toast';
import { useUserRole } from '@/hooks/useUserRole';
import { useAuth } from '@/hooks/useAuth';
-import { useRealtimeSubmissionItems } from '@/hooks/useRealtimeSubmissionItems';
import {
fetchSubmissionItems,
buildDependencyTree,
@@ -60,20 +59,6 @@ export function SubmissionReviewManager({
const isMobile = useIsMobile();
const Container = isMobile ? Sheet : Dialog;
- // Set up realtime subscription for submission items
- useRealtimeSubmissionItems({
- submissionId,
- onUpdate: (payload) => {
- console.log('Submission item updated in real-time:', payload);
- toast({
- title: 'Item Updated',
- description: 'A submission item was updated by another moderator',
- });
- loadSubmissionItems();
- },
- enabled: open && !!submissionId,
- });
-
useEffect(() => {
if (open && submissionId) {
loadSubmissionItems();
@@ -473,7 +458,11 @@ export function SubmissionReviewManager({
handleEdit(item)}
- onStatusChange={(status) => handleItemStatusChange(item.id, status)}
+ onStatusChange={async () => {
+ // Status changes handled via approve/reject actions
+ await loadSubmissionItems();
+ }}
+ submissionId={submissionId}
/>
))}
diff --git a/src/components/operators/OperatorCard.tsx b/src/components/operators/OperatorCard.tsx
index 5a96d15a..6135aa92 100644
--- a/src/components/operators/OperatorCard.tsx
+++ b/src/components/operators/OperatorCard.tsx
@@ -13,7 +13,7 @@ const OperatorCard = ({ company }: OperatorCardProps) => {
const navigate = useNavigate();
const handleClick = () => {
- navigate(`/operators/${company.slug}/parks/`);
+ navigate(`/operators/${company.slug}`);
};
const getCompanyIcon = () => {
diff --git a/src/components/park-owners/ParkOwnerCard.tsx b/src/components/park-owners/ParkOwnerCard.tsx
index 0b612438..a0cc1c10 100644
--- a/src/components/park-owners/ParkOwnerCard.tsx
+++ b/src/components/park-owners/ParkOwnerCard.tsx
@@ -13,7 +13,7 @@ const ParkOwnerCard = ({ company }: ParkOwnerCardProps) => {
const navigate = useNavigate();
const handleClick = () => {
- navigate(`/owners/${company.slug}/parks/`);
+ navigate(`/owners/${company.slug}`);
};
const getCompanyIcon = () => {
diff --git a/src/components/parks/ParkCard.tsx b/src/components/parks/ParkCard.tsx
index b8890bc8..6427925d 100644
--- a/src/components/parks/ParkCard.tsx
+++ b/src/components/parks/ParkCard.tsx
@@ -59,7 +59,7 @@ export function ParkCard({ park }: ParkCardProps) {
)}
{/* Gradient Overlay */}
-