['except' => ''], 'roleFilter' => ['except' => []], 'industrySector' => ['except' => ''], 'companySize' => ['except' => ''], 'foundedYearFrom' => ['except' => ''], 'foundedYearTo' => ['except' => ''], 'geographicPresence' => ['except' => ''], 'minRevenue' => ['except' => ''], 'maxRevenue' => ['except' => ''], 'sortBy' => ['except' => 'name'], 'sortDirection' => ['except' => 'asc'], 'viewMode' => ['except' => 'grid'], 'page' => ['except' => 1], ]; /** * Component initialization */ public function mount(): void { $this->loadIndustryStatistics(); $this->loadMarketData(); } /** * Load industry statistics with caching */ protected function loadIndustryStatistics(): void { $this->industryStats = Cache::remember( 'operators.industry.stats', now()->addHours(6), fn() => $this->calculateIndustryStatistics() ); } /** * Load market analysis data with caching */ protected function loadMarketData(): void { $this->marketData = Cache::remember( 'operators.market.data', now()->addHours(12), fn() => $this->loadMarketAnalysis() ); } /** * Calculate comprehensive industry statistics */ protected function calculateIndustryStatistics(): array { return [ 'total_operators' => Operator::active()->count(), 'park_operators' => Operator::active()->parkOperators()->count(), 'manufacturers' => Operator::active()->manufacturers()->count(), 'designers' => Operator::active()->designers()->count(), 'mixed_role' => Operator::active() ->whereHas('parks') ->whereHas('manufactured_rides') ->count(), 'sectors' => Operator::active() ->select('industry_sector', DB::raw('count(*) as count')) ->whereNotNull('industry_sector') ->groupBy('industry_sector') ->orderByDesc('count') ->get() ->pluck('count', 'industry_sector') ->toArray(), 'company_sizes' => [ 'small' => Operator::active()->companySize('small')->count(), 'medium' => Operator::active()->companySize('medium')->count(), 'large' => Operator::active()->companySize('large')->count(), 'enterprise' => Operator::active()->companySize('enterprise')->count(), ], 'geographic_distribution' => Operator::active() ->whereHas('parks.location') ->with('parks.location') ->get() ->flatMap(fn($op) => $op->parks->pluck('location.country')) ->countBy() ->sortDesc() ->take(10) ->toArray(), ]; } /** * Load market analysis data */ protected function loadMarketAnalysis(): array { return [ 'total_market_cap' => Operator::active() ->whereNotNull('market_cap') ->sum('market_cap'), 'total_revenue' => Operator::active() ->whereNotNull('annual_revenue') ->sum('annual_revenue'), 'average_parks_per_operator' => Operator::active() ->parkOperators() ->avg('total_parks'), 'top_operators_by_parks' => Operator::active() ->parkOperators() ->orderByDesc('total_parks') ->take(5) ->get(['name', 'total_parks']) ->toArray(), 'top_manufacturers_by_rides' => Operator::active() ->manufacturers() ->orderByDesc('total_rides_manufactured') ->take(5) ->get(['name', 'total_rides_manufactured']) ->toArray(), ]; } /** * Django parity dual-role search functionality */ public function dualRoleSearch($query, $roles = []) { return Operator::query() ->when($query, function ($q) use ($query) { $terms = explode(' ', trim($query)); foreach ($terms as $term) { if (strlen($term) >= 2) { $q->where(function ($subQuery) use ($term) { $subQuery->where('name', 'ilike', "%{$term}%") ->orWhere('description', 'ilike', "%{$term}%") ->orWhere('industry_sector', 'ilike', "%{$term}%") ->orWhere('headquarters_location', 'ilike', "%{$term}%") ->orWhereHas('location', function($locQuery) use ($term) { $locQuery->where('city', 'ilike', "%{$term}%") ->orWhere('state', 'ilike', "%{$term}%") ->orWhere('country', 'ilike', "%{$term}%"); }); }); } } }) ->when($roles, function ($q) use ($roles) { $q->where(function ($roleQuery) use ($roles) { if (in_array('park_operator', $roles)) { $roleQuery->whereHas('parks'); } if (in_array('ride_manufacturer', $roles)) { $roleQuery->orWhereHas('manufactured_rides'); } if (in_array('ride_designer', $roles)) { $roleQuery->orWhereHas('designed_rides'); } }); }) ->active() ->with(['location', 'parks:id,operator_id,name', 'manufactured_rides:id,manufacturer_id,name', 'designed_rides:id,designer_id,name']) ->withCount(['parks', 'manufactured_rides', 'designed_rides']); } /** * Apply advanced industry filters */ public function applyIndustryFilters($query) { return $query ->when($this->industrySector, fn($q, $sector) => $q->where('industry_sector', $sector)) ->when($this->companySize, fn($q, $size) => $q->companySize($size)) ->when($this->foundedYearFrom, fn($q, $year) => $q->where('founded_year', '>=', $year)) ->when($this->foundedYearTo, fn($q, $year) => $q->where('founded_year', '<=', $year)) ->when($this->geographicPresence, function ($q, $presence) { switch ($presence) { case 'regional': $q->whereHas('parks', function ($parkQ) { $parkQ->whereHas('location', function ($locQ) { $locQ->havingRaw('COUNT(DISTINCT country) = 1'); }); }); break; case 'international': $q->whereHas('parks', function ($parkQ) { $parkQ->whereHas('location', function ($locQ) { $locQ->havingRaw('COUNT(DISTINCT country) > 1'); }); }); break; } }) ->when($this->minRevenue, fn($q, $revenue) => $q->where('annual_revenue', '>=', $revenue)) ->when($this->maxRevenue, fn($q, $revenue) => $q->where('annual_revenue', '<=', $revenue)); } /** * Get operators with optimized caching */ public function getOperatorsProperty() { $cacheKey = "operators.listing." . md5(serialize([ 'search' => $this->search, 'roleFilter' => $this->roleFilter, 'industrySector' => $this->industrySector, 'companySize' => $this->companySize, 'foundedYearFrom' => $this->foundedYearFrom, 'foundedYearTo' => $this->foundedYearTo, 'geographicPresence' => $this->geographicPresence, 'minRevenue' => $this->minRevenue, 'maxRevenue' => $this->maxRevenue, 'sortBy' => $this->sortBy, 'sortDirection' => $this->sortDirection, 'page' => $this->getPage(), 'perPage' => $this->perPage, ])); return Cache::remember($cacheKey, now()->addMinutes(30), function() { $query = $this->dualRoleSearch($this->search, $this->roleFilter); $query = $this->applyIndustryFilters($query); // Apply sorting switch ($this->sortBy) { case 'name': $query->orderBy('name', $this->sortDirection); break; case 'founded_year': $query->orderBy('founded_year', $this->sortDirection); break; case 'parks_count': $query->orderBy('total_parks', $this->sortDirection); break; case 'rides_count': $query->orderBy('total_rides_manufactured', $this->sortDirection); break; case 'revenue': $query->orderBy('annual_revenue', $this->sortDirection); break; case 'market_influence': $query->orderByRaw('(total_parks * 10 + total_rides_manufactured * 2) ' . $this->sortDirection); break; default: $query->orderBy('name', 'asc'); } return $query->paginate($this->perPage); }); } /** * Update search and reset pagination */ public function updatedSearch(): void { $this->resetPage(); $this->invalidateCache(); } /** * Update role filter and reset pagination */ public function updatedRoleFilter(): void { $this->resetPage(); $this->invalidateCache(); } /** * Update any filter and reset pagination */ public function updatedIndustrySector(): void { $this->resetPage(); $this->invalidateCache(); } public function updatedCompanySize(): void { $this->resetPage(); $this->invalidateCache(); } public function updatedFoundedYearFrom(): void { $this->resetPage(); $this->invalidateCache(); } public function updatedFoundedYearTo(): void { $this->resetPage(); $this->invalidateCache(); } public function updatedGeographicPresence(): void { $this->resetPage(); $this->invalidateCache(); } public function updatedMinRevenue(): void { $this->resetPage(); $this->invalidateCache(); } public function updatedMaxRevenue(): void { $this->resetPage(); $this->invalidateCache(); } /** * Sort by specific column */ public function sortBy(string $column): void { if ($this->sortBy === $column) { $this->sortDirection = $this->sortDirection === 'asc' ? 'desc' : 'asc'; } else { $this->sortBy = $column; $this->sortDirection = 'asc'; } $this->resetPage(); $this->invalidateCache(); } /** * Change view mode */ public function setViewMode(string $mode): void { $this->viewMode = $mode; } /** * Clear all filters */ public function clearFilters(): void { $this->search = ''; $this->roleFilter = []; $this->industrySector = ''; $this->companySize = ''; $this->foundedYearFrom = ''; $this->foundedYearTo = ''; $this->geographicPresence = ''; $this->minRevenue = ''; $this->maxRevenue = ''; $this->sortBy = 'name'; $this->sortDirection = 'asc'; $this->resetPage(); $this->invalidateCache(); } /** * Toggle role filter */ public function toggleRoleFilter(string $role): void { if (in_array($role, $this->roleFilter)) { $this->roleFilter = array_values(array_diff($this->roleFilter, [$role])); } else { $this->roleFilter[] = $role; } $this->resetPage(); $this->invalidateCache(); } /** * Invalidate component cache */ protected function invalidateCache(): void { Cache::forget('operators.industry.stats'); Cache::forget('operators.market.data'); // Clear listing cache pattern - simplified approach $cacheKeys = [ 'operators.listing.*' ]; foreach ($cacheKeys as $pattern) { Cache::forget($pattern); } } /** * Get cache key for this component */ protected function getCacheKey(string $suffix = ''): string { return 'thrillwiki.' . class_basename(static::class) . '.' . $suffix; } /** * Remember data with caching */ protected function remember(string $key, $callback, int $ttl = 3600) { return Cache::remember($this->getCacheKey($key), $ttl, $callback); } /** * Render the component */ public function render() { return view('livewire.operators-listing', [ 'operators' => $this->operators, 'industryStats' => $this->industryStats, 'marketData' => $this->marketData, ]); } }