From 7b3a4d7de8c7d7f1a96bfa139101a8214da57924 Mon Sep 17 00:00:00 2001 From: Kevin Adametz Date: Mon, 13 Jul 2026 14:59:33 +0000 Subject: [PATCH] PM-Detailseite: Inhaltspruefung (Gruen/Gelb/Rot) + Qualitaets-Score sichtbar - Neue Kachel "Inhaltspruefung" in Status & Verlauf (Badge je Ergebnis, "Ausstehend" ohne Pruefung); bei Gelb neutraler Hinweis, dass die Boost-Platzierung gruen gepruefte Meldungen voraussetzt - Content-Score-Panel des Editors in gemeinsame Komponente x-content-score-panel extrahiert und auf der Detailseite wiederverwendet (Score/100, Stufe, Abstand zur naechsten Schwelle) - PressReleaseClassification::badgeClass() (ok/warn/err) Co-Authored-By: Claude Fable 5 --- app/Enums/PressReleaseClassification.php | 9 ++++ .../components/content-score-panel.blade.php | 42 +++++++++++++++ .../customer/press-releases/edit.blade.php | 34 +------------ .../customer/press-releases/show.blade.php | 22 ++++++++ tests/Feature/PressReleaseShowPhase8aTest.php | 51 +++++++++++++++++++ 5 files changed, 126 insertions(+), 32 deletions(-) create mode 100644 resources/views/components/content-score-panel.blade.php diff --git a/app/Enums/PressReleaseClassification.php b/app/Enums/PressReleaseClassification.php index 28fd8366..292abe4c 100644 --- a/app/Enums/PressReleaseClassification.php +++ b/app/Enums/PressReleaseClassification.php @@ -24,4 +24,13 @@ enum PressReleaseClassification: string self::Red => 'Rot', }; } + + public function badgeClass(): string + { + return match ($this) { + self::Green => 'ok', + self::Yellow => 'warn', + self::Red => 'err', + }; + } } diff --git a/resources/views/components/content-score-panel.blade.php b/resources/views/components/content-score-panel.blade.php new file mode 100644 index 00000000..06741589 --- /dev/null +++ b/resources/views/components/content-score-panel.blade.php @@ -0,0 +1,42 @@ +{{-- Content-Score-Panel (Qualitäts-Feedback): Score 0–100 + Stufe samt + Abstand zur nächsten Schwelle. Gemeinsam genutzt von PM-Editor und + PM-Detailseite (13.07.); `note` trägt den kontextspezifischen Fußtext. --}} +@props(['score', 'tier' => null, 'note' => null]) + +@php + $tierEnum = $tier instanceof \App\Enums\PressReleaseContentTier + ? $tier + : ($tier ? \App\Enums\PressReleaseContentTier::from($tier) : null); + $tiers = config('scoring.content_score.tiers'); + $nextThreshold = $score < (int) $tiers['gepruft'] + ? (int) $tiers['gepruft'] + : ($score < (int) $tiers['hochwertig'] ? (int) $tiers['hochwertig'] : null); +@endphp + +
+
+ {{ __('Qualität') }} + @if ($tierEnum) + {{ $tierEnum->label() }} + @endif +
+
+
+ {{ $score }}/100 +
+ @if ($nextThreshold) +

+ {{ __('Noch :points Punkte bis zur nächsten Stufe.', ['points' => $nextThreshold - $score]) }} +

+ @else +

+ {{ __('Höchste Stufe erreicht.') }} +

+ @endif + @if ($note) +

+ {{ $note }} +

+ @endif +
+
diff --git a/resources/views/livewire/customer/press-releases/edit.blade.php b/resources/views/livewire/customer/press-releases/edit.blade.php index 79bdaf53..06b18cf6 100644 --- a/resources/views/livewire/customer/press-releases/edit.blade.php +++ b/resources/views/livewire/customer/press-releases/edit.blade.php @@ -809,38 +809,8 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung bearbeiten')] cl {{-- Content-Score (Qualitäts-Feedback während des Schreibens) --}} @if (! is_null($contentScore)) - @php - $tierEnum = $contentTier ? \App\Enums\PressReleaseContentTier::from($contentTier) : null; - $tiers = config('scoring.content_score.tiers'); - $nextThreshold = $contentScore < (int) $tiers['gepruft'] - ? (int) $tiers['gepruft'] - : ($contentScore < (int) $tiers['hochwertig'] ? (int) $tiers['hochwertig'] : null); - @endphp -
-
- {{ __('Qualität') }} - @if ($tierEnum) - {{ $tierEnum->label() }} - @endif -
-
-
- {{ $contentScore }}/100 -
- @if ($nextThreshold) -

- {{ __('Noch :points Punkte bis zur nächsten Stufe.', ['points' => $nextThreshold - $contentScore]) }} -

- @else -

- {{ __('Höchste Stufe erreicht.') }} -

- @endif -

- {{ __('Der Score wird nach dem Speichern automatisch neu berechnet.') }} -

-
-
+ @endif {{-- Portal (Read-only, Badge in Portal-Farbe) --}} diff --git a/resources/views/livewire/customer/press-releases/show.blade.php b/resources/views/livewire/customer/press-releases/show.blade.php index 16cebee9..7fc3e7aa 100644 --- a/resources/views/livewire/customer/press-releases/show.blade.php +++ b/resources/views/livewire/customer/press-releases/show.blade.php @@ -928,6 +928,23 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung')] class extends {{ $pr->status->label() }} + {{-- Ergebnis der KI-Inhaltsprüfung (13.07.): erklärt sichtbar, + warum die Boost-Platzierung (nur Grün) verfügbar ist oder nicht. --}} +
+
{{ __('Inhaltsprüfung') }}
+
+ @if ($pr->classification) + {{ $pr->classification->label() }} + @else + {{ __('Ausstehend') }} + @endif +
+ @if ($pr->classification === \App\Enums\PressReleaseClassification::Yellow) +
+ {{ __('Die Boost-Platzierung ist grün geprüften Meldungen vorbehalten.') }} +
+ @endif +
{{ __('Erstellt') }}
@@ -1047,6 +1064,11 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung')] class extends @endif
+ + {{-- Content-Score wie im Editor (gemeinsame Komponente, 13.07.). --}} + @if (! is_null($pr->content_score)) + + @endif
{{-- ============== TITELBILD (Hero) ============== --}} diff --git a/tests/Feature/PressReleaseShowPhase8aTest.php b/tests/Feature/PressReleaseShowPhase8aTest.php index c33df0b9..f602dfb3 100644 --- a/tests/Feature/PressReleaseShowPhase8aTest.php +++ b/tests/Feature/PressReleaseShowPhase8aTest.php @@ -1,6 +1,8 @@ $pr->id]) ->assertDontSee('Eigener Abbinder (Boilerplate)'); }); + +test('customer show zeigt das Pruefergebnis und den Qualitaets-Score', function () { + /** @var TestCase $this */ + ['customer' => $customer, 'pr' => $pr] = makeCustomerForShowPhase8a([ + 'status' => PressReleaseStatus::Published->value, + 'published_at' => now(), + 'classification' => PressReleaseClassification::Green->value, + 'content_score' => 87, + 'content_tier' => PressReleaseContentTier::Hochwertig->value, + ]); + $this->actingAs($customer); + + LivewireVolt::test('customer.press-releases.show', ['id' => $pr->id]) + ->assertSee('Inhaltsprüfung') + ->assertSee('Grün') + ->assertSee('Qualität') + ->assertSee('87') + ->assertSee('Hochwertig') + ->assertSee('Höchste Stufe erreicht.'); +}); + +test('customer show erklaert bei Gelb den fehlenden Boost neutral', function () { + /** @var TestCase $this */ + ['customer' => $customer, 'pr' => $pr] = makeCustomerForShowPhase8a([ + 'status' => PressReleaseStatus::Published->value, + 'published_at' => now(), + 'classification' => PressReleaseClassification::Yellow->value, + ]); + $this->actingAs($customer); + + LivewireVolt::test('customer.press-releases.show', ['id' => $pr->id]) + ->assertSee('Inhaltsprüfung') + ->assertSee('Gelb') + ->assertSee('Die Boost-Platzierung ist grün geprüften Meldungen vorbehalten.'); +}); + +test('customer show zeigt ohne Pruefung Ausstehend und kein Qualitaets-Panel', function () { + /** @var TestCase $this */ + ['customer' => $customer, 'pr' => $pr] = makeCustomerForShowPhase8a([ + 'classification' => null, + 'content_score' => null, + ]); + $this->actingAs($customer); + + LivewireVolt::test('customer.press-releases.show', ['id' => $pr->id]) + ->assertSee('Inhaltsprüfung') + ->assertSee('Ausstehend') + ->assertDontSee('Höchste Stufe erreicht.'); +});