diff --git a/resources/views/livewire/customer/bookings.blade.php b/resources/views/livewire/customer/bookings.blade.php index 365e2d5..0f0b0a7 100644 --- a/resources/views/livewire/customer/bookings.blade.php +++ b/resources/views/livewire/customer/bookings.blade.php @@ -1,8 +1,10 @@ legacy_conditions, 'legacy_portal'); + + return Portal::tryFrom((string) $value)?->label() ?? __('Portal unbekannt'); + } + + /** + * Abrechnungsintervall eines Bestandsschutz-Postens als Label. + */ + public function legacyIntervalLabel(UserPaymentOption $option): string + { + return match (data_get($option->legacy_conditions, 'interval')) { + 'monthly' => __('Monat'), + default => __('Jahr'), + }; + } + public function with(): array { $user = auth()->user(); @@ -127,17 +151,97 @@ new #[Layout('components.layouts.app'), Title('Buchungen & Add-ons')] class exte + {{-- ============== BESTANDSSCHUTZ-PAKETE ============== --}} + {{-- Migrierte Legacy-Vereinbarungen als echte, gebuchte Pakete dargestellt: + eigener Block, Rahmen, Icon, Portal-Badge, klare Typo. --}} + @if ($legacyOptions->isNotEmpty()) +
+
+ {{ __('Ihr Bestandsschutz') }} +

+ {{ trans_choice('Ihr gebuchtes Paket|Ihre gebuchten Pakete', $legacyOptions->count()) }} +

+

+ {{ __('Ihre bisherigen Konditionen gelten unverändert weiter — unbegrenzte Pressemitteilungen, Abrechnung wie gewohnt per Rechnung.') }} +

+
+ +
$legacyOptions->count() > 1])> + @foreach ($legacyOptions as $option) + @php + $netCents = (int) data_get($option->legacy_conditions, 'net_cents', 0); + $legacyName = data_get($option->legacy_conditions, 'name') + ?? ($option->paymentOption?->article_number ?? __('Bestehende Vereinbarung')); + @endphp +
+ {{-- Akzent-Leiste --}} +
+
+
+
+
+ +
+
+
+ {{ __('Bestandsschutz') }} + {{ $this->legacyPortalLabel($option) }} +
+

+ {{ $legacyName }} +

+
+
+
+
+ {{ $this->formatEuro($netCents) }} +
+
+ {{ __('netto / :interval', ['interval' => $this->legacyIntervalLabel($option)]) }} +
+
+
+ +
    +
  • + + {{ __('Unbegrenzte') }} {{ __('Pressemitteilungen') }} +
  • +
  • + + {{ __('Konditionen gelten unverändert weiter') }} +
  • + @if ($option->current_period_end) +
  • + + {{ __('Nächste Rechnung am :date', ['date' => $option->current_period_end->format('d.m.Y')]) }} +
  • + @endif +
+
+
+ @endforeach +
+ + @if ($legacyOptions->count() > 1) +

+ {{ __('Ihre Pakete werden gemeinsam geführt und sind nur zusammen kündbar (keine Einzelkündigung).') }} +

+ @endif +
+ @endif + {{-- ============== AKTUELLER TARIF ============== --}} {{-- Erscheint erst, wenn eine Buchung existiert — vorher würde hier nur „kein Tarif" stehen und das Kontingent wäre irreführend. --}} - @if ($subscription || $legacyOptions->isNotEmpty() || $openPurchases->isNotEmpty()) + @if ($subscription || $openPurchases->isNotEmpty())
{{ __('Aktueller Tarif') }} @if ($currentPlan) {{ $currentPlan->name }} - @elseif ($legacyOptions->isNotEmpty()) - {{ __('Bestandstarif') }} @else {{ __('Einzel-PM') }} @endif @@ -164,23 +268,6 @@ new #[Layout('components.layouts.app'), Title('Buchungen & Add-ons')] class exte {{ __('Gekündigt — läuft am :date aus.', ['date' => $subscription->ends_at?->format('d.m.Y')]) }}

@endif - @elseif ($legacyOptions->isNotEmpty()) - @foreach ($legacyOptions as $option) -
-
- {{ data_get($option->legacy_conditions, 'name') ?? ($option->paymentOption?->article_number ?? __('Bestehende Vereinbarung')) }} -
-

- {{ __('Unbegrenzte Pressemitteilungen (Bestandsschutz).') }} - @if ($option->current_period_end) - {{ __('Nächste Rechnung am :date.', ['date' => $option->current_period_end->format('d.m.Y')]) }} - @endif -

-
- @endforeach -

- {{ __('Ihre bisherigen Konditionen gelten unverändert weiter; die Abrechnung erfolgt wie gewohnt per Rechnung.') }} -

@elseif ($openPurchases->isNotEmpty())
{{ trans_choice(':count Einzel-Pressemitteilung verfügbar|:count Einzel-Pressemitteilungen verfügbar', $openPurchases->count(), ['count' => $openPurchases->count()]) }} diff --git a/tests/Feature/Billing/BookingsPageTest.php b/tests/Feature/Billing/BookingsPageTest.php index c4e5274..f241a74 100644 --- a/tests/Feature/Billing/BookingsPageTest.php +++ b/tests/Feature/Billing/BookingsPageTest.php @@ -90,22 +90,30 @@ test('a subscriber sees the current plan and the manage button', function () { ->assertSee(route('me.checkout.billing-portal'), false); }); -test('a grandfathered legacy user sees the bestandstarif with unlimited quota', function () { +test('a grandfathered legacy user sees the bestandsschutz package with portal and unlimited quota', function () { /** @var TestCase $this */ $user = bookingsTestCustomer(); UserPaymentOption::factory()->create([ 'user_id' => $user->id, 'status' => UserPaymentOptionStatus::Grandfathered->value, 'current_period_end' => now()->addMonths(3), - 'legacy_conditions' => ['name' => 'Presseverteiler Premium'], + 'legacy_conditions' => [ + 'name' => 'Presseverteiler Premium', + 'legacy_portal' => 'presseecho', + 'net_cents' => 100000, + 'interval' => 'yearly', + ], ]); $this->actingAs($user); LivewireVolt::test('customer.bookings') - ->assertSee('Bestandstarif') + ->assertSee('Ihr Bestandsschutz') + ->assertSee('Bestandsschutz') ->assertSee('Presseverteiler Premium') - ->assertSee('Unbegrenzte Pressemitteilungen (Bestandsschutz).'); + // Portal wird jetzt angezeigt. + ->assertSee('Presseecho') + ->assertSee('Unbegrenzte'); }); test('open and consumed single purchases appear in the card and history', function () {