exists(); $hasFeed = Feed::where('is_active', true)->exists(); $hasChannel = PlatformChannel::where('is_active', true)->exists(); $hasRoute = Route::where('is_active', true)->exists(); // Check if onboarding was explicitly skipped or completed $onboardingSkipped = Setting::where('key', 'onboarding_skipped')->value('value') === 'true'; $onboardingCompleted = Setting::where('key', 'onboarding_completed')->exists(); // User needs onboarding if: // 1. They haven't completed or skipped onboarding AND // 2. They don't have all required components $hasAllComponents = $hasPlatformAccount && $hasFeed && $hasChannel && $hasRoute; $needsOnboarding = ! $onboardingCompleted && ! $onboardingSkipped && ! $hasAllComponents; // Determine current step $currentStep = null; if ($needsOnboarding) { if (! $hasPlatformAccount) { $currentStep = 'platform'; } elseif (! $hasFeed) { $currentStep = 'feed'; } elseif (! $hasChannel) { $currentStep = 'channel'; } elseif (! $hasRoute) { $currentStep = 'route'; } } return $this->sendResponse([ 'needs_onboarding' => $needsOnboarding, 'current_step' => $currentStep, 'has_platform_account' => $hasPlatformAccount, 'has_feed' => $hasFeed, 'has_channel' => $hasChannel, 'has_route' => $hasRoute, 'onboarding_skipped' => $onboardingSkipped, 'onboarding_completed' => $onboardingCompleted, 'missing_components' => ! $hasAllComponents && $onboardingCompleted, ], 'Onboarding status retrieved successfully.'); } /** * Get onboarding options (languages, platform instances) */ public function options(): JsonResponse { $languages = Language::where('is_active', true) ->orderBy('name') ->get(['id', 'short_code', 'name', 'native_name', 'is_active']); $platformInstances = PlatformInstance::where('is_active', true) ->orderBy('name') ->get(['id', 'platform', 'url', 'name', 'description', 'is_active']); // Get existing feeds and channels for route creation $feeds = Feed::where('is_active', true) ->orderBy('name') ->get(['id', 'name', 'url', 'type']); $platformChannels = PlatformChannel::where('is_active', true) ->with(['platformInstance:id,name,url']) ->orderBy('name') ->get(['id', 'platform_instance_id', 'name', 'display_name', 'description']); // Get feed providers from config /** @var array> $providers */ $providers = config('feed.providers', []); $feedProviders = collect($providers) ->filter(fn (array $provider) => $provider['is_active']) ->values(); return $this->sendResponse([ 'languages' => $languages, 'platform_instances' => $platformInstances, 'feeds' => $feeds, 'platform_channels' => $platformChannels, 'feed_providers' => $feedProviders, ], 'Onboarding options retrieved successfully.'); } /** * Mark onboarding as complete */ public function complete(): JsonResponse { // Track that onboarding has been completed with a timestamp Setting::updateOrCreate( ['key' => 'onboarding_completed'], ['value' => now()->toIso8601String()] ); return $this->sendResponse( ['completed' => true], 'Onboarding completed successfully.' ); } /** * Skip onboarding - user can access the app without completing setup */ public function skip(): JsonResponse { Setting::updateOrCreate( ['key' => 'onboarding_skipped'], ['value' => 'true'] ); return $this->sendResponse( ['skipped' => true], 'Onboarding skipped successfully.' ); } /** * Reset onboarding skip status - force user back to onboarding */ public function resetSkip(): JsonResponse { Setting::where('key', 'onboarding_skipped')->delete(); // Also reset completion status to allow re-onboarding Setting::where('key', 'onboarding_completed')->delete(); return $this->sendResponse( ['reset' => true], 'Onboarding status reset successfully.' ); } }