Paket-Vorteile: dynamische, im Admin pflegbare Vorteilsliste je Tarif
Neue JSON-Spalte plans.benefits (Migration + Cast + Plan::benefitsList()). Im Admin (Tarife & Pakete) pro Tarif zeilenweise pflegbar; die In-App- Buchungsseite rendert die Liste in den Tarif-Karten statt einer festen Zeile. Seeder/Factory mit Beispiel-Vorteilen. Single Source of Truth fuer Buchungsseite und (folgt separat) die oeffentliche Preise-Seite. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
7d03deddb1
commit
e96a11824b
8 changed files with 161 additions and 8 deletions
|
|
@ -25,6 +25,8 @@ new #[Layout('components.layouts.app'), Title('Tarife & Pakete')] class extends
|
|||
|
||||
public string $sortOrder = '0';
|
||||
|
||||
public string $benefits = '';
|
||||
|
||||
public ?string $savedMessage = null;
|
||||
|
||||
public function edit(int $planId): void
|
||||
|
|
@ -39,6 +41,7 @@ new #[Layout('components.layouts.app'), Title('Tarife & Pakete')] class extends
|
|||
$this->dailyLimit = $plan->daily_limit === null ? '' : (string) $plan->daily_limit;
|
||||
$this->isActive = $plan->is_active;
|
||||
$this->sortOrder = (string) $plan->sort_order;
|
||||
$this->benefits = implode("\n", $plan->benefitsList());
|
||||
$this->resetValidation();
|
||||
|
||||
Flux::modal('plan-edit')->show();
|
||||
|
|
@ -58,6 +61,7 @@ new #[Layout('components.layouts.app'), Title('Tarife & Pakete')] class extends
|
|||
'quota' => ['required', 'integer', 'min:0'],
|
||||
'dailyLimit' => ['nullable', 'integer', 'min:1'],
|
||||
'sortOrder' => ['required', 'integer', 'min:0'],
|
||||
'benefits' => ['nullable', 'string', 'max:2000'],
|
||||
],
|
||||
attributes: [
|
||||
'name' => __('Name'),
|
||||
|
|
@ -66,9 +70,17 @@ new #[Layout('components.layouts.app'), Title('Tarife & Pakete')] class extends
|
|||
'quota' => __('PM-Kontingent'),
|
||||
'dailyLimit' => __('Tageslimit'),
|
||||
'sortOrder' => __('Sortierung'),
|
||||
'benefits' => __('Vorteile'),
|
||||
],
|
||||
);
|
||||
|
||||
// Vorteile zeilenweise erfassen: je Zeile ein Vorteil, leere Zeilen raus.
|
||||
$benefitsList = collect(preg_split('/\r\n|\r|\n/', $this->benefits) ?: [])
|
||||
->map(fn (string $line): string => trim($line))
|
||||
->filter()
|
||||
->values()
|
||||
->all();
|
||||
|
||||
$plan = Plan::query()->findOrFail($this->editingPlanId);
|
||||
|
||||
$plan->fill([
|
||||
|
|
@ -79,6 +91,7 @@ new #[Layout('components.layouts.app'), Title('Tarife & Pakete')] class extends
|
|||
'daily_limit' => $validated['dailyLimit'] === null || $validated['dailyLimit'] === '' ? null : (int) $validated['dailyLimit'],
|
||||
'is_active' => $this->isActive,
|
||||
'sort_order' => (int) $validated['sortOrder'],
|
||||
'benefits' => $benefitsList,
|
||||
]);
|
||||
|
||||
$priceChanged = $plan->isDirty(['monthly_price_cents', 'yearly_price_cents']);
|
||||
|
|
@ -272,6 +285,10 @@ new #[Layout('components.layouts.app'), Title('Tarife & Pakete')] class extends
|
|||
<flux:input wire:model="sortOrder" type="number" min="0" :label="__('Sortierung')" />
|
||||
</div>
|
||||
|
||||
<flux:textarea wire:model="benefits" :label="__('Vorteile (eine Zeile = ein Vorteil)')" rows="5"
|
||||
:placeholder="__('Redaktionelle Prüfung inklusive Höheres Monatskontingent Günstigere Extra-Pressemitteilungen')"
|
||||
:description="__('Wird auf der Buchungs-Seite und der öffentlichen Preise-Seite als Vorteilsliste angezeigt.')" />
|
||||
|
||||
<flux:switch wire:model="isActive" :label="__('Tarif aktiv (buchbar und auf der Tarif-Seite sichtbar)')" />
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -562,10 +562,17 @@ new #[Layout('components.layouts.app'), Title('Buchungen & Add-ons')] class exte
|
|||
{{ __('Ohne Tageslimit') }}
|
||||
@endif
|
||||
</li>
|
||||
<li class="flex items-start gap-2">
|
||||
<flux:icon.check class="size-4 flex-shrink-0 mt-0.5 text-[color:var(--color-hub)]" />
|
||||
{{ __('Prüfung und Veröffentlichung inklusive') }}
|
||||
</li>
|
||||
@forelse ($plan->benefitsList() as $benefit)
|
||||
<li class="flex items-start gap-2">
|
||||
<flux:icon.check class="size-4 flex-shrink-0 mt-0.5 text-[color:var(--color-hub)]" />
|
||||
<span>{{ $benefit }}</span>
|
||||
</li>
|
||||
@empty
|
||||
<li class="flex items-start gap-2">
|
||||
<flux:icon.check class="size-4 flex-shrink-0 mt-0.5 text-[color:var(--color-hub)]" />
|
||||
{{ __('Prüfung und Veröffentlichung inklusive') }}
|
||||
</li>
|
||||
@endforelse
|
||||
</ul>
|
||||
|
||||
<div class="pt-2">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue