presseportale/resources/views/livewire/admin/footer-codes/edit.blade.php
Kevin Adametz 27a77bfc50 5.4 (Teil 5): page-header in roles/* + footer-codes/* + presets/*
Neun weitere Standard-Header (md) auf <x-portal.page-header>:
- roles/index (bedingter Anlegen-Button), roles/create (Guard-Badge via
  :meta), roles/edit (ID + Guard + bedingte Systemrolle via :meta)
- footer-codes/index, footer-codes/create, footer-codes/edit (ID + Global +
  Aktiv/Inaktiv via :meta, Titel als Beschreibung)
- presets/index, presets/create, presets/edit (ID via :meta)

Roles-/FooterCode-/Preset-Tests (23) gruen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 10:01:47 +00:00

242 lines
8.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
use App\Enums\Portal;
use App\Models\Category;
use App\Models\FooterCode;
use Illuminate\Support\Facades\DB;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Validate;
use Livewire\Volt\Component;
new #[Layout('components.layouts.app'), Title('Footer-Code bearbeiten')] class extends Component
{
public int $id = 0;
#[Validate('required|string|min:2|max:255')]
public string $title = '';
#[Validate('required|string|min:5')]
public string $content = '';
#[Validate('required|in:'.Portal::Both->value.','.Portal::Presseecho->value.','.Portal::Businessportal24->value)]
public string $portal = Portal::Both->value;
#[Validate('nullable|in:de,en')]
public ?string $language = null;
public bool $isGlobal = false;
public bool $isActive = true;
#[Validate('integer|min:0|max:1000')]
public int $priority = 0;
/** @var array<int, int> */
public array $categoryIds = [];
public function mount(int $id): void
{
$code = FooterCode::query()
->with('categories:id')
->findOrFail($id);
$this->id = $code->id;
$this->title = $code->title;
$this->content = $code->content;
$this->portal = $code->portal->value;
$this->language = $code->language;
$this->isGlobal = $code->is_global;
$this->isActive = $code->is_active;
$this->priority = $code->priority;
$this->categoryIds = $code->categories->pluck('id')->all();
}
public function save(): void
{
$this->validate();
$code = FooterCode::query()->findOrFail($this->id);
DB::transaction(function () use ($code): void {
$code->update([
'title' => $this->title,
'content' => $this->content,
'portal' => $this->portal,
'language' => $this->language,
'is_global' => $this->isGlobal,
'is_active' => $this->isActive,
'priority' => $this->priority,
]);
$code->categories()->sync(
$this->isGlobal ? [] : $this->categoryIds,
);
});
session()->flash('success', __('Footer-Code wurde aktualisiert.'));
$this->redirect(route('admin.footer-codes.index'), navigate: true);
}
public function delete(): void
{
$code = FooterCode::query()->findOrFail($this->id);
$code->delete();
session()->flash('success', __('Footer-Code wurde gelöscht.'));
$this->redirect(route('admin.footer-codes.index'), navigate: true);
}
public function with(): array
{
return [
'portalOptions' => Portal::cases(),
'categoryOptions' => Category::query()
->with(['translations' => fn ($q) => $q->where('locale', 'de')])
->orderBy('id')
->get()
->map(fn (Category $cat) => [
'id' => $cat->id,
'name' => $cat->localizedName(),
'portal' => $cat->portal->value,
]),
];
}
}; ?>
<div class="space-y-8">
{{-- ============== PAGE HEADER ============== --}}
<x-portal.page-header
:badge="__('Admin Backend')"
:eyebrow="__('Administration · Footer-Codes')"
:title="__('Footer-Code bearbeiten')"
:description="$title"
>
<x-slot:meta>
<span class="badge hub">ID #{{ $id }}</span>
@if ($isGlobal)
<span class="badge hub dot">{{ __('Global') }}</span>
@endif
@if ($isActive)
<span class="badge ok dot">{{ __('Aktiv') }}</span>
@else
<span class="badge dot">{{ __('Inaktiv') }}</span>
@endif
</x-slot:meta>
<x-slot:actions>
<flux:button variant="filled" icon="arrow-left" :href="route('admin.footer-codes.index')" wire:navigate>
{{ __('Zurück') }}
</flux:button>
</x-slot:actions>
</x-portal.page-header>
<form wire:submit="save" class="space-y-6">
<article class="panel">
<div class="panel-head">
<span class="section-eyebrow">{{ __('Stammdaten') }}</span>
</div>
<div class="p-5 space-y-4">
<flux:input wire:model="title" :label="__('Titel')" />
<flux:textarea
wire:model="content"
:label="__('HTML-/Text-Inhalt')"
rows="10"
/>
<div class="grid grid-cols-1 gap-4 md:grid-cols-3">
<flux:select wire:model="portal" :label="__('Portal')">
@foreach ($portalOptions as $option)
<option value="{{ $option->value }}">{{ $option->label() }}</option>
@endforeach
</flux:select>
<flux:select wire:model="language" :label="__('Sprache')">
<option value="">{{ __('Alle') }}</option>
<option value="de">{{ __('Deutsch') }}</option>
<option value="en">{{ __('Englisch') }}</option>
</flux:select>
<flux:input
wire:model="priority"
type="number"
min="0"
max="1000"
:label="__('Priorität')"
/>
</div>
</div>
</article>
<article class="panel">
<div class="panel-head">
<span class="section-eyebrow">{{ __('Sichtbarkeit') }}</span>
</div>
<div class="p-5 space-y-4">
<flux:switch
wire:model.live="isGlobal"
:label="__('Global ausspielen')"
:description="__('Wird unter allen Pressemitteilungen angezeigt – Kategorie-Zuordnung wird ignoriert.')"
/>
<flux:switch
wire:model="isActive"
:label="__('Aktiv')"
/>
</div>
</article>
@if (! $isGlobal)
<article class="panel">
<div class="panel-head">
<span class="section-eyebrow">{{ __('Kategorie-Zuordnung') }}</span>
</div>
<div class="p-5 grid grid-cols-1 gap-2 md:grid-cols-2 lg:grid-cols-3">
@forelse ($categoryOptions as $option)
<label class="flex items-center gap-2 rounded-[5px] border border-[color:var(--color-bg-rule)] bg-[color:var(--color-bg-elev)] px-3 py-2 hover:border-[color:var(--color-hub)]/30 cursor-pointer">
<input
type="checkbox"
wire:model="categoryIds"
value="{{ $option['id'] }}"
class="rounded border-[color:var(--color-bg-rule)]"
/>
<span class="text-[12.5px] text-[color:var(--color-ink)]">{{ $option['name'] }}</span>
</label>
@empty
<p class="text-[12.5px] text-[color:var(--color-ink-3)] m-0">
{{ __('Keine Kategorien vorhanden.') }}
</p>
@endforelse
</div>
</article>
@endif
<article class="panel" style="border-left:3px solid var(--color-err);">
<div class="panel-head">
<span class="section-eyebrow" style="color:var(--color-err);">{{ __('Danger Zone & Aktionen') }}</span>
</div>
<div class="p-5 flex items-center justify-between gap-2 flex-wrap">
<flux:button
type="button"
variant="danger"
icon="trash"
wire:click="delete"
wire:confirm="{{ __('Footer-Code wirklich löschen?') }}"
>
{{ __('Löschen') }}
</flux:button>
<div class="flex items-center gap-2">
<flux:button variant="filled" :href="route('admin.footer-codes.index')" wire:navigate>
{{ __('Abbrechen') }}
</flux:button>
<flux:button type="submit" variant="primary" icon="check">
{{ __('Speichern') }}
</flux:button>
</div>
</div>
</article>
</form>
</div>