trypost/app/Http/Requests/App/Onboarding/StoreOnboardingGoalsRequest.php
Paulo Castellano afc4c7a80b feat(onboarding): add goal step after persona
After picking who they are, users now pick what they want to achieve with
TryPost. A multi-select goal step (12 options + an exclusive "just exploring"
and "something else") sits between the persona step and connect, mirroring the
persona screen's style.

The goals persist to a json column on users and are mirrored to PostHog on
identify (onboarding_goals array plus a boolean per goal), so campaigns can be
cross-tabbed against the intent they actually attracted. connect now requires
both a persona and at least one goal; persona store advances to the goal step.

Options are grounded in TryPost's real capabilities (publishing, AI content,
brand voice, automation via API/MCP, collaboration, analytics) and copy is
localized in en/es/pt-BR.
2026-06-25 20:49:04 -03:00

40 lines
992 B
PHP

<?php
declare(strict_types=1);
namespace App\Http\Requests\App\Onboarding;
use App\Enums\User\Goal;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class StoreOnboardingGoalsRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
/**
* @return array<string, mixed>
*/
public function rules(): array
{
return [
'goals' => ['required', 'array', 'min:1'],
'goals.*' => [Rule::enum(Goal::class)],
];
}
public function withValidator(Validator $validator): void
{
$validator->after(function (Validator $validator): void {
$goals = (array) $this->input('goals', []);
if (in_array(Goal::JustExploring->value, $goals, true) && count($goals) > 1) {
$validator->errors()->add('goals', __('onboarding.goals_exclusive'));
}
});
}
}