22-05-2026 Optimierung der User und Admin Panels
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled

This commit is contained in:
Kevin Adametz 2026-05-22 11:18:59 +02:00
parent d2ba22c0cf
commit e8c47b7553
73 changed files with 10282 additions and 1546 deletions

View file

@ -21,16 +21,28 @@ new #[Layout('components.layouts.app'), Title('Mein Dashboard')] class extends C
$user = auth()->user();
$context = app(CustomerCompanyContext::class);
$selectedCompanyId = $context->selectedCompanyId($user);
$selectedCompany = $context->selectedCompany($user);
$selectedCompany = $selectedCompanyId === null
? null
: $context->findFor($user, $selectedCompanyId);
$pressReleaseQuery = PressRelease::withoutGlobalScopes()
->where('user_id', $user->id)
->when($selectedCompanyId !== null, fn ($query) => $query->where('company_id', $selectedCompanyId));
$myPRs = (clone $pressReleaseQuery)
->selectRaw('status, count(*) as count')
->groupBy('status')
->pluck('count', 'status');
$now = Carbon::now();
$currentStart = $now->copy()->startOfMonth();
$previousStart = $now->copy()->subMonthNoOverflow()->startOfMonth();
$previousEnd = $now->copy()->subMonthNoOverflow()->endOfMonth();
$stats = (clone $pressReleaseQuery)
->toBase()
->selectRaw('COUNT(*) as total')
->selectRaw('SUM(CASE WHEN status = ? THEN 1 ELSE 0 END) as published', [PressReleaseStatus::Published->value])
->selectRaw('SUM(CASE WHEN status = ? THEN 1 ELSE 0 END) as review', [PressReleaseStatus::Review->value])
->selectRaw('SUM(CASE WHEN status = ? THEN 1 ELSE 0 END) as draft', [PressReleaseStatus::Draft->value])
->selectRaw('SUM(CASE WHEN created_at >= ? THEN 1 ELSE 0 END) as current_month', [$currentStart])
->selectRaw('SUM(CASE WHEN created_at BETWEEN ? AND ? THEN 1 ELSE 0 END) as previous_month', [$previousStart, $previousEnd])
->first();
$recent = (clone $pressReleaseQuery)
->with('company:id,name')
@ -45,11 +57,11 @@ new #[Layout('components.layouts.app'), Title('Mein Dashboard')] class extends C
'user' => $user,
'selectedCompany' => $selectedCompany,
'stats' => [
'total' => (clone $pressReleaseQuery)->count(),
'published' => $myPRs->get('published', 0),
'review' => $myPRs->get('review', 0),
'draft' => $myPRs->get('draft', 0),
'deltaMonth' => $this->totalDeltaToPreviousMonth(clone $pressReleaseQuery),
'total' => (int) ($stats->total ?? 0),
'published' => (int) ($stats->published ?? 0),
'review' => (int) ($stats->review ?? 0),
'draft' => (int) ($stats->draft ?? 0),
'deltaMonth' => (int) ($stats->current_month ?? 0) - (int) ($stats->previous_month ?? 0),
],
'profileCompleteness' => $this->profileCompleteness($profile),
'billingCompleteness' => $this->billingCompleteness($billingAddress),
@ -61,7 +73,8 @@ new #[Layout('components.layouts.app'), Title('Mein Dashboard')] class extends C
$pressReleaseQuery,
),
'recent' => $recent,
'companies' => $context->companiesFor($user),
'companies' => $context->latestCompaniesFor($user),
'companiesTotal' => $context->companyCountFor($user),
'bridgeStatus' => [
/* Heute hardcoded — perspektivisch aus echtem Sync-Service. */
'presseecho' => ['state' => 'connected', 'subline' => __('Archiv · Branchen-Tiefe')],
@ -110,27 +123,6 @@ new #[Layout('components.layouts.app'), Title('Mein Dashboard')] class extends C
return (int) round(($filled / count($fields)) * 100);
}
/**
* Vergleicht PRs im aktuellen Monat mit dem Vormonat (Differenz, Vorzeichen mit Pfeil im View).
*/
private function totalDeltaToPreviousMonth(Builder $pressReleaseQuery): int
{
$now = Carbon::now();
$currentStart = $now->copy()->startOfMonth();
$previousStart = $now->copy()->subMonthNoOverflow()->startOfMonth();
$previousEnd = $now->copy()->subMonthNoOverflow()->endOfMonth();
$currentCount = (clone $pressReleaseQuery)
->where('created_at', '>=', $currentStart)
->count();
$previousCount = (clone $pressReleaseQuery)
->whereBetween('created_at', [$previousStart, $previousEnd])
->count();
return $currentCount - $previousCount;
}
/**
* @return list<array{icon: string, title: string, description: string, href: string, action: string, percent?: int}>
*/
@ -234,7 +226,7 @@ new #[Layout('components.layouts.app'), Title('Mein Dashboard')] class extends C
{{ __('Aktive Firma:') }} <strong class="font-semibold">{{ $selectedCompany->name }}</strong>
</span>
@else
<a href="{{ route('me.profile') }}#firmen" wire:navigate
<a href="{{ route('me.press-kits.index') }}" wire:navigate
class="inline-flex items-center gap-2 px-3 py-1.5 rounded-[4px] text-[12px] font-semibold whitespace-nowrap bg-[color:var(--color-warn-soft)] border border-[color:var(--color-warn)]/30 text-[color:var(--color-accent-deep)] hover:bg-[color:var(--color-warn-soft)]/80 transition">
<flux:icon.exclamation-triangle class="size-[13px] flex-shrink-0" />
{{ __('Keine Firma zugeordnet') }}
@ -448,11 +440,11 @@ new #[Layout('components.layouts.app'), Title('Mein Dashboard')] class extends C
<span class="section-eyebrow">{{ __('Meine Firmen') }}</span>
<div class="flex items-center gap-3">
<span class="badge hub" style="font-size:9.5px;padding:1px 6px;">
{{ $companies->count() }} {{ __('zugeordnet') }}
{{ $companiesTotal }} {{ __('zugeordnet') }}
</span>
<a href="{{ route('me.profile') }}" wire:navigate
<a href="{{ route('me.press-kits.index') }}" wire:navigate
class="text-[12px] font-semibold text-[color:var(--color-hub)] hover:underline underline-offset-[3px] decoration-[color:var(--color-hub)]/30">
{{ __('Profil & Firma verwalten') }}
{{ __('Alle Firmen anzeigen') }}
</a>
</div>
</div>
@ -483,6 +475,15 @@ new #[Layout('components.layouts.app'), Title('Mein Dashboard')] class extends C
</a>
@endforeach
</div>
@if ($companiesTotal > $companies->count())
<div class="mt-4 text-[11.5px] leading-[1.5] text-[color:var(--color-ink-3)]">
{{ __('Die zehn neuesten Firmen werden hier als Vorschau angezeigt.') }}
<a href="{{ route('me.press-kits.index') }}" wire:navigate
class="font-semibold text-[color:var(--color-hub)] hover:underline underline-offset-[3px] decoration-[color:var(--color-hub)]/30">
{{ __('Zur vollständigen Firmenliste') }}
</a>
</div>
@endif
@else
<div class="grid gap-3 grid-cols-1 md:grid-cols-2">
<div class="relative rounded-[5px] p-5 transition-colors
@ -511,11 +512,11 @@ new #[Layout('components.layouts.app'), Title('Mein Dashboard')] class extends C
bg-[color:var(--color-bg-elev)] border border-[color:var(--color-bg-rule)]">
<div class="eyebrow muted mb-2">{{ __('Hinweis') }}</div>
<div class="text-[13px] leading-[1.55] m-0 text-[color:var(--color-ink-2)]">
{{ __('Keine Firmen zugeordnet. Wenn hier eine Firma fehlen sollte, prüfen Sie bitte Ihr Profil oder wenden Sie sich an den Support.') }}
{{ __('Keine Firmen zugeordnet. Wenn hier eine Firma fehlen sollte, prüfen Sie bitte die Firmenverwaltung oder wenden Sie sich an den Support.') }}
</div>
<div class="mt-3">
<flux:button size="sm" variant="ghost" href="{{ route('me.profile') }}" wire:navigate>
{{ __('Profil prüfen') }}
<flux:button size="sm" variant="ghost" href="{{ route('me.press-kits.index') }}" wire:navigate>
{{ __('Firmen öffnen') }}
</flux:button>
</div>
</div>