+
+
+
+ {park.ride_count || 0}
+ rides
-
-
{park.coaster_count || 0}
-
+
+
+ {park.coaster_count || 0}
+ coasters
{park.review_count > 0 && (
-
-
-
{park.review_count} reviews
+
+
+ {park.review_count} reviews
)}
diff --git a/src/components/rides/RideListView.tsx b/src/components/rides/RideListView.tsx
new file mode 100644
index 00000000..8ffdb459
--- /dev/null
+++ b/src/components/rides/RideListView.tsx
@@ -0,0 +1,149 @@
+import { MapPin, Star, Zap, Ruler, Clock, Factory, Castle } from 'lucide-react';
+import { Card, CardContent } from '@/components/ui/card';
+import { Badge } from '@/components/ui/badge';
+import { Button } from '@/components/ui/button';
+import { Ride } from '@/types/database';
+import { cn } from '@/lib/utils';
+
+interface RideListViewProps {
+ rides: Ride[];
+ onRideClick: (ride: Ride) => void;
+}
+
+export function RideListView({ rides, onRideClick }: RideListViewProps) {
+ const getStatusColor = (status: string) => {
+ switch (status) {
+ case 'operating': return 'bg-green-500/20 text-green-400 border-green-500/30';
+ case 'seasonal': return 'bg-yellow-500/20 text-yellow-400 border-yellow-500/30';
+ case 'under_construction': return 'bg-blue-500/20 text-blue-400 border-blue-500/30';
+ case 'closed': return 'bg-red-500/20 text-red-400 border-red-500/30';
+ default: return 'bg-gray-500/20 text-gray-400 border-gray-500/30';
+ }
+ };
+
+ const formatCategory = (category: string) => {
+ return category.split('_').map(word =>
+ word.charAt(0).toUpperCase() + word.slice(1)
+ ).join(' ');
+ };
+
+ return (
+
+ {rides.map((ride, index) => (
+
onRideClick(ride)}
+ >
+
+
+ {/* Image */}
+
+ {ride.card_image_url ? (
+ <>
+

+
+ >
+ ) : (
+
+ )}
+
+ {/* Status Badge */}
+
+ {ride.status.replace('_', ' ').toUpperCase()}
+
+
+
+ {/* Content */}
+
+
+ {/* Header */}
+
+
+
+ {ride.name}
+
+
+ {ride.park && (
+
+
+ {ride.park.name}
+
+ )}
+
+ {ride.park?.location && (
+
+
+
+ {ride.park.location.city && `${ride.park.location.city}, `}
+ {ride.park.location.country}
+
+
+ )}
+
+
+ {/* Rating */}
+ {ride.average_rating > 0 && (
+
+
+ {ride.average_rating.toFixed(1)}
+
+ )}
+
+
+ {/* Tags */}
+
+
+ {formatCategory(ride.category)}
+
+ {ride.manufacturer && (
+
+
+ {ride.manufacturer.name}
+
+ )}
+
+
+
+ {/* Actions */}
+
+
+ {ride.review_count && ride.review_count > 0 && (
+ {ride.review_count} reviews
+ )}
+
+
+
+
+
+
+
+
+ ))}
+
+ );
+}
diff --git a/src/index.css b/src/index.css
index b36b18a8..7ad01b60 100644
--- a/src/index.css
+++ b/src/index.css
@@ -392,3 +392,20 @@ All colors MUST be HSL.
content-visibility: auto;
contain-intrinsic-size: 0 200px;
}
+
+/* Enhanced list view animations */
+@keyframes fadeInUp {
+ from {
+ opacity: 0;
+ transform: translateY(20px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+.animate-fade-in-up {
+ animation: fadeInUp 0.6s ease-out forwards;
+ opacity: 0;
+}
diff --git a/src/pages/Designers.tsx b/src/pages/Designers.tsx
index 2148c92b..b04e83fc 100644
--- a/src/pages/Designers.tsx
+++ b/src/pages/Designers.tsx
@@ -8,12 +8,14 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@
import { Collapsible, CollapsibleContent } from '@/components/ui/collapsible';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
-import { Search, SlidersHorizontal, Ruler, Plus, ChevronDown, Filter, PanelLeftClose, PanelLeftOpen } from 'lucide-react';
+import { Search, SlidersHorizontal, Ruler, Plus, ChevronDown, Filter, PanelLeftClose, PanelLeftOpen, Grid3X3, List } from 'lucide-react';
+import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { cn } from '@/lib/utils';
import { DesignerFilters, DesignerFilterState, defaultDesignerFilters } from '@/components/designers/DesignerFilters';
import { Company } from '@/types/database';
import { supabase } from '@/integrations/supabase/client';
import { DesignerCard } from '@/components/designers/DesignerCard';
+import { DesignerListView } from '@/components/designers/DesignerListView';
import { DesignerForm } from '@/components/admin/DesignerForm';
import { useAuth } from '@/hooks/useAuth';
import { useUserRole } from '@/hooks/useUserRole';
@@ -33,6 +35,7 @@ export default function Designers() {
const [sortBy, setSortBy] = useState('name');
const [filters, setFilters] = useState
(defaultDesignerFilters);
const [showFilters, setShowFilters] = useState(false);
+ const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid');
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
const [sidebarCollapsed, setSidebarCollapsed] = useState(() => {
const saved = localStorage.getItem('designers-sidebar-collapsed');
@@ -200,6 +203,12 @@ export default function Designers() {
Filters
+ setViewMode(v as 'grid' | 'list')} className="hidden md:inline-flex">
+
+
+
+
+