sortBy === $column) { $this->sortDir = $this->sortDir === 'asc' ? 'desc' : 'asc'; } else { $this->sortBy = $column; $this->sortDir = 'asc'; } $this->resetPage(); } public function with(): array { $sortable = ['name', 'email', 'is_active', 'press_releases_count', 'contacts_count', 'created_at']; $sort = in_array($this->sortBy, $sortable) ? $this->sortBy : 'name'; $sortsByCount = in_array($sort, ['press_releases_count', 'contacts_count'], true); $companiesQuery = Company::query() ->when($sortsByCount, fn ($query) => $query->withCount(['pressReleases', 'contacts'])) ->when($this->search, function ($query): void { $term = trim($this->search); if ($this->supportsFullTextSearch($term)) { $query->whereFullText(['name', 'email', 'slug'], $term); return; } $query->where(function ($searchQuery): void { $searchQuery->where('name', 'like', '%'.$this->search.'%')->orWhere('email', 'like', '%'.$this->search.'%'); }); }) ->when($this->activeFilter !== 'all', function ($query): void { $query->where('is_active', $this->activeFilter === 'active'); }) ->when($this->portalFilter !== 'all', function ($query): void { $query->where('portal', $this->portalFilter); }) ->when($this->userFilter !== 'all', function ($query): void { $query->where(function ($userScopedQuery): void { $userScopedQuery ->where('owner_user_id', (int) $this->userFilter) ->orWhereHas('users', fn ($userQuery) => $userQuery->where('users.id', (int) $this->userFilter)); }); }) ->when($this->contactFilter !== 'all', function ($query): void { $query->whereHas('contacts', fn ($contactQuery) => $contactQuery->where('contacts.id', (int) $this->contactFilter)); }) ->when($this->qualityFilter !== 'all', function ($query): void { match ($this->qualityFilter) { 'with_press_releases' => $query->whereHas('pressReleases'), 'without_press_releases' => $query->whereDoesntHave('pressReleases'), 'with_contacts' => $query->whereHas('contacts'), 'without_contacts' => $query->whereDoesntHave('contacts'), default => null, }; }) ->orderBy($sort, $this->sortDir); $companies = $companiesQuery->paginate(50); if (! $sortsByCount) { $this->hydrateCounts($companies); } return [ 'companies' => $companies, 'stats' => $this->stats(), 'portalOptions' => Portal::cases(), 'userLookupResults' => $this->userLookupResults(), 'contactLookupResults' => $this->contactLookupResults(), ]; } /** * @return array{total: int, active: int, inactive: int} */ private function stats(): array { $portal = CurrentPortalContext::get()?->value ?? 'all'; $cache = app(AdminPerformanceCache::class); return $cache->remember($cache->companiesStatsKey($portal), AdminPerformanceCache::StatsTtl, function (): array { $stats = Company::query() ->toBase() ->selectRaw('COUNT(*) as total') ->selectRaw('SUM(CASE WHEN is_active = ? THEN 1 ELSE 0 END) as active', [true]) ->selectRaw('SUM(CASE WHEN is_active = ? THEN 1 ELSE 0 END) as inactive', [false]) ->first(); return [ 'total' => (int) ($stats->total ?? 0), 'active' => (int) ($stats->active ?? 0), 'inactive' => (int) ($stats->inactive ?? 0), ]; }); } private function hydrateCounts($companies): void { $companyIds = $companies->getCollection()->pluck('id'); if ($companyIds->isEmpty()) { return; } $pressReleaseCounts = PressRelease::query() ->whereIn('company_id', $companyIds) ->selectRaw('company_id, COUNT(*) as aggregate') ->groupBy('company_id') ->pluck('aggregate', 'company_id'); $contactCounts = Contact::query() ->whereIn('company_id', $companyIds) ->selectRaw('company_id, COUNT(*) as aggregate') ->groupBy('company_id') ->pluck('aggregate', 'company_id'); $companies->getCollection()->each(function (Company $company) use ($pressReleaseCounts, $contactCounts): void { $company->setAttribute('press_releases_count', (int) $pressReleaseCounts->get($company->id, 0)); $company->setAttribute('contacts_count', (int) $contactCounts->get($company->id, 0)); }); } private function supportsFullTextSearch(string $term): bool { return mb_strlen($term) >= 3 && in_array(DB::connection()->getDriverName(), ['mysql', 'pgsql'], true); } public function updatedSearch(): void { $this->resetPage(); } public function updatedActiveFilter(): void { $this->resetPage(); } public function updatedPortalFilter(): void { $this->resetPage(); } public function updatedUserFilter(): void { if (blank($this->userFilter)) { $this->userFilter = 'all'; } $this->userLookup = ''; $this->resetPage(); } public function updatedContactFilter(): void { if (blank($this->contactFilter)) { $this->contactFilter = 'all'; } $this->contactLookup = ''; $this->resetPage(); } public function updatedQualityFilter(): void { $this->resetPage(); } public function clearUserSearch(): void { $this->userFilter = 'all'; $this->userLookup = ''; $this->resetPage(); } public function clearContactSearch(): void { $this->contactFilter = 'all'; $this->contactLookup = ''; $this->resetPage(); } private function portalBadgeColor(?Portal $portal): string { return match ($portal) { Portal::Presseecho => 'blue', Portal::Businessportal24 => 'purple', Portal::Both => 'zinc', default => 'zinc', }; } private function userLookupResults() { $term = trim($this->userLookup); if ($term === '' && $this->userFilter === 'all') { return collect(); } return User::query() ->select(['id', 'name', 'email']) ->where(function ($query) use ($term): void { if ($this->userFilter !== 'all') { $query->where('id', (int) $this->userFilter); } if ($term !== '') { $query->orWhere(function ($searchQuery) use ($term): void { $searchQuery ->where('name', 'like', '%'.$term.'%') ->orWhere('email', 'like', '%'.$term.'%'); }); } }) ->orderBy('name') ->limit(20) ->get(); } private function contactLookupResults() { $term = trim($this->contactLookup); if ($term === '' && $this->contactFilter === 'all') { return collect(); } return Contact::withoutGlobalScopes() ->select(['id', 'company_id', 'first_name', 'last_name', 'email']) ->with('company:id,name') ->where(function ($query) use ($term): void { if ($this->contactFilter !== 'all') { $query->where('id', (int) $this->contactFilter); } if ($term !== '') { $query->orWhere(function ($searchQuery) use ($term): void { $searchQuery ->where('first_name', 'like', '%'.$term.'%') ->orWhere('last_name', 'like', '%'.$term.'%') ->orWhere('email', 'like', '%'.$term.'%'); }); } }) ->orderBy('last_name') ->orderBy('first_name') ->limit(20) ->get(); } }; ?>
{{-- ============== PAGE HEADER ============== --}}
{{ __('Admin Backend') }} {{ __('Stammdaten · Firmen') }}

{{ __('Firmen') }}

{{ __('Übersicht aller Firmen beider Portale, mit Filter, Datenqualität und Schnellaktionen.') }}

{{ __('Neue Firma') }}
{{-- ============== KPI-Reihe ============== --}}
{{ __('alle Portale') }} {{ __('Stammdaten-Basis') }} {{ __('produktiv') }} {{ __('für PMs nutzbar') }} {{ __('pausiert') }} {{ __('archiviert oder geblockt') }}
{{-- ============== FILTER-PANEL ============== --}}
{{ __('Filter & Suche') }}
@foreach($portalOptions as $portalOption) @endforeach
@foreach($userLookupResults as $userOption) {{ $userOption->name }} · {{ $userOption->email }} @endforeach {{ blank(trim($userLookup)) ? __('Usernamen oder E-Mail eingeben…') : __('Kein User gefunden.') }}
@foreach($contactLookupResults as $contactOption) @php($contactName = trim(($contactOption->first_name ?? '').' '.($contactOption->last_name ?? '')) ?: __('Kontakt ohne Name')) {{ $contactName }} @if($contactOption->email)· {{ $contactOption->email }} @endif · {{ $contactOption->company?->name ?? __('Unbekannte Firma') }} @endforeach {{ blank(trim($contactLookup)) ? __('Kontaktname oder E-Mail eingeben…') : __('Kein Kontakt gefunden.') }}
{{-- ============== TABELLE-PANEL ============== --}}
{{ __('Alle Firmen') }} {{ __(':count Einträge', ['count' => $companies->count()]) }}
{{ __('Aktionen') }} {{ __('Firma') }} {{ __('Kontakt') }} {{ __('Status') }} {{ __('Portal') }} {{ __('PMs') }} {{ __('Kontakte') }} {{ __('Hinzugefügt') }} @forelse($companies as $company) @php($logoUrl = $company->logoUrl())
@if ($logoUrl) {{ $company->name }} @else
@endif {{ \Illuminate\Support\Str::limit($company->name, 60) }}
{{ $company->email ?: __('Keine E-Mail') }}
{{ $company->phone ?: __('Kein Telefon') }}
@if ($company->is_active) {{ __('Aktiv') }} @else {{ __('Inaktiv') }} @endif {{ $company->portal?->label() ?? __('Unbekannt') }} @if ($company->press_releases_count > 0) {{ $company->press_releases_count }} {{ __('PMs') }} @else 0 @endif @if ($company->contacts_count > 0) {{ $company->contacts_count }} {{ __('Kontakte') }} @else 0 @endif {{ $company->created_at?->format('d.m.Y H:i') ?? '–' }}
@empty
{{ __('Keine Firmen gefunden') }}

{{ __('Passen Sie die Filter an oder legen Sie eine neue Firma an.') }}

@endforelse
{{ $companies->links('components.portal.pagination') }}