2025-08-09 00:03:45 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Http\Controllers\Api\V1;
|
|
|
|
|
|
|
|
|
|
use App\Models\Feed;
|
|
|
|
|
use App\Models\Language;
|
|
|
|
|
use App\Models\PlatformAccount;
|
|
|
|
|
use App\Models\PlatformChannel;
|
|
|
|
|
use App\Models\PlatformInstance;
|
2025-08-09 13:48:25 +02:00
|
|
|
use App\Models\Route;
|
2025-08-09 02:51:18 +02:00
|
|
|
use App\Models\Setting;
|
2025-08-09 00:03:45 +02:00
|
|
|
use Illuminate\Http\JsonResponse;
|
|
|
|
|
|
|
|
|
|
class OnboardingController extends BaseController
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* Get onboarding status - whether user needs onboarding
|
|
|
|
|
*/
|
|
|
|
|
public function status(): JsonResponse
|
|
|
|
|
{
|
|
|
|
|
$hasPlatformAccount = PlatformAccount::where('is_active', true)->exists();
|
|
|
|
|
$hasFeed = Feed::where('is_active', true)->exists();
|
|
|
|
|
$hasChannel = PlatformChannel::where('is_active', true)->exists();
|
2025-08-09 13:48:25 +02:00
|
|
|
$hasRoute = Route::where('is_active', true)->exists();
|
2025-08-09 17:05:11 +02:00
|
|
|
|
2025-08-14 21:16:39 +02:00
|
|
|
// Check if onboarding was explicitly skipped or completed
|
2025-08-09 02:51:18 +02:00
|
|
|
$onboardingSkipped = Setting::where('key', 'onboarding_skipped')->value('value') === 'true';
|
2025-08-14 21:16:39 +02:00
|
|
|
$onboardingCompleted = Setting::where('key', 'onboarding_completed')->exists();
|
2025-08-09 00:03:45 +02:00
|
|
|
|
2025-08-14 21:16:39 +02:00
|
|
|
// 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;
|
2026-03-08 14:18:28 +01:00
|
|
|
$needsOnboarding = ! $onboardingCompleted && ! $onboardingSkipped && ! $hasAllComponents;
|
2025-08-09 00:03:45 +02:00
|
|
|
|
|
|
|
|
// Determine current step
|
|
|
|
|
$currentStep = null;
|
|
|
|
|
if ($needsOnboarding) {
|
2026-03-08 14:18:28 +01:00
|
|
|
if (! $hasPlatformAccount) {
|
2025-08-09 00:03:45 +02:00
|
|
|
$currentStep = 'platform';
|
2026-03-08 14:18:28 +01:00
|
|
|
} elseif (! $hasFeed) {
|
2025-08-09 00:03:45 +02:00
|
|
|
$currentStep = 'feed';
|
2026-03-08 14:18:28 +01:00
|
|
|
} elseif (! $hasChannel) {
|
2025-08-09 00:03:45 +02:00
|
|
|
$currentStep = 'channel';
|
2026-03-08 14:18:28 +01:00
|
|
|
} elseif (! $hasRoute) {
|
2025-08-09 13:48:25 +02:00
|
|
|
$currentStep = 'route';
|
2025-08-09 00:03:45 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $this->sendResponse([
|
|
|
|
|
'needs_onboarding' => $needsOnboarding,
|
|
|
|
|
'current_step' => $currentStep,
|
|
|
|
|
'has_platform_account' => $hasPlatformAccount,
|
|
|
|
|
'has_feed' => $hasFeed,
|
|
|
|
|
'has_channel' => $hasChannel,
|
2025-08-09 13:48:25 +02:00
|
|
|
'has_route' => $hasRoute,
|
2025-08-09 02:51:18 +02:00
|
|
|
'onboarding_skipped' => $onboardingSkipped,
|
2025-08-14 21:16:39 +02:00
|
|
|
'onboarding_completed' => $onboardingCompleted,
|
2026-03-08 14:18:28 +01:00
|
|
|
'missing_components' => ! $hasAllComponents && $onboardingCompleted,
|
2025-08-09 00:03:45 +02:00
|
|
|
], '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']);
|
|
|
|
|
|
2025-08-09 13:48:25 +02:00
|
|
|
// 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']);
|
|
|
|
|
|
2025-08-10 21:47:10 +02:00
|
|
|
// Get feed providers from config
|
2026-03-08 14:18:28 +01:00
|
|
|
/** @var array<string, array<string, mixed>> $providers */
|
|
|
|
|
$providers = config('feed.providers', []);
|
|
|
|
|
$feedProviders = collect($providers)
|
|
|
|
|
->filter(fn (array $provider) => $provider['is_active'])
|
2025-08-10 21:47:10 +02:00
|
|
|
->values();
|
|
|
|
|
|
2025-08-09 00:03:45 +02:00
|
|
|
return $this->sendResponse([
|
|
|
|
|
'languages' => $languages,
|
|
|
|
|
'platform_instances' => $platformInstances,
|
2025-08-09 13:48:25 +02:00
|
|
|
'feeds' => $feeds,
|
|
|
|
|
'platform_channels' => $platformChannels,
|
2025-08-10 21:47:10 +02:00
|
|
|
'feed_providers' => $feedProviders,
|
2025-08-09 00:03:45 +02:00
|
|
|
], 'Onboarding options retrieved successfully.');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Mark onboarding as complete
|
|
|
|
|
*/
|
|
|
|
|
public function complete(): JsonResponse
|
|
|
|
|
{
|
2025-08-14 21:16:39 +02:00
|
|
|
// Track that onboarding has been completed with a timestamp
|
|
|
|
|
Setting::updateOrCreate(
|
|
|
|
|
['key' => 'onboarding_completed'],
|
|
|
|
|
['value' => now()->toIso8601String()]
|
|
|
|
|
);
|
2025-08-09 17:05:11 +02:00
|
|
|
|
2025-08-09 00:03:45 +02:00
|
|
|
return $this->sendResponse(
|
2025-08-10 01:26:56 +02:00
|
|
|
['completed' => true],
|
2025-08-09 00:03:45 +02:00
|
|
|
'Onboarding completed successfully.'
|
|
|
|
|
);
|
|
|
|
|
}
|
2025-08-09 02:51:18 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Skip onboarding - user can access the app without completing setup
|
|
|
|
|
*/
|
|
|
|
|
public function skip(): JsonResponse
|
|
|
|
|
{
|
|
|
|
|
Setting::updateOrCreate(
|
|
|
|
|
['key' => 'onboarding_skipped'],
|
|
|
|
|
['value' => 'true']
|
|
|
|
|
);
|
2025-08-09 17:05:11 +02:00
|
|
|
|
2025-08-09 02:51:18 +02:00
|
|
|
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();
|
2025-08-14 21:16:39 +02:00
|
|
|
// Also reset completion status to allow re-onboarding
|
|
|
|
|
Setting::where('key', 'onboarding_completed')->delete();
|
2025-08-09 17:05:11 +02:00
|
|
|
|
2025-08-09 02:51:18 +02:00
|
|
|
return $this->sendResponse(
|
|
|
|
|
['reset' => true],
|
2025-08-14 21:16:39 +02:00
|
|
|
'Onboarding status reset successfully.'
|
2025-08-09 02:51:18 +02:00
|
|
|
);
|
|
|
|
|
}
|
2025-08-09 17:05:11 +02:00
|
|
|
}
|