Fix entity filters

This commit is contained in:
gpt-engineer-app[bot]
2025-10-28 17:13:27 +00:00
parent 80e63ab355
commit e7bcba8fee
3 changed files with 322 additions and 23 deletions

View File

@@ -1,4 +1,4 @@
import { useState, useEffect } from 'react';
import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { Header } from '@/components/layout/Header';
import { Button } from '@/components/ui/button';
@@ -15,7 +15,7 @@ import { RideCard } from '@/components/rides/RideCard';
import { RideListView } from '@/components/rides/RideListView';
import { RideForm } from '@/components/admin/RideForm';
import { RideFilters, RideFilterState, defaultRideFilters } from '@/components/rides/RideFilters';
import { Ride } from '@/types/database';
import { Ride, Park } from '@/types/database';
import { supabase } from '@/integrations/supabase/client';
import { useAuth } from '@/hooks/useAuth';
import { useUserRole } from '@/hooks/useUserRole';
@@ -89,11 +89,180 @@ export default function Rides() {
}
};
const filteredRides = rides.filter(ride =>
ride.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
ride.park?.name?.toLowerCase().includes(searchQuery.toLowerCase()) ||
ride.manufacturer?.name?.toLowerCase().includes(searchQuery.toLowerCase())
);
const filteredAndSortedRides = React.useMemo(() => {
let filtered = rides.filter(ride => {
// Search filter
if (searchQuery) {
const searchTerm = searchQuery.toLowerCase();
const matchesSearch =
ride.name.toLowerCase().includes(searchTerm) ||
ride.park?.name?.toLowerCase().includes(searchTerm) ||
ride.manufacturer?.name?.toLowerCase().includes(searchTerm) ||
ride.designer?.name?.toLowerCase().includes(searchTerm);
if (!matchesSearch) return false;
}
// Category filter
if (filters.categories.length > 0 && !filters.categories.includes(ride.category)) {
return false;
}
// Status filter
if (filters.status !== 'all' && ride.status !== filters.status) {
return false;
}
// Country filter
if (filters.countries.length > 0) {
if (!ride.park?.location?.country || !filters.countries.includes(ride.park.location.country)) {
return false;
}
}
// States filter
if (filters.statesProvinces.length > 0) {
if (!ride.park?.location?.state_province || !filters.statesProvinces.includes(ride.park.location.state_province)) {
return false;
}
}
// Cities filter
if (filters.cities.length > 0) {
if (!ride.park?.location?.city || !filters.cities.includes(ride.park.location.city)) {
return false;
}
}
// Parks filter
if (filters.parks.length > 0) {
const parkId = (ride.park as Park)?.id;
if (!parkId || !filters.parks.includes(parkId)) {
return false;
}
}
// Manufacturer filter
if (filters.manufacturers.length > 0) {
if (!ride.manufacturer?.id || !filters.manufacturers.includes(ride.manufacturer.id)) {
return false;
}
}
// Designer filter
if (filters.designers.length > 0) {
if (!ride.designer?.id || !filters.designers.includes(ride.designer.id)) {
return false;
}
}
// Coaster type filter
if (filters.coasterTypes.length > 0) {
// Assuming coaster_type is a field on the ride
if (!ride.coaster_type || !filters.coasterTypes.includes(ride.coaster_type)) {
return false;
}
}
// Seating type filter
if (filters.seatingTypes.length > 0) {
if (!ride.seating_type || !filters.seatingTypes.includes(ride.seating_type)) {
return false;
}
}
// Intensity level filter
if (filters.intensityLevels.length > 0) {
if (!ride.intensity_level || !filters.intensityLevels.includes(ride.intensity_level)) {
return false;
}
}
// Track material filter
if (filters.trackMaterials.length > 0) {
if (!ride.track_material || !filters.trackMaterials.includes(ride.track_material)) {
return false;
}
}
// Speed filter
if (filters.minSpeed > 0 || filters.maxSpeed < 200) {
const speed = ride.max_speed_kmh || 0;
if (speed < filters.minSpeed || speed > filters.maxSpeed) {
return false;
}
}
// Height filter
if (filters.minHeight > 0 || filters.maxHeight < 150) {
const height = ride.max_height_meters || 0;
if (height < filters.minHeight || height > filters.maxHeight) {
return false;
}
}
// Length filter
if (filters.minLength > 0 || filters.maxLength < 3000) {
const length = ride.length_meters || 0;
if (length < filters.minLength || length > filters.maxLength) {
return false;
}
}
// Inversions filter
if (filters.minInversions > 0 || filters.maxInversions < 14) {
const inversions = ride.inversions || 0;
if (inversions < filters.minInversions || inversions > filters.maxInversions) {
return false;
}
}
// Has inversions checkbox
if (filters.hasInversions && (!ride.inversions || ride.inversions === 0)) {
return false;
}
// Opening date filter
if (filters.openingDateFrom || filters.openingDateTo) {
if (!ride.opening_date) {
return false;
}
const openingDate = new Date(ride.opening_date);
if (filters.openingDateFrom && openingDate < filters.openingDateFrom) {
return false;
}
if (filters.openingDateTo && openingDate > filters.openingDateTo) {
return false;
}
}
// Operating only filter
if (filters.operatingOnly && ride.status !== 'operating') {
return false;
}
return true;
});
// Apply sorting
filtered.sort((a, b) => {
switch (sortBy) {
case 'name':
return a.name.localeCompare(b.name);
case 'rating':
return (b.average_rating || 0) - (a.average_rating || 0);
case 'speed':
return (b.max_speed_kmh || 0) - (a.max_speed_kmh || 0);
case 'height':
return (b.max_height_meters || 0) - (a.max_height_meters || 0);
case 'reviews':
return (b.review_count || 0) - (a.review_count || 0);
default:
return 0;
}
});
return filtered;
}, [rides, searchQuery, sortBy, filters]);
const categories = [
@@ -150,7 +319,7 @@ export default function Rides() {
<div className="flex items-center justify-between">
<div className="flex flex-wrap items-center gap-1.5 sm:gap-2">
<Badge variant="secondary" className="flex items-center justify-center text-sm sm:text-base px-2 py-0.5 sm:px-3 sm:py-1 whitespace-nowrap">
{filteredRides.length} rides
{filteredAndSortedRides.length} rides
</Badge>
<Badge variant="outline" className="flex items-center justify-center text-xs sm:text-sm px-2 py-0.5 whitespace-nowrap">
{rides.filter(r => r.category === 'roller_coaster').length} coasters
@@ -276,15 +445,15 @@ export default function Rides() {
{/* Results Area */}
<div className="flex-1 min-w-0">
{filteredRides.length > 0 ? (
{filteredAndSortedRides.length > 0 ? (
viewMode === 'grid' ? (
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 2xl:grid-cols-6 3xl:grid-cols-7 gap-4 lg:gap-5 xl:gap-4 2xl:gap-5">
{filteredRides.map((ride) => (
{filteredAndSortedRides.map((ride) => (
<RideCard key={ride.id} ride={ride} showParkName={true} />
))}
</div>
) : (
<RideListView rides={filteredRides} onRideClick={(ride) => navigate(`/parks/${ride.park?.slug}/rides/${ride.slug}`)} />
<RideListView rides={filteredAndSortedRides} onRideClick={(ride) => navigate(`/parks/${ride.park?.slug}/rides/${ride.slug}`)} />
)
) : (
<div className="text-center py-12">