5.4 (Teil 6): page-header in payments/invoices/legal/coupons/reports/newsletter
Component minimal-additiv erweitert (Defaults unveraendert): - size=sm (28px) fuer legal-requests/show - description-width=720px fuer breite Fliesstexte Umgestellt (letzter grosser Batch): - payments/index, payments/plans (720px, Aktionen) - invoices/index, coupons/index (720px, Badge via :meta, keine Aktionen) - legal-requests/index (Standard), legal-requests/show (sm, Status-Badge) - reports/slow-requests (Logdatei-Zaehler-Badge als Aktion) - newsletter/sync (Sync-Status via :meta, Dry-Run/Test-Sync-Buttons) CSS-Hash unveraendert -> keine neuen Klassen. 74 Tests gruen. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
27a77bfc50
commit
feda8be4d3
9 changed files with 97 additions and 136 deletions
|
|
@ -12,18 +12,24 @@
|
|||
'description' => '',
|
||||
|
||||
/**
|
||||
* Titel-Größe: md (Standard, 30px) | lg (Landing/Hero-Listen, 34px).
|
||||
* Titel-Größe: sm (28px) | md (Standard, 30px) | lg (Landing/Hero-Listen, 34px).
|
||||
* lg vergrößert zusätzlich die Beschreibung und den Button-Abstand.
|
||||
*/
|
||||
'size' => 'md',
|
||||
|
||||
/** Maximale Breite der Beschreibung: 640px (Standard) | 720px (breite Fließtexte) */
|
||||
'descriptionWidth' => '640px',
|
||||
])
|
||||
|
||||
@php
|
||||
$size = in_array($size, ['md', 'lg'], true) ? $size : 'md';
|
||||
$titleClass = $size === 'lg'
|
||||
? 'text-[34px] tracking-[-0.7px] leading-[1.1]'
|
||||
: 'text-[30px] tracking-[-0.6px] leading-[1.15]';
|
||||
$size = in_array($size, ['sm', 'md', 'lg'], true) ? $size : 'md';
|
||||
$titleClass = match ($size) {
|
||||
'sm' => 'text-[28px] tracking-[-0.5px] leading-[1.15]',
|
||||
'lg' => 'text-[34px] tracking-[-0.7px] leading-[1.1]',
|
||||
default => 'text-[30px] tracking-[-0.6px] leading-[1.15]',
|
||||
};
|
||||
$descriptionClass = $size === 'lg' ? 'text-[13.5px]' : 'text-[13px]';
|
||||
$descriptionMaxWidth = $descriptionWidth === '720px' ? 'max-w-[720px]' : 'max-w-[640px]';
|
||||
$actionsGap = $size === 'lg' ? 'gap-3' : 'gap-2';
|
||||
@endphp
|
||||
|
||||
|
|
@ -52,7 +58,7 @@
|
|||
</h1>
|
||||
|
||||
@if (filled($description))
|
||||
<p class="{{ $descriptionClass }} leading-[1.55] mt-2 m-0 max-w-[640px] text-[color:var(--color-ink-2)]">
|
||||
<p class="{{ $descriptionClass }} leading-[1.55] mt-2 m-0 {{ $descriptionMaxWidth }} text-[color:var(--color-ink-2)]">
|
||||
{{ $description }}
|
||||
</p>
|
||||
@endif
|
||||
|
|
|
|||
|
|
@ -14,21 +14,17 @@ new #[Layout('components.layouts.app'), Title('Gutscheine')] class extends Compo
|
|||
|
||||
<div class="space-y-8">
|
||||
{{-- ============== PAGE HEADER ============== --}}
|
||||
<header class="page-header">
|
||||
<div class="min-w-0">
|
||||
<div class="flex items-center gap-3 mb-3 flex-wrap">
|
||||
<span class="badge hub dot">{{ __('Admin Backend') }}</span>
|
||||
<span class="eyebrow muted">{{ __('Administration · Finanzen') }}</span>
|
||||
<x-portal.page-header
|
||||
:badge="__('Admin Backend')"
|
||||
:eyebrow="__('Administration · Finanzen')"
|
||||
:title="__('Gutscheine')"
|
||||
:description="__('Coupons sind in der Initialmigration vertagt (Entscheidung D-16). Eine Wiedereinführung wird später separat evaluiert – ggf. direkt über Stripe-Coupons.')"
|
||||
description-width="720px"
|
||||
>
|
||||
<x-slot:meta>
|
||||
<span class="badge warn">{{ __('Vertagt') }}</span>
|
||||
</div>
|
||||
<h1 class="text-[30px] font-bold tracking-[-0.6px] leading-[1.15] m-0 text-[color:var(--color-ink)]">
|
||||
{{ __('Gutscheine') }}
|
||||
</h1>
|
||||
<p class="text-[13px] leading-[1.55] mt-2 m-0 max-w-[720px] text-[color:var(--color-ink-2)]">
|
||||
{{ __('Coupons sind in der Initialmigration vertagt (Entscheidung D-16). Eine Wiedereinführung wird später separat evaluiert – ggf. direkt über Stripe-Coupons.') }}
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
</x-slot:meta>
|
||||
</x-portal.page-header>
|
||||
|
||||
<article class="panel">
|
||||
<div class="panel-head">
|
||||
|
|
|
|||
|
|
@ -122,21 +122,17 @@ new #[Layout('components.layouts.app'), Title('Legacy Rechnungen')] class extend
|
|||
|
||||
<div class="space-y-8">
|
||||
{{-- ============== PAGE HEADER ============== --}}
|
||||
<header class="page-header">
|
||||
<div class="min-w-0">
|
||||
<div class="flex items-center gap-3 mb-3 flex-wrap">
|
||||
<span class="badge hub dot">{{ __('Admin Backend') }}</span>
|
||||
<span class="eyebrow muted">{{ __('Administration · Finanzen') }}</span>
|
||||
<x-portal.page-header
|
||||
:badge="__('Admin Backend')"
|
||||
:eyebrow="__('Administration · Finanzen')"
|
||||
:title="__('Legacy Rechnungen')"
|
||||
:description="__('Legacy-Rechnungsarchiv mit read-only Übersicht, Filtern und PDF-Download. Der neue Stripe-Rechnungslauf folgt separat in Phase 8.')"
|
||||
description-width="720px"
|
||||
>
|
||||
<x-slot:meta>
|
||||
<span class="badge hub">{{ __('Legacy-Rechnungsarchiv') }}</span>
|
||||
</div>
|
||||
<h1 class="text-[30px] font-bold tracking-[-0.6px] leading-[1.15] m-0 text-[color:var(--color-ink)]">
|
||||
{{ __('Legacy Rechnungen') }}
|
||||
</h1>
|
||||
<p class="text-[13px] leading-[1.55] mt-2 m-0 max-w-[720px] text-[color:var(--color-ink-2)]">
|
||||
{{ __('Legacy-Rechnungsarchiv mit read-only Übersicht, Filtern und PDF-Download. Der neue Stripe-Rechnungslauf folgt separat in Phase 8.') }}
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
</x-slot:meta>
|
||||
</x-portal.page-header>
|
||||
|
||||
@if ($stats['unmapped_count'] > 0)
|
||||
<div class="px-4 py-3 rounded-[5px] border text-[12.5px] flex items-start gap-3
|
||||
|
|
|
|||
|
|
@ -60,20 +60,12 @@ new #[Layout('components.layouts.app'), Title('Recht & Compliance')] class exten
|
|||
|
||||
<div class="space-y-8">
|
||||
{{-- ============== PAGE HEADER ============== --}}
|
||||
<header class="page-header">
|
||||
<div class="min-w-0">
|
||||
<div class="flex items-center gap-3 mb-3 flex-nowrap whitespace-nowrap">
|
||||
<span class="badge hub dot">{{ __('Admin Backend') }}</span>
|
||||
<span class="eyebrow muted">{{ __('Administration · Recht & Compliance') }}</span>
|
||||
</div>
|
||||
<h1 class="text-[30px] font-bold tracking-[-0.6px] leading-[1.15] m-0 text-[color:var(--color-ink)]">
|
||||
{{ __('Recht & Compliance') }}
|
||||
</h1>
|
||||
<p class="text-[13px] leading-[1.55] mt-2 m-0 max-w-[640px] text-[color:var(--color-ink-2)]">
|
||||
{{ __('DSGVO-Anonymisierung, Persönlichkeitsrechte und Meldungen zu Pressemitteilungen – manuelle Bearbeitung, keine KI.') }}
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
<x-portal.page-header
|
||||
:badge="__('Admin Backend')"
|
||||
:eyebrow="__('Administration · Recht & Compliance')"
|
||||
:title="__('Recht & Compliance')"
|
||||
:description="__('DSGVO-Anonymisierung, Persönlichkeitsrechte und Meldungen zu Pressemitteilungen – manuelle Bearbeitung, keine KI.')"
|
||||
/>
|
||||
|
||||
{{-- ============== KPI-Reihe ============== --}}
|
||||
<section class="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||
|
|
|
|||
|
|
@ -83,24 +83,21 @@ new #[Layout('components.layouts.app'), Title('Anfrage · Recht & Compliance')]
|
|||
|
||||
<div class="space-y-8">
|
||||
{{-- ============== PAGE HEADER ============== --}}
|
||||
<header class="page-header">
|
||||
<div class="min-w-0">
|
||||
<div class="flex items-center gap-3 mb-3 flex-wrap">
|
||||
<span class="badge hub dot">{{ __('Admin Backend') }}</span>
|
||||
<span class="eyebrow muted">{{ __('Recht & Compliance · Anfrage') }}</span>
|
||||
<x-portal.page-header
|
||||
size="sm"
|
||||
:badge="__('Admin Backend')"
|
||||
:eyebrow="__('Recht & Compliance · Anfrage')"
|
||||
:title="$request->type->label()"
|
||||
>
|
||||
<x-slot:meta>
|
||||
<span class="badge dot {{ $this->statusBadgeClass($request->status) }}">{{ $request->status->label() }}</span>
|
||||
</div>
|
||||
<h1 class="text-[28px] font-bold tracking-[-0.5px] leading-[1.15] m-0 text-[color:var(--color-ink)]">
|
||||
{{ $request->type->label() }}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap items-center gap-2 flex-shrink-0">
|
||||
</x-slot:meta>
|
||||
<x-slot:actions>
|
||||
<flux:button icon="arrow-left" variant="filled" href="{{ route('admin.legal-requests.index') }}" wire:navigate>
|
||||
{{ __('Zurück') }}
|
||||
</flux:button>
|
||||
</div>
|
||||
</header>
|
||||
</x-slot:actions>
|
||||
</x-portal.page-header>
|
||||
|
||||
@if ($notification)
|
||||
<div x-data="{ show: true }" x-init="setTimeout(() => show = false, 3000)" x-show="show" x-transition
|
||||
|
|
|
|||
|
|
@ -88,34 +88,28 @@ new #[Layout('components.layouts.app'), Title('Newsletter Sync')] class extends
|
|||
|
||||
<div class="space-y-8">
|
||||
{{-- ============== PAGE HEADER ============== --}}
|
||||
<header class="page-header">
|
||||
<div class="min-w-0">
|
||||
<div class="flex items-center gap-3 mb-3 flex-wrap">
|
||||
<span class="badge hub dot">{{ __('Admin Backend') }}</span>
|
||||
<span class="eyebrow muted">{{ __('Administration · Newsletter') }}</span>
|
||||
<x-portal.page-header
|
||||
:badge="__('Admin Backend')"
|
||||
:eyebrow="__('Administration · Newsletter')"
|
||||
:title="__('Newsletter Synchronisierung')"
|
||||
:description="__('Vorbereitung fuer die kuenftige externe API-Anbindung. Aktuell ist nur das technische Grundgeruest aktiv.')"
|
||||
>
|
||||
<x-slot:meta>
|
||||
@if ($syncConfig['enabled'])
|
||||
<span class="badge ok dot">{{ __('Sync aktiv') }}</span>
|
||||
@else
|
||||
<span class="badge dot">{{ __('Sync deaktiviert') }}</span>
|
||||
@endif
|
||||
</div>
|
||||
<h1 class="text-[30px] font-bold tracking-[-0.6px] leading-[1.15] m-0 text-[color:var(--color-ink)]">
|
||||
{{ __('Newsletter Synchronisierung') }}
|
||||
</h1>
|
||||
<p class="text-[13px] leading-[1.55] mt-2 m-0 max-w-[640px] text-[color:var(--color-ink-2)]">
|
||||
{{ __('Vorbereitung fuer die kuenftige externe API-Anbindung. Aktuell ist nur das technische Grundgeruest aktiv.') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-2 flex-shrink-0">
|
||||
</x-slot:meta>
|
||||
<x-slot:actions>
|
||||
<flux:button size="sm" variant="filled" icon="eye" wire:click="triggerDryRun">
|
||||
{{ __('Dry Run') }}
|
||||
</flux:button>
|
||||
<flux:button size="sm" variant="primary" icon="play" wire:click="triggerTestSync">
|
||||
{{ __('Test-Sync ausfuehren') }}
|
||||
</flux:button>
|
||||
</div>
|
||||
</header>
|
||||
</x-slot:actions>
|
||||
</x-portal.page-header>
|
||||
|
||||
@if ($dryRunMessage)
|
||||
<div class="px-4 py-3 rounded-[5px] border text-[12.5px] flex items-start gap-3
|
||||
|
|
|
|||
|
|
@ -156,28 +156,22 @@ new #[Layout('components.layouts.app'), Title('Zahlungen')] class extends Compon
|
|||
|
||||
<div class="space-y-8">
|
||||
{{-- ============== PAGE HEADER ============== --}}
|
||||
<header class="page-header">
|
||||
<div class="min-w-0">
|
||||
<div class="flex items-center gap-3 mb-3 flex-wrap">
|
||||
<span class="badge hub dot">{{ __('Admin Backend') }}</span>
|
||||
<span class="eyebrow muted">{{ __('Administration · Finanzen') }}</span>
|
||||
</div>
|
||||
<h1 class="text-[30px] font-bold tracking-[-0.6px] leading-[1.15] m-0 text-[color:var(--color-ink)]">
|
||||
{{ __('Zahlungen') }}
|
||||
</h1>
|
||||
<p class="text-[13px] leading-[1.55] mt-2 m-0 max-w-[720px] text-[color:var(--color-ink-2)]">
|
||||
{{ __('Stripe-Abos, Einmalkäufe und der lokale Rechnungsausgang (STR-/MAN-Kreis) auf einen Blick. Stripe bleibt Zahlungs- und Belegquelle — diese Übersicht spiegelt die per Webhook synchronisierten Daten.') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<x-portal.page-header
|
||||
:badge="__('Admin Backend')"
|
||||
:eyebrow="__('Administration · Finanzen')"
|
||||
:title="__('Zahlungen')"
|
||||
:description="__('Stripe-Abos, Einmalkäufe und der lokale Rechnungsausgang (STR-/MAN-Kreis) auf einen Blick. Stripe bleibt Zahlungs- und Belegquelle — diese Übersicht spiegelt die per Webhook synchronisierten Daten.')"
|
||||
description-width="720px"
|
||||
>
|
||||
<x-slot:actions>
|
||||
<flux:button size="sm" variant="filled" icon="archive-box" :href="route('admin.invoices.index')" wire:navigate>
|
||||
{{ __('Legacy-Rechnungen') }}
|
||||
</flux:button>
|
||||
<flux:button size="sm" variant="primary" icon="rectangle-stack" :href="route('admin.payments.plans')" wire:navigate>
|
||||
{{ __('Tarife & Pakete') }}
|
||||
</flux:button>
|
||||
</div>
|
||||
</header>
|
||||
</x-slot:actions>
|
||||
</x-portal.page-header>
|
||||
|
||||
@if ($notification)
|
||||
<div x-data="{ show: true }" x-init="setTimeout(() => show = false, 3500)" x-show="show" x-transition
|
||||
|
|
|
|||
|
|
@ -127,25 +127,19 @@ new #[Layout('components.layouts.app'), Title('Tarife & Pakete')] class extends
|
|||
|
||||
<div class="space-y-8">
|
||||
{{-- ============== PAGE HEADER ============== --}}
|
||||
<header class="page-header">
|
||||
<div class="min-w-0">
|
||||
<div class="flex items-center gap-3 mb-3 flex-wrap">
|
||||
<span class="badge hub dot">{{ __('Admin Backend') }}</span>
|
||||
<span class="eyebrow muted">{{ __('Administration · Finanzen') }}</span>
|
||||
</div>
|
||||
<h1 class="text-[30px] font-bold tracking-[-0.6px] leading-[1.15] m-0 text-[color:var(--color-ink)]">
|
||||
{{ __('Tarife & Pakete') }}
|
||||
</h1>
|
||||
<p class="text-[13px] leading-[1.55] mt-2 m-0 max-w-[720px] text-[color:var(--color-ink-2)]">
|
||||
{{ __('Preise, Kontingente und Limits der Tarife pflegen. Änderungen erscheinen sofort auf der Buchungs-Seite und werden direkt nach Stripe synchronisiert.') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<x-portal.page-header
|
||||
:badge="__('Admin Backend')"
|
||||
:eyebrow="__('Administration · Finanzen')"
|
||||
:title="__('Tarife & Pakete')"
|
||||
:description="__('Preise, Kontingente und Limits der Tarife pflegen. Änderungen erscheinen sofort auf der Buchungs-Seite und werden direkt nach Stripe synchronisiert.')"
|
||||
description-width="720px"
|
||||
>
|
||||
<x-slot:actions>
|
||||
<flux:button size="sm" variant="filled" icon="credit-card" :href="route('admin.payments.index')" wire:navigate>
|
||||
{{ __('Zahlungen') }}
|
||||
</flux:button>
|
||||
</div>
|
||||
</header>
|
||||
</x-slot:actions>
|
||||
</x-portal.page-header>
|
||||
|
||||
@if ($savedMessage)
|
||||
<div class="px-4 py-3 rounded-[5px] border text-[12.5px] flex items-start gap-3
|
||||
|
|
|
|||
|
|
@ -53,24 +53,16 @@ new #[Layout('components.layouts.app'), Title('Performance Reports')] class exte
|
|||
|
||||
<div class="space-y-8">
|
||||
{{-- ============== PAGE HEADER ============== --}}
|
||||
<header class="page-header">
|
||||
<div class="min-w-0">
|
||||
<div class="flex items-center gap-3 mb-3 flex-nowrap whitespace-nowrap">
|
||||
<span class="badge hub dot">{{ __('Admin Backend') }}</span>
|
||||
<span class="eyebrow muted">{{ __('Administration · Reports') }}</span>
|
||||
</div>
|
||||
<h1 class="text-[30px] font-bold tracking-[-0.6px] leading-[1.15] m-0 text-[color:var(--color-ink)]">
|
||||
{{ __('Performance Reports') }}
|
||||
</h1>
|
||||
<p class="text-[13px] leading-[1.55] mt-2 m-0 max-w-[640px] text-[color:var(--color-ink-2)]">
|
||||
{{ __('Auswertung der Slow-Admin-Request-Logs aus dem admin_slow Log-Kanal.') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-2 flex-shrink-0">
|
||||
<x-portal.page-header
|
||||
:badge="__('Admin Backend')"
|
||||
:eyebrow="__('Administration · Reports')"
|
||||
:title="__('Performance Reports')"
|
||||
:description="__('Auswertung der Slow-Admin-Request-Logs aus dem admin_slow Log-Kanal.')"
|
||||
>
|
||||
<x-slot:actions>
|
||||
<span class="badge hub">{{ __('Logdateien') }}: {{ $report['summary']['files'] }}</span>
|
||||
</div>
|
||||
</header>
|
||||
</x-slot:actions>
|
||||
</x-portal.page-header>
|
||||
|
||||
{{-- ============== FILTER-PANEL ============== --}}
|
||||
<article class="panel">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue