park = $park; $this->loadFilterOptions(); $this->setupSortOptions(); } /** * Load filter options specific to this park */ protected function loadFilterOptions(): void { $cacheKey = "park_rides_filters_{$this->park->id}"; $filterData = Cache::remember($cacheKey, 3600, function() { // Categories available in this park $categories = $this->park->rides() ->select('category') ->groupBy('category') ->get() ->map(function($ride) { $category = RideCategory::from($ride->category); return [ 'value' => $category->value, 'label' => $category->name, 'count' => $this->park->rides()->where('category', $category->value)->count() ]; }) ->toArray(); // Statuses available in this park $statuses = $this->park->rides() ->select('status') ->groupBy('status') ->get() ->map(function($ride) { $status = RideStatus::from($ride->status); return [ 'value' => $status->value, 'label' => $status->name, 'count' => $this->park->rides()->where('status', $status->value)->count() ]; }) ->toArray(); return compact('categories', 'statuses'); }); $this->categories = $filterData['categories']; $this->statuses = $filterData['statuses']; } /** * Setup sort options */ protected function setupSortOptions(): void { $this->sortOptions = [ 'name' => 'Name', 'opening_year' => 'Opening Year', 'height_requirement' => 'Height Requirement', 'created_at' => 'Date Added', 'updated_at' => 'Last Updated' ]; } /** * Update search term and reset pagination */ public function updatedSearchTerm(): void { $this->resetPage(); } /** * Update category filter */ public function updatedSelectedCategory(): void { $this->resetPage(); } /** * Update status filter */ public function updatedSelectedStatus(): void { $this->resetPage(); } /** * Update sort options */ public function updatedSortBy(): void { $this->resetPage(); } /** * Update sort direction */ public function updatedSortDirection(): void { $this->resetPage(); } /** * Set category filter */ public function setCategory(?string $category): void { $this->selectedCategory = $category === $this->selectedCategory ? null : $category; $this->resetPage(); } /** * Set status filter */ public function setStatus(?string $status): void { $this->selectedStatus = $status === $this->selectedStatus ? null : $status; $this->resetPage(); } /** * Set sort parameters */ public function setSortBy(string $field): void { if ($this->sortBy === $field) { $this->sortDirection = $this->sortDirection === 'asc' ? 'desc' : 'asc'; } else { $this->sortBy = $field; $this->sortDirection = 'asc'; } $this->resetPage(); } /** * Toggle filters visibility */ public function toggleFilters(): void { $this->showFilters = !$this->showFilters; } /** * Clear all filters */ public function clearFilters(): void { $this->searchTerm = ''; $this->selectedCategory = null; $this->selectedStatus = null; $this->sortBy = 'name'; $this->sortDirection = 'asc'; $this->resetPage(); } /** * Get filtered and sorted rides for this park */ public function getRidesProperty() { $cacheKey = $this->getCacheKey(); return Cache::remember($cacheKey, 300, function() { $query = $this->park->rides() ->with(['manufacturer', 'designer', 'photos']) ->when($this->searchTerm, function (Builder $query) { $query->where(function (Builder $subQuery) { $subQuery->where('name', 'ILIKE', "%{$this->searchTerm}%") ->orWhere('description', 'ILIKE', "%{$this->searchTerm}%") ->orWhereHas('manufacturer', function (Builder $manufacturerQuery) { $manufacturerQuery->where('name', 'ILIKE', "%{$this->searchTerm}%"); }) ->orWhereHas('designer', function (Builder $designerQuery) { $designerQuery->where('name', 'ILIKE', "%{$this->searchTerm}%"); }); }); }) ->when($this->selectedCategory, function (Builder $query) { $query->where('category', $this->selectedCategory); }) ->when($this->selectedStatus, function (Builder $query) { $query->where('status', $this->selectedStatus); }); // Apply sorting switch ($this->sortBy) { case 'name': $query->orderBy('name', $this->sortDirection); break; case 'opening_year': $query->orderBy('opening_year', $this->sortDirection) ->orderBy('name', 'asc'); break; case 'height_requirement': $query->orderBy('height_requirement', $this->sortDirection) ->orderBy('name', 'asc'); break; case 'created_at': $query->orderBy('created_at', $this->sortDirection); break; case 'updated_at': $query->orderBy('updated_at', $this->sortDirection); break; default: $query->orderBy('name', 'asc'); } return $query->paginate($this->perPage); }); } /** * Get park statistics */ public function getParkStatsProperty(): array { $cacheKey = "park_stats_{$this->park->id}"; return Cache::remember($cacheKey, 3600, function() { $totalRides = $this->park->rides()->count(); $operatingRides = $this->park->rides()->where('status', 'operating')->count(); $categories = $this->park->rides() ->select('category') ->groupBy('category') ->get() ->count(); $avgRating = $this->park->rides() ->whereHas('reviews') ->withAvg('reviews', 'rating') ->get() ->avg('reviews_avg_rating'); return [ 'total_rides' => $totalRides, 'operating_rides' => $operatingRides, 'categories' => $categories, 'avg_rating' => $avgRating ? round($avgRating, 1) : null ]; }); } /** * Get active filters count */ public function getActiveFiltersCountProperty(): int { return collect([ $this->searchTerm, $this->selectedCategory, $this->selectedStatus ])->filter()->count(); } /** * Get cache key for current state */ protected function getCacheKey(): string { return sprintf( 'park_rides_%d_%s_%s_%s_%s_%s_%d_%d', $this->park->id, md5($this->searchTerm), $this->selectedCategory ?? 'all', $this->selectedStatus ?? 'all', $this->sortBy, $this->sortDirection, $this->perPage, $this->getPage() ); } /** * Render the component */ public function render() { return view('livewire.park-rides-listing', [ 'rides' => $this->rides, 'parkStats' => $this->parkStats, 'activeFiltersCount' => $this->activeFiltersCount ]); } /** * Reset pagination when filters change */ public function resetPage($pageName = 'page'): void { $this->resetPage($pageName); // Clear cache when filters change $this->clearComponentCache(); } /** * Clear component-specific cache */ protected function clearComponentCache(): void { $patterns = [ "park_rides_{$this->park->id}_*", "park_stats_{$this->park->id}", "park_rides_filters_{$this->park->id}" ]; foreach ($patterns as $pattern) { Cache::forget($pattern); } } /** * Get pagination view */ public function paginationView(): string { return 'livewire.pagination-links'; } }