Status-Widget: immer verfuegbarer Buchungsueberblick in der Topbar
Ein Header-Dropdown oben rechts (Desktop) bzw. im Mobile-Header zeigt fuer alle Kunden-Panel-User den aktuellen Status: aktuelle Buchung/Tarif, verbleibendes PM-Kontingent und Credit-Guthaben. Ohne aktive Buchung weist es direkt auf die noetige Buchung hin und verlinkt die Buchungsseite. CustomerStatusSummary buendelt die Anzeige-Werte ueber die oeffentliche User-API (Gating bleibt Single Source of Truth im Modell); die anonyme Blade-Komponente x-customer.status-menu rendert das Dropdown. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
e962cc2213
commit
af99189b23
4 changed files with 321 additions and 0 deletions
84
resources/views/components/customer/status-menu.blade.php
Normal file
84
resources/views/components/customer/status-menu.blade.php
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
@props(['user' => null])
|
||||
|
||||
@php
|
||||
$user ??= auth()->user();
|
||||
$status = $user ? \App\Services\Customer\CustomerStatusSummary::fromUser($user) : null;
|
||||
@endphp
|
||||
|
||||
@if ($status)
|
||||
<flux:dropdown position="bottom" align="end">
|
||||
{{-- Trigger: kompaktes Status-Badge in der Topbar --}}
|
||||
<button
|
||||
type="button"
|
||||
class="inline-flex items-center gap-2 rounded-full border border-[color:var(--color-bg-rule)] bg-[color:var(--color-bg-card)] px-3 py-1.5 text-[12px] font-semibold text-[color:var(--color-ink)] transition-colors hover:border-[color:var(--color-hub)] hover:text-[color:var(--color-hub)]"
|
||||
aria-label="{{ __('Mein Status & Guthaben') }}"
|
||||
>
|
||||
<flux:icon name="wallet" variant="micro" class="size-3.5 text-[color:var(--color-hub)]" />
|
||||
<span class="whitespace-nowrap font-mono">{{ $status->badgeLabel() }}</span>
|
||||
<flux:icon name="chevron-down" variant="micro" class="size-3 text-[color:var(--color-ink-3)]" />
|
||||
</button>
|
||||
|
||||
<flux:menu class="w-[268px]">
|
||||
{{-- Aktuelle Buchung --}}
|
||||
<div class="px-3 pt-2 pb-1">
|
||||
<div class="mb-1 text-[10px] font-semibold uppercase tracking-[0.16em] text-[color:var(--color-ink-3)]">
|
||||
{{ __('Aktuelle Buchung') }}
|
||||
</div>
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<span class="text-[13.5px] font-semibold text-[color:var(--color-ink)]">
|
||||
{{ $status->bookingLabel() }}
|
||||
@if ($status->billingIntervalLabel())
|
||||
<span class="font-normal text-[color:var(--color-ink-3)]">· {{ $status->billingIntervalLabel() }}</span>
|
||||
@endif
|
||||
</span>
|
||||
@if ($status->hasActiveBooking)
|
||||
<span class="inline-flex items-center gap-1 text-[11px] font-semibold text-[color:var(--color-ok)]">
|
||||
<span class="size-1.5 rounded-full bg-[color:var(--color-ok)]"></span>{{ __('aktiv') }}
|
||||
</span>
|
||||
@else
|
||||
<span class="text-[11px] font-semibold text-[color:var(--color-warn)]">{{ __('keine') }}</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<flux:menu.separator />
|
||||
|
||||
{{-- Kennzahlen: PM-Kontingent & Credits --}}
|
||||
<div class="grid grid-cols-2 gap-px bg-[color:var(--color-bg-rule)] mx-3 my-1 rounded-[5px] overflow-hidden border border-[color:var(--color-bg-rule)]">
|
||||
<div class="bg-[color:var(--color-bg-card)] p-2.5">
|
||||
<div class="text-[10px] font-semibold uppercase tracking-[0.14em] text-[color:var(--color-ink-3)]">
|
||||
{{ __('PMs frei') }}
|
||||
</div>
|
||||
<div class="mt-0.5 text-[18px] font-bold leading-none text-[color:var(--color-ink)]">
|
||||
@if ($status->unlimitedQuota)
|
||||
∞
|
||||
@else
|
||||
{{ $status->quotaRemaining }}<span class="text-[12px] font-medium text-[color:var(--color-ink-3)]"> / {{ $status->quotaTotal }}</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-[color:var(--color-bg-card)] p-2.5">
|
||||
<div class="text-[10px] font-semibold uppercase tracking-[0.14em] text-[color:var(--color-ink-3)]">
|
||||
{{ __('Guthaben') }}
|
||||
</div>
|
||||
<div class="mt-0.5 text-[18px] font-bold leading-none text-[color:var(--color-ink)]">
|
||||
{{ $status->creditBalance }}<span class="text-[12px] font-medium text-[color:var(--color-ink-3)]"> Cr</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@unless ($status->hasActiveBooking)
|
||||
<div class="mx-3 my-1.5 flex items-start gap-1.5 rounded-[4px] border border-[color:color-mix(in_srgb,var(--color-warn)_45%,transparent)] bg-[color:var(--color-warn-soft,transparent)] px-2.5 py-2 text-[11px] leading-[1.45] text-[color:var(--color-ink-2)]">
|
||||
<flux:icon name="exclamation-triangle" variant="micro" class="mt-0.5 size-3.5 flex-shrink-0 text-[color:var(--color-warn)]" />
|
||||
<span>{{ __('Zum Veröffentlichen brauchst du eine Buchung.') }}</span>
|
||||
</div>
|
||||
@endunless
|
||||
|
||||
<flux:menu.separator />
|
||||
|
||||
<flux:menu.item :href="route('me.bookings.index')" icon="shopping-bag" wire:navigate>
|
||||
{{ __('Buchungen & Add-ons') }}
|
||||
</flux:menu.item>
|
||||
</flux:menu>
|
||||
</flux:dropdown>
|
||||
@endif
|
||||
|
|
@ -307,6 +307,15 @@
|
|||
</flux:dropdown>
|
||||
</flux:sidebar>
|
||||
|
||||
{{-- Desktop-Topbar: immer verfügbarer Status (Buchung, freie PMs, Credits)
|
||||
oben rechts. Nur für Panel-User mit Kundenbereich. --}}
|
||||
@if ($canCustomer)
|
||||
<flux:header class="hidden xl:flex">
|
||||
<flux:spacer />
|
||||
<x-customer.status-menu :user="$user" />
|
||||
</flux:header>
|
||||
@endif
|
||||
|
||||
<!-- Mobile User Menu -->
|
||||
<flux:header class="xl:hidden">
|
||||
<flux:sidebar.toggle class="xl:hidden" icon="bars-2" inset="left" />
|
||||
|
|
@ -317,6 +326,9 @@
|
|||
</span>
|
||||
</a>
|
||||
<flux:spacer />
|
||||
@if ($canCustomer)
|
||||
<x-customer.status-menu :user="$user" />
|
||||
@endif
|
||||
|
||||
<flux:dropdown position="top" align="end">
|
||||
<flux:profile :initials="auth()->user()->initials()" icon-trailing="chevron-down" />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue