dashboard/errors: Onboarding-Card „Erste Schritte" & Hub-Styling der Fehlerseiten
Neue aufklappbare "Erste Schritte"-Card als erste Card im Kunden-Dashboard, die neue Nutzer durch Profil, Rechnungsadresse, Firma und erste PM führt und sich ausblendet, sobald alle Schritte erledigt sind. Zusätzlich die gemeinsame Fehlerseiten-Vorlage (404/403/419/500/503) an das Hub-Design angepasst (Palette, Gold-Akzent, Hub-Blau-Button), weiterhin self-contained ohne Vite-Assets. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
6f6cb13f2e
commit
a54637835d
4 changed files with 307 additions and 28 deletions
|
|
@ -50,9 +50,20 @@ new #[Layout('components.layouts.app'), Title('Mein Dashboard')] class extends C
|
|||
$profile = $user->profile;
|
||||
$billingAddress = $user->billingAddress;
|
||||
|
||||
$profilePercent = $this->profileCompleteness($profile);
|
||||
$billingPercent = $this->billingCompleteness($billingAddress);
|
||||
$pressReleaseTotal = (int) ($stats->total ?? 0);
|
||||
$companiesTotal = $context->companyCountFor($user);
|
||||
|
||||
$onboardingSteps = $this->onboardingSteps($profilePercent, $billingPercent, $selectedCompany, $companiesTotal, $pressReleaseTotal);
|
||||
$onboardingCompleted = collect($onboardingSteps)->where('done', true)->count();
|
||||
|
||||
return [
|
||||
'user' => $user,
|
||||
'selectedCompany' => $selectedCompany,
|
||||
'onboardingSteps' => $onboardingSteps,
|
||||
'onboardingCompleted' => $onboardingCompleted,
|
||||
'onboardingTotal' => count($onboardingSteps),
|
||||
// Launch-Gate (WS-5): Solange billing.enforce_booking aus ist, ist
|
||||
// dies immer false und der Hinweis bleibt unsichtbar. Bei scharfem
|
||||
// Gate sehen Bestandskunden (grandfathered) den Banner nicht.
|
||||
|
|
@ -64,12 +75,12 @@ new #[Layout('components.layouts.app'), Title('Mein Dashboard')] class extends C
|
|||
'draft' => (int) ($stats->draft ?? 0),
|
||||
'deltaMonth' => (int) ($stats->current_month ?? 0) - (int) ($stats->previous_month ?? 0),
|
||||
],
|
||||
'profileCompleteness' => $this->profileCompleteness($profile),
|
||||
'billingCompleteness' => $this->billingCompleteness($billingAddress),
|
||||
'profileCompleteness' => $profilePercent,
|
||||
'billingCompleteness' => $billingPercent,
|
||||
'qualityHints' => $this->qualityHints($user, $profile, $billingAddress, $selectedCompany, $pressReleaseQuery),
|
||||
'recent' => $recent,
|
||||
'companies' => $context->latestCompaniesFor($user),
|
||||
'companiesTotal' => $context->companyCountFor($user),
|
||||
'companiesTotal' => $companiesTotal,
|
||||
'bridgeStatus' => [
|
||||
/* Heute hardcoded — perspektivisch aus echtem Sync-Service. */
|
||||
'presseecho' => ['state' => 'connected', 'subline' => __('Archiv · Branchen-Tiefe')],
|
||||
|
|
@ -104,6 +115,54 @@ new #[Layout('components.layouts.app'), Title('Mein Dashboard')] class extends C
|
|||
return $address?->completenessPercent() ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Geführte „Erste Schritte" für neue Kunden. Jeder Schritt gilt als
|
||||
* erledigt, sobald die zugehörigen Stammdaten vorhanden sind.
|
||||
*
|
||||
* @return list<array{num: string, icon: string, title: string, description: string, href: string, action: string, done: bool}>
|
||||
*/
|
||||
private function onboardingSteps(int $profilePercent, int $billingPercent, ?Company $selectedCompany, int $companiesTotal, int $pressReleaseTotal): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
'num' => '01',
|
||||
'icon' => 'user',
|
||||
'title' => __('Profil vervollständigen'),
|
||||
'description' => __('Hinterlegen Sie Anrede, Telefon und Adresse für eine saubere Kundenakte.'),
|
||||
'href' => route('me.profile') . '#profil',
|
||||
'action' => __('Profil öffnen'),
|
||||
'done' => $profilePercent >= 100,
|
||||
],
|
||||
[
|
||||
'num' => '02',
|
||||
'icon' => 'archive-box',
|
||||
'title' => __('Rechnungsadresse hinterlegen'),
|
||||
'description' => __('Damit spätere Buchungen sauber abgerechnet werden können.'),
|
||||
'href' => route('me.profile') . '#rechnungsadresse',
|
||||
'action' => __('Adresse ergänzen'),
|
||||
'done' => $billingPercent >= 100,
|
||||
],
|
||||
[
|
||||
'num' => '03',
|
||||
'icon' => 'building-office',
|
||||
'title' => __('Firma zuordnen'),
|
||||
'description' => __('Ordnen Sie Ihrem Konto eine Firma bzw. Pressestelle zu, für die Sie veröffentlichen.'),
|
||||
'href' => route('me.press-kits.index'),
|
||||
'action' => __('Firmen öffnen'),
|
||||
'done' => $selectedCompany !== null || $companiesTotal > 0,
|
||||
],
|
||||
[
|
||||
'num' => '04',
|
||||
'icon' => 'newspaper',
|
||||
'title' => __('Erste Pressemitteilung erstellen'),
|
||||
'description' => __('Verfassen Sie Ihre erste Mitteilung und senden Sie sie zur Prüfung.'),
|
||||
'href' => route('me.press-releases.create'),
|
||||
'action' => __('Mitteilung erstellen'),
|
||||
'done' => $pressReleaseTotal > 0,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array{icon: string, title: string, description: string, href: string, action: string, percent?: int}>
|
||||
*/
|
||||
|
|
@ -205,6 +264,11 @@ new #[Layout('components.layouts.app'), Title('Mein Dashboard')] class extends C
|
|||
</div>
|
||||
</header>
|
||||
|
||||
{{-- ============== ERSTE SCHRITTE (Onboarding, aufklappbar) ============== --}}
|
||||
@if ($onboardingCompleted < $onboardingTotal)
|
||||
<x-portal.onboarding-guide :steps="$onboardingSteps" :completed="$onboardingCompleted" :total="$onboardingTotal" />
|
||||
@endif
|
||||
|
||||
{{-- ============== BUCHUNGS-GATE (WS-5) ============== --}}
|
||||
@if ($bookingRequired)
|
||||
<section
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue