Optimierung 2.8: <x-portal.pr-presubmit-check> Blade-Component

Den in allen vier PM-Editoren identischen, rein praesentationalen
Pre-Submit-Checklisten-Block (~34 Zeilen je Datei) in eine
Blade-Component ausgelagert, die $this->presubmitChecks als Prop nimmt.
Render-Test ergaenzt.

Bewusst konservativ: Nur dieser wire:model-freie, presentational Block
wurde extrahiert. Die interaktiven Markup-Panels (Tag-Input, Publish-
Schedule, Kontakt-/Firmen-Select) bleiben in den Editoren, da ihre
wire:model-/Alpine-Bindungen ohne visuelle QA nicht risikofrei in
Components zu ueberfuehren sind und die Tests gerendertes Markup nur
begrenzt abdecken.

Tests: volle Suite gruen (800 passed, 1 skipped).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-06-19 10:16:21 +00:00
parent 3a18a2b494
commit 153bac7a9c
6 changed files with 56 additions and 138 deletions

View file

@ -0,0 +1,37 @@
@props(['checks'])
@php
$okCount = collect($checks)->where('status', 'ok')->count();
$totalCount = count($checks);
@endphp
<div class="rounded-[4px] border border-[color:var(--color-bg-rule)] bg-[color:var(--color-bg-elev)] p-3 mb-3">
<div class="flex items-center justify-between mb-1">
<span class="eyebrow muted" style="font-size:9.5px;letter-spacing:0.16em;">
{{ __('Pre-Submit-Check') }}
</span>
<span class="text-[10.5px] font-mono font-semibold text-[color:var(--color-ok)]">
{{ $okCount }} / {{ $totalCount }} ok
</span>
</div>
@foreach ($checks as $check)
<div class="pr-check-row {{ $check['status'] }}">
<span class="ic">
@if ($check['status'] === 'ok')
<flux:icon name="check" variant="micro" class="size-3" />
@elseif ($check['status'] === 'warn')
<flux:icon name="exclamation-triangle" variant="micro" class="size-3" />
@else
<flux:icon name="x-mark" variant="micro" class="size-3" />
@endif
</span>
<span class="lbl">
{{ $check['label'] }}
@if (! empty($check['sub']))
<span class="sub">{{ $check['sub'] }}</span>
@endif
</span>
</div>
@endforeach
</div>

View file

@ -438,41 +438,7 @@ new #[Layout('components.layouts.app'), Title('Neue Pressemitteilung')] class ex
<span class="badge muted dot">{{ __('Neu') }}</span>
</div>
<div class="p-5">
<div
class="rounded-[4px] border border-[color:var(--color-bg-rule)] bg-[color:var(--color-bg-elev)] p-3 mb-3">
@php
$okCount = collect($this->presubmitChecks)->where('status', 'ok')->count();
$totalCount = count($this->presubmitChecks);
@endphp
<div class="flex items-center justify-between mb-1">
<span class="eyebrow muted" style="font-size:9.5px;letter-spacing:0.16em;">
{{ __('Pre-Submit-Check') }}
</span>
<span class="text-[10.5px] font-mono font-semibold text-[color:var(--color-ok)]">
{{ $okCount }} / {{ $totalCount }} ok
</span>
</div>
@foreach ($this->presubmitChecks as $check)
<div class="pr-check-row {{ $check['status'] }}">
<span class="ic">
@if ($check['status'] === 'ok')
<flux:icon name="check" variant="micro" class="size-3" />
@elseif ($check['status'] === 'warn')
<flux:icon name="exclamation-triangle" variant="micro" class="size-3" />
@else
<flux:icon name="x-mark" variant="micro" class="size-3" />
@endif
</span>
<span class="lbl">
{{ $check['label'] }}
@if (!empty($check['sub']))
<span class="sub">{{ $check['sub'] }}</span>
@endif
</span>
</div>
@endforeach
</div>
<x-portal.pr-presubmit-check :checks="$this->presubmitChecks" />
<flux:button type="button" variant="primary" icon="paper-airplane" class="w-full"
wire:click="save('review')" wire:loading.attr="disabled">

View file

@ -704,41 +704,7 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung bearbeiten')] cl
<span @class(['badge', $statusClass])>{{ $statusEnum?->label() ?? $currentStatus }}</span>
</div>
<div class="p-5">
<div
class="rounded-[4px] border border-[color:var(--color-bg-rule)] bg-[color:var(--color-bg-elev)] p-3 mb-3">
@php
$okCount = collect($this->presubmitChecks)->where('status', 'ok')->count();
$totalCount = count($this->presubmitChecks);
@endphp
<div class="flex items-center justify-between mb-1">
<span class="eyebrow muted" style="font-size:9.5px;letter-spacing:0.16em;">
{{ __('Pre-Submit-Check') }}
</span>
<span class="text-[10.5px] font-mono font-semibold text-[color:var(--color-ok)]">
{{ $okCount }} / {{ $totalCount }} ok
</span>
</div>
@foreach ($this->presubmitChecks as $check)
<div class="pr-check-row {{ $check['status'] }}">
<span class="ic">
@if ($check['status'] === 'ok')
<flux:icon name="check" variant="micro" class="size-3" />
@elseif ($check['status'] === 'warn')
<flux:icon name="exclamation-triangle" variant="micro" class="size-3" />
@else
<flux:icon name="x-mark" variant="micro" class="size-3" />
@endif
</span>
<span class="lbl">
{{ $check['label'] }}
@if (!empty($check['sub']))
<span class="sub">{{ $check['sub'] }}</span>
@endif
</span>
</div>
@endforeach
</div>
<x-portal.pr-presubmit-check :checks="$this->presubmitChecks" />
<flux:field>
<flux:label>{{ __('Neuer Status') }}</flux:label>

View file

@ -775,40 +775,7 @@ new #[Layout('components.layouts.app'), Title('Neue Pressemitteilung')] class ex
<span class="badge muted dot">{{ __('Entwurf') }}</span>
</div>
<div class="p-5">
<div class="rounded-[4px] border border-[color:var(--color-bg-rule)] bg-[color:var(--color-bg-elev)] p-3 mb-3">
@php
$okCount = collect($this->presubmitChecks)->where('status', 'ok')->count();
$totalCount = count($this->presubmitChecks);
@endphp
<div class="flex items-center justify-between mb-1">
<span class="eyebrow muted" style="font-size:9.5px;letter-spacing:0.16em;">
{{ __('Pre-Submit-Check') }}
</span>
<span class="text-[10.5px] font-mono font-semibold text-[color:var(--color-ok)]">
{{ $okCount }} / {{ $totalCount }} ok
</span>
</div>
@foreach ($this->presubmitChecks as $check)
<div class="pr-check-row {{ $check['status'] }}">
<span class="ic">
@if ($check['status'] === 'ok')
<flux:icon name="check" variant="micro" class="size-3" />
@elseif ($check['status'] === 'warn')
<flux:icon name="exclamation-triangle" variant="micro" class="size-3" />
@else
<flux:icon name="x-mark" variant="micro" class="size-3" />
@endif
</span>
<span class="lbl">
{{ $check['label'] }}
@if (! empty($check['sub']))
<span class="sub">{{ $check['sub'] }}</span>
@endif
</span>
</div>
@endforeach
</div>
<x-portal.pr-presubmit-check :checks="$this->presubmitChecks" />
<flux:modal.trigger name="confirm-submit-review">
<flux:button

View file

@ -701,40 +701,7 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung bearbeiten')] cl
@endif
</div>
<div class="p-5">
<div class="rounded-[4px] border border-[color:var(--color-bg-rule)] bg-[color:var(--color-bg-elev)] p-3 mb-3">
@php
$okCount = collect($this->presubmitChecks)->where('status', 'ok')->count();
$totalCount = count($this->presubmitChecks);
@endphp
<div class="flex items-center justify-between mb-1">
<span class="eyebrow muted" style="font-size:9.5px;letter-spacing:0.16em;">
{{ __('Pre-Submit-Check') }}
</span>
<span class="text-[10.5px] font-mono font-semibold text-[color:var(--color-ok)]">
{{ $okCount }} / {{ $totalCount }} ok
</span>
</div>
@foreach ($this->presubmitChecks as $check)
<div class="pr-check-row {{ $check['status'] }}">
<span class="ic">
@if ($check['status'] === 'ok')
<flux:icon name="check" variant="micro" class="size-3" />
@elseif ($check['status'] === 'warn')
<flux:icon name="exclamation-triangle" variant="micro" class="size-3" />
@else
<flux:icon name="x-mark" variant="micro" class="size-3" />
@endif
</span>
<span class="lbl">
{{ $check['label'] }}
@if (! empty($check['sub']))
<span class="sub">{{ $check['sub'] }}</span>
@endif
</span>
</div>
@endforeach
</div>
<x-portal.pr-presubmit-check :checks="$this->presubmitChecks" />
<flux:modal.trigger name="confirm-submit-review">
<flux:button

View file

@ -41,6 +41,21 @@ test('mount picks the alphabetically first contact of the default company', func
->assertSet('contactId', $contactA->id);
});
test('the pre-submit check component renders the checklist', function () {
/** @var TestCase $this */
$customer = User::factory()->create(['is_active' => true]);
$customer->assignRole('customer');
$company = Company::factory()->presseecho()->create(['name' => 'Alpha GmbH']);
$customer->companies()->attach($company->id, ['role' => 'owner']);
$this->actingAs($customer);
LivewireVolt::test('customer.press-releases.create')
->assertSee('Pre-Submit-Check')
->assertSee('Firma zugeordnet')
->assertSee('Alpha GmbH');
});
test('changing the company resets the contactId to the new company default', function () {
/** @var TestCase $this */
$customer = User::factory()->create(['is_active' => true]);