presseportale/resources/views/livewire/components/press-release-placeholder-picker.blade.php
Kevin Adametz a000238ca8 User Panel: Phase-8-Abschluss, Titelbild/Lizenzen/Zeitzonen und KI-Pruef-Pipeline
Phase 8 (Rest) + Umbauten vom 10./11.06.:
- Ein Titelbild pro PM (Cover 1280x580), SVG-Platzhalter-Set + Picker,
  PressReleaseCoverImage-Resolver
- Lizenz-/Rechteformular nach "Lizenztyp Bildupload" (7 Lizenztypen,
  Personen-/Sachrechte-Status, bedingte Pflichtfelder, Risikohinweise)
- Veroeffentlichungs-Box vereinfacht (Embargo aus der Form-UI entfernt),
  geplante Termine in Europe/Berlin (Speicherung UTC, DISPLAY_TIMEZONE)
- Quota-Stub (users.press_release_quota) + monatlicher Reset-Command
- Einreichungs-Modal einheitlich in Show/Create/Edit; Ghost-Buttons auf
  filled; PM-Editor-Layout responsive entkoppelt (.pr-editor-layout)

KI-Pruef-Pipeline (Phasen 1-5 des Entwicklungsplans):
- API-Haertung: status nicht mehr per API setzbar, eigene Submit-Route
  durch denselben Funnel (Blacklist, Quota, Status-Log)
- Klassifikation Rot/Gelb/Gruen asynchron (Queue classification,
  OpenAI-Treiber + deterministischer Fallback), ki_audits-Audit-Log
- Routing: Rot -> rejected + Mail, Gelb -> Review-Queue, Gruen ->
  Auto-Publish; Scheduler publiziert nur gruene faellige PMs
- Content-Score 0-100 -> Stufe (Standard/Geprueft/Hochwertig) inkl.
  Editor-Panel und Badges; Re-Klassifikation/-Score bei Aenderung
- Admin: KI-Badge + Filter, On-Demand-Pruefung mit Anbieter-Override

Suite: 442 passed, 4 skipped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 08:30:13 +00:00

82 lines
3.1 KiB
PHP

<?php
use App\Enums\PressReleasePlaceholder;
use Flux\Flux;
use Livewire\Volt\Component;
/**
* Auswahl-Modal für die SVG-Titelbild-Platzhalter.
*
* Wird in den PM-Forms eingebunden. Beim Bestätigen wird das Event
* `placeholder-selected` mit der gewählten Variante dispatched; das
* Eltern-Formular übernimmt den Wert in sein `placeholder_variant`-Feld.
*/
new class extends Component
{
public string $selected = '';
public function mount(?string $current = null): void
{
$this->selected = PressReleasePlaceholder::fromValueOrDefault($current)->value;
}
public function choose(string $variant): void
{
$this->selected = PressReleasePlaceholder::fromValueOrDefault($variant)->value;
}
public function confirm(): void
{
$this->dispatch('placeholder-selected', variant: $this->selected);
Flux::modal('placeholder-picker')->close();
}
public function with(): array
{
return [
'variants' => PressReleasePlaceholder::cases(),
];
}
}; ?>
<flux:modal name="placeholder-picker" class="w-full max-w-4xl">
<div class="space-y-5">
<div>
<flux:heading size="lg">{{ __('Titelbild-Platzhalter wählen') }}</flux:heading>
<flux:subheading>
{{ __('Wird verwendet, solange kein eigenes Titelbild hochgeladen ist.') }}
</flux:subheading>
</div>
<div class="grid max-h-[62vh] grid-cols-2 gap-3 overflow-y-auto pr-1 sm:grid-cols-3 lg:grid-cols-4">
@foreach ($variants as $variant)
<button type="button" wire:click="choose('{{ $variant->value }}')"
@class([
'group relative aspect-[16/9] overflow-hidden rounded-[6px] border-2 transition',
'border-[color:var(--color-hub)] ring-2 ring-[color:var(--color-hub)]/30' => $selected === $variant->value,
'border-transparent hover:border-[color:var(--color-bg-rule)]' => $selected !== $variant->value,
])
aria-pressed="{{ $selected === $variant->value ? 'true' : 'false' }}"
title="{{ $variant->label() }}">
<img src="{{ asset($variant->path()) }}" alt="{{ $variant->label() }}"
class="absolute inset-0 h-full w-full object-cover" loading="lazy" />
@if ($selected === $variant->value)
<span class="absolute right-1.5 top-1.5 flex size-5 items-center justify-center rounded-full bg-[color:var(--color-hub)] text-white">
<flux:icon.check variant="micro" class="size-3.5" />
</span>
@endif
</button>
@endforeach
</div>
<div class="flex justify-end gap-2">
<flux:modal.close>
<flux:button variant="filled">{{ __('Abbrechen') }}</flux:button>
</flux:modal.close>
<flux:button variant="primary" wire:click="confirm">
{{ __('Übernehmen') }}
</flux:button>
</div>
</div>
</flux:modal>