5.3: PressReleaseStatus::badgeClass() zentralisiert + toten statusColor-Code entfernt

Status-Badge-Farblogik (ok/warn/err/muted) aus 7 divergenten match-Bloecken in eine Enum-Methode gezogen. Archiviert/Entwurf jetzt konsistent 'muted' (grau) auch auf Detail-/Edit-/Log-Seiten (vorher dort 'hub'-Akzent). Toter statusColor-Block (Flux-Farben, nie referenziert) in customer/show entfernt. flux:badge :color in admin/users bleibt bewusst separat (eigenes Farbvokabular, Einzel-Call-Site).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-07-02 10:36:15 +00:00
parent 0e08d8acc4
commit 55d0804917
8 changed files with 43 additions and 58 deletions

View file

@ -20,4 +20,19 @@ enum PressReleaseStatus: string
self::Archived => 'Archiviert',
};
}
/**
* CSS-Badge-Modifier für die Status-Darstellung (siehe `.badge`-Klassen im
* Hub-CSS). Neutrale Zustände (Entwurf/Archiviert) werden bewusst grau
* abgesetzt (`muted`), aktive Zustände farblich hervorgehoben.
*/
public function badgeClass(): string
{
return match ($this) {
self::Published => 'ok',
self::Review => 'warn',
self::Rejected => 'err',
self::Draft, self::Archived => 'muted',
};
}
}

View file

@ -397,12 +397,7 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung bearbeiten')] cl
<div class="space-y-8 pr-editor-shell" x-data="{ tagInput: '' }">
@php
$statusClass = match ($currentStatus) {
'published' => 'ok',
'review' => 'warn',
'rejected' => 'err',
default => 'hub',
};
$statusClass = $statusEnum?->badgeClass() ?? 'muted';
@endphp
{{-- Flash-Banner ersetzt durch <flux:toast /> im Layout. --}}

View file

@ -820,13 +820,7 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilungen')] class exten
'rejected' => 'is-row-err',
default => '',
};
$badgeClass = match ($status) {
'published' => 'ok',
'review' => 'warn',
'rejected' => 'err',
'archived', 'draft' => 'muted',
default => 'hub',
};
$badgeClass = $pr->status->badgeClass();
$portal = $pr->portal?->value ?? 'both';
$showPe = in_array($portal, ['presseecho', 'both'], true);
$showBp = in_array($portal, ['businessportal24', 'both'], true);

View file

@ -116,12 +116,7 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung')] class extends
<div class="space-y-8">
@php
$statusClass = match ($pr->status->value) {
'published' => 'ok',
'review' => 'warn',
'rejected' => 'err',
default => 'hub',
};
$statusClass = $pr->status->badgeClass();
@endphp
{{-- Flash-Banner ersetzt durch <flux:toast /> im Layout. --}}
@ -429,12 +424,7 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung')] class extends
<li class="text-[12.5px]">
<div class="flex flex-wrap items-center gap-2">
@php
$logClass = match ($log->to_status?->value) {
'published' => 'ok',
'review' => 'warn',
'rejected' => 'err',
default => 'hub',
};
$logClass = $log->to_status?->badgeClass() ?? 'muted';
@endphp
<span @class(['badge', $logClass])>{{ $log->to_status?->label() ?? $log->to_status }}</span>
@if ($log->from_status)

View file

@ -323,13 +323,7 @@ new #[Layout('components.layouts.app'), Title('Mein Dashboard')] class extends C
@forelse ($recent as $pr)
@php
$badgeClass = match ($pr->status->value) {
'published' => 'ok',
'review' => 'warn',
'rejected' => 'err',
'archived', 'draft' => 'muted',
default => 'hub',
};
$badgeClass = $pr->status->badgeClass();
$portal = $pr->portal?->value ?? 'both';
$showPe = in_array($portal, ['presseecho', 'both'], true);
$showBp = in_array($portal, ['businessportal24', 'both'], true);

View file

@ -432,13 +432,7 @@ new #[Layout('components.layouts.app'), Title('Meine Pressemitteilungen')] class
'rejected' => 'is-row-err',
default => '',
};
$badgeClass = match ($status) {
'published' => 'ok',
'review' => 'warn',
'rejected' => 'err',
'archived', 'draft' => 'muted',
default => 'hub',
};
$badgeClass = $pr->status->badgeClass();
$portal = $pr->portal?->value ?? 'both';
$showPe = in_array($portal, ['presseecho', 'both'], true);
$showBp = in_array($portal, ['businessportal24', 'both'], true);

View file

@ -189,13 +189,6 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung')] class extends
'latestRejection' => $latestRejection,
'contacts' => $pr->contacts,
'statusLogs' => $pr->statusLogs,
'statusColor' => match($pr->status->value) {
'published' => 'green',
'review' => 'yellow',
'rejected' => 'red',
'archived' => 'blue',
default => 'zinc',
},
];
}
@ -273,12 +266,7 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung')] class extends
<div class="space-y-8">
@php
$statusClass = match ($pr->status->value) {
'published' => 'ok',
'review' => 'warn',
'rejected' => 'err',
default => 'hub',
};
$statusClass = $pr->status->badgeClass();
@endphp
{{-- Flash-Banner ersetzt durch <flux:toast /> im Layout. --}}
@ -741,12 +729,7 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung')] class extends
<li class="text-[12.5px]">
<div class="flex flex-wrap items-center gap-2">
@php
$logClass = match ($log->to_status?->value) {
'published' => 'ok',
'review' => 'warn',
'rejected' => 'err',
default => 'hub',
};
$logClass = $log->to_status?->badgeClass() ?? 'muted';
@endphp
<span @class(['badge', $logClass])>{{ $log->to_status?->label() }}</span>
<span class="text-[11.5px] text-[color:var(--color-ink-3)]">

View file

@ -0,0 +1,20 @@
<?php
use App\Enums\PressReleaseStatus;
test('active statuses map to their accent badge class', function () {
expect(PressReleaseStatus::Published->badgeClass())->toBe('ok')
->and(PressReleaseStatus::Review->badgeClass())->toBe('warn')
->and(PressReleaseStatus::Rejected->badgeClass())->toBe('err');
});
test('neutral statuses are muted', function () {
expect(PressReleaseStatus::Draft->badgeClass())->toBe('muted')
->and(PressReleaseStatus::Archived->badgeClass())->toBe('muted');
});
test('every status resolves to a badge class', function () {
foreach (PressReleaseStatus::cases() as $status) {
expect($status->badgeClass())->toBeIn(['ok', 'warn', 'err', 'muted']);
}
});