diff --git a/app-modules/panel-app/resources/views/components/profile-media-header.blade.php b/app-modules/panel-app/resources/views/components/profile-media-header.blade.php index 66d6d235..c55e5e5f 100644 --- a/app-modules/panel-app/resources/views/components/profile-media-header.blade.php +++ b/app-modules/panel-app/resources/views/components/profile-media-header.blade.php @@ -127,11 +127,15 @@ class="absolute inset-0 z-30 flex items-center justify-center rounded-full bg-bl + @error('nickname') +

{{ $message }}

+ @enderror
- + \ No newline at end of file diff --git a/app-modules/panel-app/resources/views/components/profile-preview-card.blade.php b/app-modules/panel-app/resources/views/components/profile-preview-card.blade.php index 5386dac5..65b125c0 100644 --- a/app-modules/panel-app/resources/views/components/profile-preview-card.blade.php +++ b/app-modules/panel-app/resources/views/components/profile-preview-card.blade.php @@ -8,9 +8,9 @@ ]) @php - $name = $user?->name ?? ''; $username = $user?->username ?? ''; $nickname = $data['nickname'] ?? null; + $name = ($nickname ?: null) ?? $user?->name ?? $username; $headline = $data['headline'] ?? null; $about = $data['about'] ?? null; $yearsExperience = $data['years_experience'] ?? null; @@ -266,4 +266,4 @@ class="inline-block rounded-full border border-gray-200 bg-gray-50 px-2.5 py-0.5

Esse card aparece na listagem de membros e no seu perfil público.

- + \ No newline at end of file diff --git a/app-modules/panel-app/src/Pages/ProfilePage.php b/app-modules/panel-app/src/Pages/ProfilePage.php index d007d531..fad37c5d 100644 --- a/app-modules/panel-app/src/Pages/ProfilePage.php +++ b/app-modules/panel-app/src/Pages/ProfilePage.php @@ -38,6 +38,7 @@ use He4rt\Profile\Models\Profile; use He4rt\Profile\Models\Skill; use Illuminate\Support\Str; +use Illuminate\Validation\ValidationException; use Livewire\Attributes\Computed; use Livewire\Attributes\Validate; use Livewire\Features\SupportFileUploads\TemporaryUploadedFile; @@ -61,6 +62,8 @@ class ProfilePage extends Page #[Validate(rule: 'nullable|image|mimes:jpg,jpeg,png,webp|max:4096')] public $coverUpload; + public ?string $nicknameInput = null; + protected static string|null|BackedEnum $navigationIcon = 'heroicon-o-user-circle'; protected static ?string $title = 'Profile'; @@ -98,6 +101,8 @@ public function mount(): void $profile->preferences->employmentTypes, ), ]); + + $this->nicknameInput = $profile->nickname; } public function form(Schema $schema): Schema @@ -374,13 +379,15 @@ public function form(Schema $schema): Schema public function save(): void { + $this->resetErrorBag('nickname'); + $formData = $this->form->getState(); $profile = $this->getRecord(); $socialLinks = $this->repeaterToSocialLinks($formData['social_links'] ?? []); $dto = UpsertProfileDTO::fromArray([ - 'nickname' => $this->data['nickname'] ?? null, + 'nickname' => mb_trim($this->nicknameInput ?? ''), 'birthdate' => $this->data['birthdate'] ?? null, 'about' => $formData['about'] ?? null, 'headline' => $formData['headline'] ?? null, @@ -397,7 +404,16 @@ public function save(): void ], ]); - resolve(UpsertProfile::class)->handle($profile, $dto); + try { + resolve(UpsertProfile::class)->handle($profile, $dto); + } catch (ValidationException $validationException) { + $this->addError('nickname', $validationException->validator->errors()->first('nickname')); + $this->dispatch('scroll-to-nickname'); + + return; + } + + $this->data['nickname'] = mb_trim($this->nicknameInput ?? '') ?: null; $available = (bool) ($formData['available_for_proposals'] ?? false); $rawStartAvailability = $formData['start_availability'] ?? null; diff --git a/app-modules/panel-app/tests/Feature/ProfilePageTest.php b/app-modules/panel-app/tests/Feature/ProfilePageTest.php index 60ff3599..2421afaa 100644 --- a/app-modules/panel-app/tests/Feature/ProfilePageTest.php +++ b/app-modules/panel-app/tests/Feature/ProfilePageTest.php @@ -75,7 +75,7 @@ test('profile page saves all fields', function (): void { livewire(ProfilePage::class) - ->set('data.nickname', 'Dan') + ->set('nicknameInput', 'Dan') ->fillForm([ 'headline' => 'Backend Developer', 'seniority_level' => 'mid', diff --git a/app-modules/profile/src/Actions/UpsertProfile.php b/app-modules/profile/src/Actions/UpsertProfile.php index 2dd859bf..5cea786b 100644 --- a/app-modules/profile/src/Actions/UpsertProfile.php +++ b/app-modules/profile/src/Actions/UpsertProfile.php @@ -21,7 +21,7 @@ public function handle(Profile $profile, UpsertProfileDTO $dto): Profile $attributes = []; if ($dto->nickname !== null) { - $attributes['nickname'] = $dto->nickname; + $attributes['nickname'] = $dto->nickname === '' ? null : $dto->nickname; } if ($dto->birthdate instanceof CarbonInterface) { @@ -79,8 +79,14 @@ private function validate(UpsertProfileDTO $dto): void $errors['headline'] = [__('validation.max.string', ['attribute' => 'headline', 'max' => 100])]; } - if ($dto->nickname !== null && mb_strlen($dto->nickname) > 100) { - $errors['nickname'] = [__('validation.max.string', ['attribute' => 'nickname', 'max' => 100])]; + if ($dto->nickname !== null && $dto->nickname !== '') { + if (mb_strlen($dto->nickname) > 100) { + $errors['nickname'] = ['O apelido deve ter no máximo 100 caracteres.']; + } elseif (!preg_match("/^[\p{L}\p{M}\p{N}\s\-']+$/u", $dto->nickname)) { + $errors['nickname'] = ['Apenas letras, números, espaços, hífens e apóstrofos são permitidos.']; + } elseif (!preg_match('/[\p{L}]{2,}/u', $dto->nickname)) { + $errors['nickname'] = ['O apelido deve conter pelo menos 2 letras juntas.']; + } } if ($dto->yearsExperience !== null && ($dto->yearsExperience < 0 || $dto->yearsExperience > 50)) {