autostart = Auth::user()?->onboarding_tour_completed_at === null; } /** Persist that the tour has been finished or skipped, so it won't auto-open again. */ public function markSeen(): void { $user = Auth::user(); if ($user !== null && $user->onboarding_tour_completed_at === null) { $user->forceFill(['onboarding_tour_completed_at' => now()])->save(); } } /** * The tour steps. A null `target` is a centred card (welcome / finish); a non-null `target` * matches a `data-tour="…"` attribute on a sidebar nav item and is spotlighted. * * @return array> */ public function steps(): array { return [ ['target' => null, 'icon' => 'command', 'eyebrow' => __('onboarding.welcome_eyebrow'), 'title' => __('onboarding.welcome_title'), 'body' => __('onboarding.welcome_body')], ['target' => 'dashboard', 'icon' => 'dashboard', 'eyebrow' => __('onboarding.dashboard_eyebrow'), 'title' => __('onboarding.dashboard_title'), 'body' => __('onboarding.dashboard_body')], ['target' => 'servers', 'icon' => 'server', 'eyebrow' => __('onboarding.servers_eyebrow'), 'title' => __('onboarding.servers_title'), 'body' => __('onboarding.servers_body')], ['target' => 'terminal', 'icon' => 'terminal', 'eyebrow' => __('onboarding.terminal_eyebrow'), 'title' => __('onboarding.terminal_title'), 'body' => __('onboarding.terminal_body')], ['target' => 'settings', 'icon' => 'settings', 'eyebrow' => __('onboarding.settings_eyebrow'), 'title' => __('onboarding.settings_title'), 'body' => __('onboarding.settings_body')], ['target' => null, 'icon' => 'shield', 'eyebrow' => __('onboarding.done_eyebrow'), 'title' => __('onboarding.done_title'), 'body' => __('onboarding.done_body')], ]; } public function render() { return view('livewire.onboarding.tour', ['steps' => $this->steps()]); } }