mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-24 12:11:12 -05:00
feat: Add track material column and filtering
This commit is contained in:
@@ -42,6 +42,10 @@ export function RideCreditFilters({
|
||||
const cities = new Set<string>();
|
||||
const parks = new Map<string, string>();
|
||||
const manufacturers = new Map<string, string>();
|
||||
const coasterTypes = new Set<string>();
|
||||
const seatingTypes = new Set<string>();
|
||||
const intensityLevels = new Set<string>();
|
||||
const trackMaterials = new Set<string>();
|
||||
|
||||
credits.forEach(credit => {
|
||||
const location = credit.rides?.parks?.locations;
|
||||
@@ -56,6 +60,22 @@ export function RideCreditFilters({
|
||||
if (credit.rides?.manufacturer?.id && credit.rides?.manufacturer?.name) {
|
||||
manufacturers.set(credit.rides.manufacturer.id, credit.rides.manufacturer.name);
|
||||
}
|
||||
|
||||
if (credit.rides?.coaster_type) {
|
||||
coasterTypes.add(credit.rides.coaster_type);
|
||||
}
|
||||
|
||||
if (credit.rides?.seating_type) {
|
||||
seatingTypes.add(credit.rides.seating_type);
|
||||
}
|
||||
|
||||
if (credit.rides?.intensity_level) {
|
||||
intensityLevels.add(credit.rides.intensity_level);
|
||||
}
|
||||
|
||||
if (credit.rides?.track_material) {
|
||||
trackMaterials.add(credit.rides.track_material);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -64,6 +84,10 @@ export function RideCreditFilters({
|
||||
cities: Array.from(cities).sort(),
|
||||
parks: Array.from(parks.entries()).map(([id, name]) => ({ id, name })).sort((a, b) => a.name.localeCompare(b.name)),
|
||||
manufacturers: Array.from(manufacturers.entries()).map(([id, name]) => ({ id, name })).sort((a, b) => a.name.localeCompare(b.name)),
|
||||
coasterTypes: Array.from(coasterTypes).sort(),
|
||||
seatingTypes: Array.from(seatingTypes).sort(),
|
||||
intensityLevels: Array.from(intensityLevels).sort(),
|
||||
trackMaterials: Array.from(trackMaterials).sort(),
|
||||
};
|
||||
}, [credits]);
|
||||
|
||||
@@ -295,6 +319,86 @@ export function RideCreditFilters({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{filterOptions.coasterTypes.length > 0 && (
|
||||
<div className={sectionSpacing}>
|
||||
<Label className="text-sm font-medium">Coaster Type</Label>
|
||||
<MultiSelectCombobox
|
||||
options={filterOptions.coasterTypes.map(type => ({
|
||||
label: type.charAt(0).toUpperCase() + type.slice(1),
|
||||
value: type
|
||||
}))}
|
||||
value={filters.coasterTypes || []}
|
||||
onValueChange={(values) =>
|
||||
onFilterChange('coasterTypes', values.length > 0 ? values : undefined)
|
||||
}
|
||||
placeholder="Select coaster types..."
|
||||
searchPlaceholder="Search types..."
|
||||
emptyText="No coaster types found"
|
||||
className={compact ? "h-9 text-sm" : ""}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{filterOptions.seatingTypes.length > 0 && (
|
||||
<div className={sectionSpacing}>
|
||||
<Label className="text-sm font-medium">Seating Type</Label>
|
||||
<MultiSelectCombobox
|
||||
options={filterOptions.seatingTypes.map(type => ({
|
||||
label: type.replace('_', ' ').replace(/\b\w/g, l => l.toUpperCase()),
|
||||
value: type
|
||||
}))}
|
||||
value={filters.seatingTypes || []}
|
||||
onValueChange={(values) =>
|
||||
onFilterChange('seatingTypes', values.length > 0 ? values : undefined)
|
||||
}
|
||||
placeholder="Select seating types..."
|
||||
searchPlaceholder="Search types..."
|
||||
emptyText="No seating types found"
|
||||
className={compact ? "h-9 text-sm" : ""}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{filterOptions.intensityLevels.length > 0 && (
|
||||
<div className={sectionSpacing}>
|
||||
<Label className="text-sm font-medium">Intensity Level</Label>
|
||||
<MultiSelectCombobox
|
||||
options={filterOptions.intensityLevels.map(level => ({
|
||||
label: level.charAt(0).toUpperCase() + level.slice(1),
|
||||
value: level
|
||||
}))}
|
||||
value={filters.intensityLevels || []}
|
||||
onValueChange={(values) =>
|
||||
onFilterChange('intensityLevels', values.length > 0 ? values : undefined)
|
||||
}
|
||||
placeholder="Select intensity levels..."
|
||||
searchPlaceholder="Search intensity..."
|
||||
emptyText="No intensity levels found"
|
||||
className={compact ? "h-9 text-sm" : ""}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{filterOptions.trackMaterials.length > 0 && (
|
||||
<div className={sectionSpacing}>
|
||||
<Label className="text-sm font-medium">Track Material</Label>
|
||||
<MultiSelectCombobox
|
||||
options={filterOptions.trackMaterials.map(tm => ({
|
||||
label: tm.charAt(0).toUpperCase() + tm.slice(1),
|
||||
value: tm
|
||||
}))}
|
||||
value={filters.trackMaterial || []}
|
||||
onValueChange={(values) =>
|
||||
onFilterChange('trackMaterial', values.length > 0 ? values : undefined)
|
||||
}
|
||||
placeholder="Select track materials..."
|
||||
searchPlaceholder="Search materials..."
|
||||
emptyText="No track materials found"
|
||||
className={compact ? "h-9 text-sm" : ""}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label>Inversions</Label>
|
||||
<div className="flex items-center gap-2">
|
||||
|
||||
Reference in New Issue
Block a user