Skip to content

fix: corrigir novo campo de skills, adicionado linkedin e links redirect#443

Open
fernanduandrade wants to merge 4 commits into
he4rt:4.xfrom
fernanduandrade:fix/profile-add-skill
Open

fix: corrigir novo campo de skills, adicionado linkedin e links redirect#443
fernanduandrade wants to merge 4 commits into
he4rt:4.xfrom
fernanduandrade:fix/profile-add-skill

Conversation

@fernanduandrade

Copy link
Copy Markdown
Contributor

Contexto

Este PR implementa a solução da issue #427 e traz melhorias adicionais relacionadas à experiência de edição do perfil.

Atualmente, a seção Skills exige múltiplos cliques para adicionar várias habilidades e bloqueia o salvamento do perfil quando existem linhas de skills completamente vazias. Esses comportamentos tornam o preenchimento mais lento e geram fricção desnecessária durante a edição do perfil.

Além disso, foram realizadas melhorias complementares na experiência de visualização e gerenciamento de links sociais.

Alterações

Skills

  • Permite salvar o perfil quando existirem linhas de skills completamente vazias.
  • Ajusta a validação para ignorar registros vazios que não possuem dados preenchidos.
  • Mantém as validações para skills efetivamente preenchidas.
  • Implementa comportamento reativo utilizando live() e afterStateUpdated() do Filament para monitorar alterações nos campos da skill.
  • Adiciona automaticamente uma nova linha de skill quando o último campo da skill atual é preenchido.
  • A nova linha é criada automaticamente apenas quando:
    • A skill possui um valor selecionado.
    • O nível de proficiência foi informado.
    • O usuário está preenchendo a última linha disponível do repeater.
  • Utiliza geração automática de UUIDs para manter a consistência dos itens adicionados dinamicamente ao repeater.

Social Media

  • Adiciona suporte ao LinkedIn na seção de links sociais do perfil.
  • Implementa tratamento para aceitar tanto:
    • URLs completas (https://linkedin.com/in/usuario)
    • Apenas o username/handler (usuario)
  • Normaliza automaticamente os dados para gerar o link correto.

Preview do Perfil

  • Adiciona links de redirecionamento nos ícones e informações exibidas no card de preview do perfil.
  • Permite acessar diretamente os perfis sociais a partir da visualização do usuário.

Benefícios

  • Reduz significativamente a quantidade de cliques necessários para cadastrar múltiplas skills.
  • Torna o fluxo de edição mais rápido e intuitivo.
  • Evita bloqueios de salvamento causados por linhas vazias sem dados.
  • Melhora a experiência de configuração de redes sociais.
  • Facilita a navegação a partir do preview do perfil.

Issue relacionada

Closes #427

Links com redirect no preview profile

adiiconar links com redirect no profile preview

Linkedin adicionado no socio media

adicionado linkedin na socials links

Permite salvar com campos em branco ainda não preenchidos

adicionar skill com dados em branco

Adiciona novo campo automático quando a última coluna é preenchida

adicionar novo campo automatico

@fernanduandrade fernanduandrade added bug Something isn't working profile Profile module difficulty:easy 1-2 days labels Jul 22, 2026
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 996ced6f-3e77-4fc3-a0e4-7d580a21f49f

📥 Commits

Reviewing files that changed from the base of the PR and between cde25c3 and 9959ce7.

📒 Files selected for processing (1)
  • app-modules/panel-app/src/Pages/ProfilePage.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • app-modules/panel-app/src/Pages/ProfilePage.php

📝 Walkthrough

Walkthrough

Adds LinkedIn support with URL generation, icons, translations, and tests. Localizes profile preview labels in English and Portuguese and renders social handles as external links. Updates skills and social-link repeaters to add rows automatically, makes work-experience validation conditional, and skips empty work-experience rows.

Possibly related PRs

Suggested reviewers: clintonrocha98, diogokaster

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning LinkedIn support, preview redirect links, translations, and tests go beyond the skills-only scope of issue #427. Move the LinkedIn/social-link and preview redirect changes into a separate PR or link the appropriate issue for that scope.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title reflects the main changes: skills behavior, LinkedIn support, and preview redirect links.
Description check ✅ Passed The description matches the implemented skills, LinkedIn, and preview-link updates.
Linked Issues check ✅ Passed The skills form changes satisfy issue #427 by auto-adding rows and ignoring empty ones on save.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app-modules/panel-app/src/Pages/ProfilePage.php (1)

381-412: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Treat an end date as partial work-experience data.

end_date is absent from all partial-row predicates and from $keyFields; an end-date-only row is treated as empty and discarded. Include it in validation triggers and normalization detection.

Also applies to: 690-696

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app-modules/panel-app/src/Pages/ProfilePage.php` around lines 381 - 412,
Update the work-experience partial-row predicates in the ProfilePage form to
include end_date alongside the other fields, so an end-date-only row triggers
validation. Also add end_date to the $keyFields used for normalization, ensuring
rows containing only an end date are retained rather than discarded.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app-modules/panel-app/src/Pages/ProfilePage.php`:
- Around line 150-156: Update the required predicates for the `skill_id` and
`proficiency` fields in the profile skills form to also consider
`years_experience`, ensuring rows containing only years are rejected rather than
silently discarded by `repeaterToSkills()`.
- Around line 153-195: Update both ProfilePage repeater field handlers at
app-modules/panel-app/src/Pages/ProfilePage.php lines 153-195 and 260-307 so the
shared auto-row creation check runs after either required field changes:
skill_id or proficiency in the skills repeater, and platform or handle in the
platforms repeater. Remove the single-field trigger limitation while preserving
the existing validation that both fields are filled before adding a row.
- Around line 158-194: Type-hint the $component parameter as
Filament\Forms\Components\Component in both afterStateUpdated callbacks,
including the handler containing the repeater auto-add logic, so PHPStan can
resolve getParentRepeater() and getStatePath().

---

Outside diff comments:
In `@app-modules/panel-app/src/Pages/ProfilePage.php`:
- Around line 381-412: Update the work-experience partial-row predicates in the
ProfilePage form to include end_date alongside the other fields, so an
end-date-only row triggers validation. Also add end_date to the $keyFields used
for normalization, ensuring rows containing only an end date are retained rather
than discarded.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 755de64e-c1a8-46b3-afa1-5e5c25d737e3

📥 Commits

Reviewing files that changed from the base of the PR and between 71a6ab1 and cde25c3.

📒 Files selected for processing (8)
  • app-modules/panel-app/lang/en/profile.php
  • app-modules/panel-app/lang/pt_BR/profile.php
  • app-modules/panel-app/resources/views/components/profile-preview-card.blade.php
  • app-modules/panel-app/src/Pages/ProfilePage.php
  • app-modules/profile/lang/en/enums.php
  • app-modules/profile/lang/pt_BR/enums.php
  • app-modules/profile/src/Enums/SocialPlatform.php
  • app-modules/profile/tests/Unit/SocialPlatformTest.php

Comment thread app-modules/panel-app/src/Pages/ProfilePage.php
Comment thread app-modules/panel-app/src/Pages/ProfilePage.php
Comment on lines +158 to +194
->afterStateUpdated(function (Get $get, $component): void {
if (blank($get('skill_id')) || blank($get('proficiency'))) {
return;
}

$repeater = $component->getParentRepeater();

if (!$repeater) {
return;
}

$items = $repeater->getRawState();

if (blank($items)) {
return;
}

// Only auto-add when filling the last row
$repeaterPath = $repeater->getStatePath();
$currentKey = explode('.', mb_substr((string) $component->getStatePath(), mb_strlen($repeaterPath) + 1))[0];

if ($currentKey !== array_key_last($items)) {
return;
}

$newUuid = $repeater->generateUuid();

if ($newUuid) {
$items[$newUuid] = [];
} else {
$items[] = [];
}

$repeater->rawState($items);
$repeater->getChildSchema($newUuid ?? array_key_last($items))->fill();
$repeater->collapsed(false, shouldMakeComponentCollapsible: false);
$repeater->callAfterStateUpdated();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the target file around the reported lines and its imports/types.
sed -n '1,260p' app-modules/panel-app/src/Pages/ProfilePage.php

Repository: he4rt/heartdevs.com

Length of output: 13460


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the file structure first, then inspect the relevant methods/symbols.
ast-grep outline app-modules/panel-app/src/Pages/ProfilePage.php --view expanded

Repository: he4rt/heartdevs.com

Length of output: 1596


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Search for the concrete class of $component and any PHPStan-related annotations in the module.
rg -n "afterStateUpdated\\(|getParentRepeater\\(|generateUuid\\(|callAfterStateUpdated\\(|\\$component" app-modules/panel-app/src -g '*.php'

Repository: he4rt/heartdevs.com

Length of output: 199


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '720,760p' app-modules/panel-app/src/Pages/ProfilePage.php
printf '\n---\n'
rg -n "afterStateUpdated\\(function \\(Get \\$get, [A-Za-z_\\\\][A-Za-z0-9_\\\\]* \\$component" app-modules/panel-app/src -g '*.php'

Repository: he4rt/heartdevs.com

Length of output: 1427


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Look for Filament component type hints used in similar callbacks.
rg -n "function \\(Get \\$get, (Select|TextInput|Toggle|Textarea|Repeater|Component|Field) \\$component|function \\((Select|TextInput|Toggle|Textarea|Repeater|Component|Field) \\$component" app-modules/panel-app/src -g '*.php'

Repository: he4rt/heartdevs.com

Length of output: 193


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '720,760p' app-modules/panel-app/src/Pages/ProfilePage.php
printf '\n---\n'
rg -n "afterStateUpdated\\(function \\(Get \\$get, [A-Za-z_\\\\][A-Za-z0-9_\\\\]* \\$component" app-modules/panel-app/src -g '*.php'
printf '\n---\n'
rg -n "function \\((Select|TextInput|Toggle|Textarea|Repeater|Component|Field) \\$component" app-modules/panel-app/src -g '*.php'

Repository: he4rt/heartdevs.com

Length of output: 1427


🌐 Web query:

Filament afterStateUpdated callback component parameter type Get $get component concrete type getParentRepeater

💡 Result:

In Filament's afterStateUpdated() callback, you can inject various parameters to interact with the component and form state. Component Parameter Type To access the current form component instance (e.g., to call getName(), getStatePath(), or getParentRepeater()), you can type-hint the Filament\Forms\Components\Component class in your callback function [1]. Example: ->afterStateUpdated(function (Component $component, $state, Set $set) { $parentRepeater = $component->getParentRepeater; //... }) Available Utilities The afterStateUpdated() method automatically injects utilities via parameter type-hinting or name matching [2][3]: - $get and $set: Used to interact with field values. In standard forms, they act on the root state. Inside a Repeater or similar nested containers, they are scoped to the current item [4][5]. You can use relative path syntax (e.g., ../field_name) to access data outside the current repeater item [4][5]. - $state: The new value of the field [2][3]. - $old: The previous value of the field [3][6]. getParentRepeater The getParentRepeater() method is available on components that implement the CanBeRepeated concern (which most standard form fields do) [7][8][9]. It returns an instance of Filament\Forms\Components\Repeater or null if the component is not inside a repeater [8][9]. If you are working with deeply nested structures, it effectively traverses the container hierarchy to find the parent repeater [7]. Note: Always ensure you import the correct Filament\Forms\Components\Component namespace if you are using it for type-hinting [1].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find existing callbacks that type-hint the generic Filament component.
rg -n 'afterStateUpdated\(function \([^)]*\bComponent \$component\b' app-modules/panel-app/src -g '*.php' || true
printf '\n---\n'
rg -n 'use Filament\\Forms\\Components\\Component;' app-modules/panel-app/src -g '*.php' || true
printf '\n---\n'
rg -n 'getParentRepeater\(\)' app-modules/panel-app/src -g '*.php' || true

Repository: he4rt/heartdevs.com

Length of output: 562


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
p = Path('app-modules/panel-app/src/Pages/ProfilePage.php')
text = p.read_text()
start = text.index('->afterStateUpdated(function')
end = text.index('->columnSpan(1)', start)
print(text[start:end])
PY

Repository: he4rt/heartdevs.com

Length of output: 2406


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import re
from pathlib import Path

text = Path('app-modules/panel-app/src/Pages/ProfilePage.php').read_text()

m = re.search(r'->afterStateUpdated\(function \(([^)]*)\): void \{', text)
print(m.group(1) if m else 'NO_MATCH')
PY

Repository: he4rt/heartdevs.com

Length of output: 178


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '250,290p' app-modules/panel-app/src/Pages/ProfilePage.php

Repository: he4rt/heartdevs.com

Length of output: 2528


Type-hint the repeater callback component Both afterStateUpdated() handlers use untyped $component; type-hint it as Filament\Forms\Components\Component so PHPStan can resolve getParentRepeater() and getStatePath().

🧰 Tools
🪛 GitHub Check: Perform Phpstan Check / Run

[failure] 188-188:
Cannot access an offset on mixed.


[failure] 186-186:
Cannot access offset mixed on mixed.


[failure] 183-183:
Cannot call method generateUuid() on mixed.


[failure] 179-179:
Parameter #1 $array of function array_key_last expects array, mixed given.


[failure] 177-177:
Parameter #1 $string of function mb_strlen expects string, mixed given.


[failure] 177-177:
Cannot cast mixed to string.


[failure] 177-177:
Cannot call method getStatePath() on mixed.


[failure] 176-176:
Cannot call method getStatePath() on mixed.


[failure] 169-169:
Cannot call method getRawState() on mixed.


[failure] 163-163:
Cannot call method getParentRepeater() on mixed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app-modules/panel-app/src/Pages/ProfilePage.php` around lines 158 - 194,
Type-hint the $component parameter as Filament\Forms\Components\Component in
both afterStateUpdated callbacks, including the handler containing the repeater
auto-add logic, so PHPStan can resolve getParentRepeater() and getStatePath().

Source: Linters/SAST tools

@davicbtoliveira davicbtoliveira left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working difficulty:easy 1-2 days profile Profile module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Seção "Skills" do perfil: adição manual repetitiva e bloqueio de salvamento com linhas vazias

2 participants