sortBy === $column) {
$this->sortDir = $this->sortDir === 'asc' ? 'desc' : 'asc';
} else {
$this->sortBy = $column;
$this->sortDir = 'asc';
}
$this->resetPage();
}
public function setView(string $view): void
{
$this->statusFilter = $view;
$this->resetPage();
}
public function resetFilters(): void
{
$this->search = '';
$this->statusFilter = 'all';
$this->portalFilter = 'all';
if ($this->companyFilter !== 'all') {
$this->companyFilter = 'all';
}
$this->resetPage();
}
public function updatedSearch(): void
{
$this->resetPage();
}
public function updatedStatusFilter(): void
{
$this->resetPage();
}
public function updatedCompanyFilter(): void
{
$this->resetPage();
}
public function updatedPortalFilter(): void
{
$this->resetPage();
}
public function submitForReview(int $id): void
{
$pr = $this->findMyPR($id);
if (!$pr) {
return;
}
try {
app(PressReleaseService::class)->submitForReview($pr);
Flux::toast(
heading: __('Eingereicht'),
text: __('Pressemitteilung zur Prüfung eingereicht.'),
variant: 'success',
);
} catch (BlacklistViolationException $e) {
Flux::toast(
heading: __('Automatisch abgelehnt'),
text: __('Unzulässiges Wort gefunden: ":word".', ['word' => $e->word]),
variant: 'danger',
duration: 8000,
);
} catch (BookingRequiredException|QuotaExceededException $e) {
Flux::toast(text: $e->getMessage(), variant: 'warning', duration: 8000);
} catch (\LogicException $e) {
Flux::toast(text: $e->getMessage(), variant: 'danger');
}
}
public function with(): array
{
$userId = auth()->id();
$context = app(CustomerCompanyContext::class);
$selectedCompanyId = $context->selectedCompanyId(auth()->user());
$base = PressRelease::withoutGlobalScopes()
->where('user_id', $userId)
->when($selectedCompanyId !== null, fn($q) => $q->where('company_id', $selectedCompanyId))
->when($selectedCompanyId === null && $this->companyFilter === 'assigned', fn($q) => $q->whereNotNull('company_id'))
->when($selectedCompanyId === null && $this->companyFilter === 'unassigned', fn($q) => $q->whereNull('company_id'));
$statusCountsRaw = (clone $base)->toBase()->selectRaw('status, COUNT(*) as aggregate')->groupBy('status')->pluck('aggregate', 'status');
$statusCounts = [
'all' => (int) $statusCountsRaw->sum(),
PressReleaseStatus::Published->value => (int) ($statusCountsRaw[PressReleaseStatus::Published->value] ?? 0),
PressReleaseStatus::Draft->value => (int) ($statusCountsRaw[PressReleaseStatus::Draft->value] ?? 0),
PressReleaseStatus::Review->value => (int) ($statusCountsRaw[PressReleaseStatus::Review->value] ?? 0),
PressReleaseStatus::Rejected->value => (int) ($statusCountsRaw[PressReleaseStatus::Rejected->value] ?? 0),
PressReleaseStatus::Archived->value => (int) ($statusCountsRaw[PressReleaseStatus::Archived->value] ?? 0),
];
$prs = (clone $base)
->with('company:id,name')
->when(filled($this->search), function ($q): void {
$term = $this->search;
$q->where('title', 'like', '%' . $term . '%');
})
->when($this->statusFilter !== 'all', fn($q) => $q->where('status', $this->statusFilter))
->when($this->portalFilter !== 'all', fn($q) => $q->where('portal', $this->portalFilter))
->orderBy(in_array($this->sortBy, ['title', 'status', 'created_at']) ? $this->sortBy : 'created_at', $this->sortDir)
->paginate(25);
return [
'pressReleases' => $prs,
'statusOptions' => PressReleaseStatus::cases(),
'portalOptions' => Portal::cases(),
'selectedCompany' => $context->selectedCompany(auth()->user()),
'hasGlobalCompanyContext' => $selectedCompanyId === null,
'statusCounts' => $statusCounts,
];
}
private function findMyPR(int $id): ?PressRelease
{
return PressRelease::withoutGlobalScopes()
->where('id', $id)
->where('user_id', auth()->id())
->first();
}
}; ?>
@php
$hasAnyFilter =
$search !== '' ||
$statusFilter !== 'all' ||
$portalFilter !== 'all' ||
($hasGlobalCompanyContext && $companyFilter !== 'all');
$hasAnyPR = $statusCounts['all'] > 0;
@endphp
{{-- Flash-Banner ersetzt durch
im Layout. --}}
{{-- ============== PAGE HEADER ============== --}}
{{-- ============== SAVED-VIEWS-TABS ============== --}}
@if ($hasAnyPR)
@endif
{{-- ============== FILTER + SUCHE ============== --}}
@if ($hasAnyPR)
@foreach ($portalOptions as $p)
@endforeach
@if ($hasGlobalCompanyContext)
@endif
{{-- Active-Chips --}}
@if ($hasAnyFilter)
{{ __('Aktiv') }}
@if ($statusFilter !== 'all')
@php $statusEnum = \App\Enums\PressReleaseStatus::tryFrom($statusFilter); @endphp
{{ __('Status') }}:
{{ $statusEnum?->label() ?? $statusFilter }}
@endif
@if ($portalFilter !== 'all')
@php $portalEnum = \App\Enums\Portal::tryFrom($portalFilter); @endphp
{{ __('Portal') }}:
{{ $portalEnum?->label() ?? $portalFilter }}
@endif
@if ($hasGlobalCompanyContext && $companyFilter !== 'all')
{{ __('Firma') }}:
{{ $companyFilter === 'assigned' ? __('Mit Firma') : __('Ohne Firma') }}
@endif
@if ($search !== '')
{{ __('Suche') }}:
„{{ \Illuminate\Support\Str::limit($search, 40) }}"
@endif
@endif
@endif
{{-- ============== TABELLE / EMPTY ============== --}}
@if ($pressReleases->isNotEmpty())
@if ($statusFilter !== 'all')
@php $sEnum = \App\Enums\PressReleaseStatus::tryFrom($statusFilter); @endphp
{{ $sEnum?->label() ?? __('Pressemitteilungen') }}
@else
{{ __('Alle Pressemitteilungen') }}
@endif
{{ __(':count Einträge', ['count' => $pressReleases->total()]) }}
{{ __('Status') }}
{{ __('Titel') }}
{{ __('Portal') }}
{{ __('Firma') }}
{{ __('Datum') }}
{{ __('Aktionen') }}
@foreach ($pressReleases as $pr)
@php
$status = $pr->status->value;
$rowClass = match ($status) {
'review' => 'is-row-warn',
'rejected' => 'is-row-err',
default => '',
};
$badgeClass = match ($status) {
'published' => 'ok',
'review' => 'warn',
'rejected' => 'err',
'archived', 'draft' => 'muted',
default => 'hub',
};
$portal = $pr->portal?->value ?? 'both';
$showPe = in_array($portal, ['presseecho', 'both'], true);
$showBp = in_array($portal, ['businessportal24', 'both'], true);
$dateSubLabel = match ($status) {
'published' => __('veröffentlicht'),
'review' => __('eingereicht'),
'rejected' => __('abgelehnt'),
'draft' => __('erstellt'),
'archived' => __('archiviert'),
default => __('erstellt'),
};
$primaryDate = match (true) {
$status === 'published' && $pr->published_at => $pr->published_at,
default => $pr->created_at,
};
@endphp
{{ $pr->status->label() }}
@if ($status === 'draft')
@endif
{{ $pr->title }}
PM-{{ $pr->id }}
@if ($showPe)
presseecho
@endif
@if ($showBp)
businessportal24
@endif
@if ($pr->company)
{{ $pr->company->name }}
@else
{{ __('— keine —') }}
@endif
{{ $primaryDate?->format('d.m.Y') }}
{{ $dateSubLabel }} · {{ $primaryDate?->format('H:i') }}
@if ($status === 'review' && $pr->scheduled_at && $pr->scheduled_at->isFuture())
{{ __('geplant') }} · {{ $pr->scheduledAtLocal()->format('d.m. H:i') }}
@endif
@if ($pr->embargo_at && $pr->embargo_at->isFuture())
{{ __('Embargo bis') }} {{ $pr->embargoAtLocal()->format('d.m.') }}
@endif
@if (in_array($status, ['draft', 'rejected']))
@endif
@endforeach
{{ $pressReleases->links('components.portal.pagination') }}
@elseif ($hasAnyPR && $search !== '')
{{-- Empty: Suche ohne Treffer --}}
{{ __('Keine Treffer für „:term"', ['term' => $search]) }}
{{ __('Wir konnten zu Ihrer Suche nichts finden. Prüfen Sie die Schreibweise oder schränken Sie den Suchbegriff ein.') }}
{{ __('Suche zurücksetzen') }}
@elseif ($hasAnyPR && $hasAnyFilter)
{{-- Empty: Filter ohne Treffer --}}
{{ __('Keine Mitteilungen mit diesen Filtern') }}
{{ __('Aktive Filter passen auf keine Einträge. Setzen Sie einen Filter zurück oder probieren Sie eine breitere Auswahl.') }}
{{ __('Alle Filter zurücksetzen') }}
@else
{{-- Empty: gar keine PMs überhaupt --}}
{{ __('Noch keine Pressemitteilungen') }}
{{ __('Starten Sie mit Ihrer ersten Mitteilung. Nach redaktioneller Prüfung erscheint sie i. d. R. binnen 4 Stunden werktags auf beiden Portalen.') }}
{{ __('Erste Pressemitteilung erstellen') }}
01
{{ __('Firma zuordnen') }}
02
{{ __('Mitteilung verfassen') }}
03
{{ __('Zur Prüfung senden') }}
@endif
{{-- ============== STATUS-AKTIONEN-LEGENDE ============== --}}
@if ($hasAnyPR)
{{ __('Aktionen je Status') }}
{{ __('Welche Aktionen pro Status verfügbar sind.') }}
{{ __('Entwurf') }}
- {{ __('Bearbeiten') }}
- {{ __('Vorschau') }}
-
{{ __('→ Zur Prüfung senden') }}
{{ __('In Prüfung') }}
- {{ __('Vorschau') }}
- {{ __('Warten auf Redaktion') }}
{{ __('Veröffentlicht') }}
- {{ __('Vorschau') }}
- {{ __('Statistik (bald)') }}
{{ __('Abgelehnt') }}
- {{ __('Bearbeiten') }}
-
{{ __('→ Erneut einreichen') }}
@endif