Skip to content

feat(panel-admin): profile tab on UserResource #256#293

Draft
Hadzab wants to merge 7 commits into
4.xfrom
feat/256-admin-panel-profile-tab
Draft

feat(panel-admin): profile tab on UserResource #256#293
Hadzab wants to merge 7 commits into
4.xfrom
feat/256-admin-panel-profile-tab

Conversation

@Hadzab
Copy link
Copy Markdown

@Hadzab Hadzab commented May 28, 2026

Closes #256

Contexto

Parte da PRD #250 — Módulo Profile Fase 1.

O admin precisa visualizar e editar o perfil de qualquer membro para fins de moderação. Em vez de criar um ProfileResource separado, foi adicionada uma tab "Profile" dentro do UserResource existente.

O que foi feito

  • Criado UserResource no Admin panel com páginas ListUsers, CreateUser e EditUser
  • Adicionada tab "Profile" no UserForm com as seções:
    • Dados Pessoais (nickname, birthdate)
    • Dados Profissionais (headline, seniority_level, years_experience, about)
    • Links Sociais (social_links via Repeater)
    • Disponibilidade (available_for_proposals + start_availability condicional)
  • Save handler chama as domain actions UpsertProfile e ToggleAvailability
  • Profile inexistente é criado on-the-fly via firstOrCreate
  • UserResource registrado no PanelAdminServiceProvider

Testes

  • admin sees profile tab on user resource
  • profile tab loads member data
  • admin can edit member bio
  • validates bio max length
  • toggle availability shows start availability field

Checklist

  • Código vive na camada do Admin panel
  • Pint passou sem erros
  • Testes passando

Description

Adds a "Profile" tab to the Admin UserResource so admins can view/edit tenant-scoped member profiles (personal, professional, social links, availability). Implements List/Create/Edit user pages, a tabbed UserForm schema with conditional availability, and save handlers that call UpsertProfile and ToggleAvailability, creating missing profiles on-the-fly.

References

Dependencies & Requirements

  • No new external dependencies.
  • No environment variables or config changes required.
  • Conforms to existing Filament/admin architecture; Pint formatting and tests pass.

Contributor Summary

Contributor Lines Added Lines Removed Files Changed
Hadzab 585 0 7

Changes Summary

File Path Change Description
app-modules/panel-admin/src/Filament/Resources/Users/UserResource.php New Filament Resource: model binding, form wiring (delegates to UserForm), table columns, filters and pages registration
app-modules/panel-admin/src/Filament/Resources/Users/Schemas/UserForm.php New UserForm schema with Tabs: Account and Profile (personal, professional, social links repeater, availability with conditional start field)
app-modules/panel-admin/src/Filament/Resources/Users/Pages/CreateUser.php Filament page for creating users (CreateRecord)
app-modules/panel-admin/src/Filament/Resources/Users/Pages/EditUser.php Filament Edit page: hydrates tenant-scoped Profile, maps social_links to/from repeater, validates duplicates, calls UpsertProfile and ToggleAvailability, updates user and notifies
app-modules/panel-admin/src/Filament/Resources/Users/Pages/ListUsers.php Filament List page with Create action
app-modules/panel-admin/src/PanelAdminServiceProvider.php Registers UserResource in admin panel resources/navigation
app-modules/panel-admin/tests/Feature/Users/UserResourceTest.php Feature tests: tab visibility, data loading, editing/saving, validation, and availability toggle behavior

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 28, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a Filament UserResource with a tabbed UserForm (account and profile sections), list/create/edit pages (ListUsers, CreateUser, EditUser). EditUser loads the tenant-scoped Profile, maps social_links to/from a repeater, upserts profile via UpsertProfile, toggles availability via ToggleAvailability, updates user name/email, and shows success notifications. UserResource table columns and filters are configured. PanelAdminServiceProvider registers the resource. A Pest feature test suite verifies EditUser behaviors.

Possibly related PRs

  • he4rt/heartdevs.com#206: Both PRs modify app-modules/panel-admin/src/PanelAdminServiceProvider.php to register/boot Filament resources for the admin module (the retrieved PR sets up the module provider, and the main PR extends it to include the new UserResource).

Suggested reviewers

  • Clintonrocha98
  • thalesmengue
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(panel-admin): profile tab on UserResource #256' accurately describes the main change in the changeset by highlighting the addition of a profile tab feature to the UserResource in the panel-admin module.
Linked Issues check ✅ Passed The pull request implementation fully addresses all major coding requirements from issue #256: UserResource created with profile tab functionality, form schema with all required fields (nickname, birthdate, headline, seniority_level, years_experience, about, social_links, available_for_proposals, start_availability), domain action calls (UpsertProfile, ToggleAvailability), tenant-scoped profile handling, identical validations, and comprehensive Livewire tests covering tab visibility, data loading, saving, validation, and availability toggle behavior.
Out of Scope Changes check ✅ Passed All changes align with the stated objectives: UserResource pages (CreateUser, EditUser, ListUsers), UserForm schema, profile-related columns in user table, tenant filtering, and PanelAdminServiceProvider registration are all directly related to implementing the profile tab feature for UserResource in the Admin panel.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 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-admin/src/Filament/Resources/Users/Pages/EditUser.php`:
- Around line 49-57: The code coerces an empty social links repeater to null,
preventing UpsertProfileDTO/UpsertProfile from persisting a cleared list; in the
UpsertProfileDTO creation (the $dto assignment using UpsertProfileDTO::fromArray
and the 'social_links' key) stop converting [] to null — pass $socialLinks
directly (i.e. 'social_links' => $socialLinks) so an explicit empty array will
be persisted as “no links” instead of being ignored.
- Around line 91-103: The helper methods socialLinksToRepeater and
repeaterToSocialLinks lack precise array value-type annotations, causing phpstan
iterable value-type errors; add explicit docblock types: for
socialLinksToRepeater accept ?array<string,string> and return
array<int,array{platform:string,handle:string}> (i.e. `@param`
?array<string,string> $socialLinks and `@return`
array<int,array{platform:string,handle:string}>), and for repeaterToSocialLinks
accept array<int,array{platform:string,handle:string}> and return
array<string,string> (i.e. `@param`
array<int,array{platform:string,handle:string}> $repeaterData and `@return`
array<string,string>), leaving runtime signatures unchanged but satisfying
static analysis for the functions socialLinksToRepeater and
repeaterToSocialLinks.
- Around line 42-77: handleRecordUpdate currently updates only the profile and
availability and ignores user account fields from $data, so edits to name/email
are lost; update handleRecordUpdate to extract the account data from $data (e.g.
$data['account'] or top-level keys used in the form), set them on the $record
(the User model) and persist before returning (use $record->fill(...) and
$record->save() or $record->update(...)), while keeping the existing calls to
UpsertProfile::handle($profile, $dto) and ToggleAvailability::handle($profile,
$available, $startAvailability).
- Around line 107-114: The loop in EditUser.php that builds $links from
$repeaterData can silently overwrite entries when the same platform appears
twice; before assigning $links[$key] = (string) $handle check if $key already
exists and, if so, raise a validation error (e.g. throw
Illuminate\Validation\ValidationException or
ValidationException::withMessages([...]) for the social links field) or
otherwise mark the record invalid so the user gets feedback; reference the loop
variables $repeaterData, $platform, $handle, $links and the SocialPlatform enum
to locate and update the logic.
🪄 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: he4rt/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 448c6372-355b-4fb3-81ef-ab5fb4a2771a

📥 Commits

Reviewing files that changed from the base of the PR and between c5c45e0 and 1978b4f.

📒 Files selected for processing (7)
  • app-modules/panel-admin/src/Filament/Resources/Users/Pages/CreateUser.php
  • app-modules/panel-admin/src/Filament/Resources/Users/Pages/EditUser.php
  • app-modules/panel-admin/src/Filament/Resources/Users/Pages/ListUsers.php
  • app-modules/panel-admin/src/Filament/Resources/Users/Schemas/UserForm.php
  • app-modules/panel-admin/src/Filament/Resources/Users/UserResource.php
  • app-modules/panel-admin/src/PanelAdminServiceProvider.php
  • app-modules/panel-admin/tests/Feature/Users/UserResourceTest.php

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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-admin/src/Filament/Resources/Users/Pages/EditUser.php`:
- Around line 78-81: The PHPStan errors are caused by using the generic Model
type for $record while accessing User-specific properties (name/email) in
EditUser::mutateFormDataUsing; fix by importing App\Models\User and narrowing
the type: either change the method param to User $record or add a docblock like
`@param` User $record (or add an inline assertion /** `@var` User $record */ or
assert($record instanceof User) before using $record) so accesses to
$record->name and $record->email are recognized as valid.
🪄 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: f7470b8d-8533-49f0-974e-70b3f0caba71

📥 Commits

Reviewing files that changed from the base of the PR and between 3167810 and 4fdf956.

📒 Files selected for processing (2)
  • app-modules/panel-admin/src/Filament/Resources/Users/Pages/EditUser.php
  • app-modules/panel-admin/src/Filament/Resources/Users/UserResource.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • app-modules/panel-admin/src/Filament/Resources/Users/UserResource.php

@Hadzab Hadzab requested a review from a team June 5, 2026 18:44
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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-admin/src/Filament/Resources/Users/UserResource.php`:
- Around line 71-73: The "Criado este mês" filter currently only checks month
and may match other years; update the Filter::make('created_at')->query callback
to constrain by both month and year by adding a whereYear('created_at',
now()->year) alongside the existing whereMonth call so the Builder query checks
the current month AND the current year.
- Around line 45-63: The UserResource is referencing related fields via
TextColumn::make('profile.*') but the User model lacks a profile() relationship
and the relation isn't being eager-loaded, so add a profile() relation method to
the User model (returning a hasOne to the Profile model) and update UserResource
to eager-load('profile') in the query provider (or
getEloquentQuery/getTableQuery override) so
TextColumn::make('profile.headline'), 'profile.seniority_level',
'profile.years_experience', and 'profile.available_for_proposals' resolve
correctly.
🪄 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: 904f892c-ffd1-48ee-a6ad-a6778dbddf0a

📥 Commits

Reviewing files that changed from the base of the PR and between 43935a9 and 3f84678.

📒 Files selected for processing (1)
  • app-modules/panel-admin/src/Filament/Resources/Users/UserResource.php

Comment on lines +45 to +63
TextColumn::make('profile.headline')
->label('Headline')
->default('—')
->searchable(),

TextColumn::make('profile.seniority_level')
->label('Seniority')
->badge()
->default('—'),

TextColumn::make('profile.years_experience')
->label('Exp.')
->formatStateUsing(fn ($state) => $state ? $state.' anos' : '—'),

TextColumn::make('profile.available_for_proposals')
->label('Disponível')
->badge()
->formatStateUsing(fn ($state) => $state ? 'Sim' : 'Não')
->color(fn ($state) => $state ? 'success' : 'gray'),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check for profile relationship definition on User model

# Search for profile relationship method in User model
ast-grep --pattern $'class User $$$  {
  $$$
  profile($$$) {
    $$$
  }
  $$$
}'

# Alternative: search for relationship definition with rg
rg -nP --type=php -A5 'function profile\(' app-modules/identity/

Repository: he4rt/heartdevs.com

Length of output: 45


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Locate the User model file(s)
echo "== User model candidates =="
fd -t f 'User.php' app-modules src . | head -n 50 || true

# Broader: search for class User definitions
echo
echo "== class User { occurrences =="
rg -n --type=php 'class\s+User\b' . | head -n 50 || true

# 2) Find any relationship method named profile() across repo
echo
echo "== function profile( occurrences =="
rg -n --type=php 'function\s+profile\s*\(' . | head -n 50 || true

# 3) Inspect UserResource.php around table() method
echo
echo "== UserResource.php: table() method area =="
FILE="app-modules/panel-admin/src/Filament/Resources/Users/UserResource.php"
if [ -f "$FILE" ]; then
  # print ~120 lines around table() definition
  rg -n --type=php 'function\s+table\s*\(' "$FILE"
  # show from table() to columns/closing (best-effort)
  start=$(rg -n --type=php 'function\s+table\s*\(' "$FILE" | head -n 1 | cut -d: -f1)
  if [ -n "${start:-}" ]; then
    from=$((start-20))
    to=$((start+180))
    sed -n "${from},${to}p" "$FILE" | nl -ba | sed -n '1,220p'
  fi
else
  echo "Missing: $FILE"
fi

Repository: he4rt/heartdevs.com

Length of output: 1879


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE_USER="app-modules/identity/src/User/Models/User.php"
FILE_RESOURCE="app-modules/panel-admin/src/Filament/Resources/Users/UserResource.php"

echo "== profile mentions in User model =="
if [ -f "$FILE_USER" ]; then
  rg -n --type=php 'profile' "$FILE_USER" || true
  echo
  echo "== User model excerpt around relationship-like methods =="
  # show first ~220 lines to include relationship methods; cap output
  sed -n '1,220p' "$FILE_USER" | cat -n
fi

echo
echo "== relationship methods in identity models mentioning profile =="
fd -t f 'Models/*.php' app-modules/identity/src | head -n 50 >/dev/null 2>&1 || true
rg -n --type=php 'function\s+[A-Za-z0-9_]*profile[A-Za-z0-9_]*\s*\(' app-modules/identity/src || true
rg -n --type=php '->profile' app-modules/identity/src || true
rg -n --type=php 'with\(\s*[\"\x27]profile[\"\x27]\s*\)' . || true

echo
echo "== Inspect UserResource::table() =="
if [ -f "$FILE_RESOURCE" ]; then
  # find where table() starts
  start=$(rg -n --type=php 'function\s+table\s*\(' "$FILE_RESOURCE" | head -n 1 | cut -d: -f1)
  if [ -n "${start:-}" ]; then
    from=$((start-30))
    to=$((start+220))
    sed -n "${from},${to}p" "$FILE_RESOURCE" | cat -n
  fi
fi

echo
echo "== Search for any eager loading in UserResource.php =="
rg -n --type=php 'with\(|eager|modifyQueryUsing|withCount|load\(' "$FILE_RESOURCE" || true

Repository: he4rt/heartdevs.com

Length of output: 9180


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Any profile() methods in app-modules (PHP) =="
rg -n --type=php 'function\s+profile\s*\(' app-modules . || true

echo
echo "== Any getProfile accessors in app-modules =="
rg -n --type=php '(function\s+getProfile\s*\(|\bgetProfile\b|->profile\b)' app-modules . || true

echo
echo "== Search for profile fields used in Filament columns =="
for f in "headline" "seniority_level" "years_experience" "available_for_proposals"; do
  echo "-- $f --"
  rg -n --type=php "$f" app-modules/identity app-modules/panel-admin . | head -n 50 || true
done

echo
echo "== Inspect HasAddress trait for possible profile accessor =="
HAS_ADDRESS_FILE="$(fd -t f 'HasAddress.php' . | head -n 5 | tr '\n' ' ' || true)"
if [ -z "${HAS_ADDRESS_FILE:-}" ]; then
  echo "HasAddress.php not found via fd"
else
  echo "Found: $HAS_ADDRESS_FILE"
  for f in $HAS_ADDRESS_FILE; do
    echo
    echo "---- $f (profile mentions) ----"
    rg -n --type=php 'profile' "$f" || true
    echo
    echo "---- $f (excerpt) ----"
    sed -n '1,220p' "$f" | cat -n
  done
fi

echo
echo "== Filament columns - confirm UserResource doesn't eager load =="
FILE_RESOURCE="app-modules/panel-admin/src/Filament/Resources/Users/UserResource.php"
if [ -f "$FILE_RESOURCE" ]; then
  sed -n '1,120p' "$FILE_RESOURCE" | cat -n
  rg -n --type=php 'modifyQueryUsing|with\(|eager|load\(' "$FILE_RESOURCE" || true
fi

Repository: he4rt/heartdevs.com

Length of output: 29345


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Inspect Profile model (relationships) =="
FILE_PROFILE="app-modules/profile/src/Models/Profile.php"
if [ -f "$FILE_PROFILE" ]; then
  sed -n '1,220p' "$FILE_PROFILE" | cat -n
else
  echo "Missing $FILE_PROFILE"
fi

echo
echo "== Search for Profile::class usage in identity/user models =="
rg -n --type=php 'Profile::class' app-modules/identity/src || true

echo
echo "== Search for relationships to user_profiles / headline/seniority fields (hints of inverse relation) =="
rg -n --type=php 'user_profiles|UserProfile|available_for_proposals|years_experience|seniority_level' app-modules/identity/src || true

echo
echo "== Inspect UserResourceTest expectations for profile.* columns =="
FILE_TEST="app-modules/panel-admin/tests/Feature/Users/UserResourceTest.php"
if [ -f "$FILE_TEST" ]; then
  sed -n '1,220p' "$FILE_TEST" | cat -n
fi

echo
echo "== Inspect EditUser::getProfile (how profile is loaded) =="
FILE_EDIT="app-modules/panel-admin/src/Filament/Resources/Users/Pages/EditUser.php"
if [ -f "$FILE_EDIT" ]; then
  sed -n '1,220p' "$FILE_EDIT" | cat -n
fi

echo
echo "== Broader: any method named profile* or accessors in User model traits =="
# show traits used by User model
sed -n '1,140p' "app-modules/identity/src/User/Models/User.php" | cat -n | rg -n 'use\s+' || true

# search for profile methods in any trait used by User
rg -n --type=php 'function\s+profile\s*\(' app-modules app/ || true
rg -n --type=php 'getProfileAttribute' app-modules app/ || true

Repository: he4rt/heartdevs.com

Length of output: 15193


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Inspect InteractsWithTenants trait =="
FILE_TENANT="app-modules/identity/src/Tenant/Concerns/InteractsWithTenants.php"
if [ -f "$FILE_TENANT" ]; then
  sed -n '1,220p' "$FILE_TENANT" | cat -n
  echo
  rg -n --type=php 'profile' "$FILE_TENANT" || true
else
  echo "Missing $FILE_TENANT"
fi

echo
echo "== Inspect ListUsers page =="
FILE_LIST="app-modules/panel-admin/src/Filament/Resources/Users/Pages/ListUsers.php"
if [ -f "$FILE_LIST" ]; then
  sed -n '1,260p' "$FILE_LIST" | cat -n
  echo
  rg -n --type=php 'with\(|modifyQueryUsing|eager|profile' "$FILE_LIST" || true
else
  echo "Missing $FILE_LIST"
fi

echo
echo "== Search for profile accessors/relations across repo =="
rg -n --type=php 'getProfileAttribute\s*\(' . || true
rg -n --type=php 'function\s+profile\s*\(' . || true
rg -n --type=php '\bprofile\s*\(\)\s*:' . || true
rg -n --type=php '->profile\b' app-modules/identity app-modules/panel-admin . || true

echo
echo "== Search for with(\"profile\") or with('profile') usage =="
rg -n --type=php 'with\(\s*[\"'\'']profile[\"'\'']\s*\)' . || true

Repository: he4rt/heartdevs.com

Length of output: 2806


🌐 Web query:

Filament TextColumn make('relation.field') eager load N+1 dot notation behavior

💡 Result:

In Filament, using dot notation (e.g., TextColumn::make('relation.field')) automatically triggers eager loading for the specified relationship to avoid the N+1 query problem [1][2]. Filament analyzes the column name and detects the relationship chain, ensuring the related records are fetched efficiently [1][2]. However, if you are accessing relationship data through custom methods—such as within description() or closures like state()—Filament may not automatically detect the need for eager loading, which can result in N+1 issues [3][4]. To resolve or prevent N+1 issues in these scenarios: 1. Use modifyQueryUsing: For table columns, you can force eager loading by using the modifyQueryUsing() method on the table definition [3]: $table->modifyQueryUsing(fn (Builder $query) => $query->with('relation.nestedRelation')) 2. Eager Load at the Query Level: If you find specific parts of your application are still triggering N+1 queries, ensure that the underlying Eloquent query is prepared with the necessary relationships using standard Laravel eager loading techniques before the data reaches the Filament components [5]. 3. Pivot Relationships: When dealing with pivot table data (e.g., pivot.relation.field), standard eager loading also applies, but ensure the relationships are correctly defined in your pivot model [6]. If you are encountering N+1 issues despite using dot notation, it is typically because the data access is occurring outside of the standard column resolution path (e.g., inside a custom state() or description() closure) [3][4]. In such cases, manually defining the eager load in modifyQueryUsing is the recommended solution [3].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE_USER="app-modules/identity/src/User/Models/User.php"
echo "== User.php line count =="
wc -l "$FILE_USER"

echo
echo "== Last 80 lines of User.php =="
tail -n 80 "$FILE_USER" | cat -n

Repository: he4rt/heartdevs.com

Length of output: 2637


Fix profile.* columns by adding the missing User::profile() relationship (and then eager-load it).

app-modules/panel-admin/src/Filament/Resources/Users/UserResource.php renders TextColumn::make('profile.*'), but app-modules/identity/src/User/Models/User.php defines no profile() relationship (Profile model only has user()/tenant()), so those columns can’t be resolved correctly.

⚡ Proposed fix (eager-load once the relationship exists)
 public static function table(Table $table): Table
 {
     return $table
+        ->modifyQueryUsing(fn (Builder $query) => $query->with('profile'))
         ->columns([
🤖 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-admin/src/Filament/Resources/Users/UserResource.php` around
lines 45 - 63, The UserResource is referencing related fields via
TextColumn::make('profile.*') but the User model lacks a profile() relationship
and the relation isn't being eager-loaded, so add a profile() relation method to
the User model (returning a hasOne to the Profile model) and update UserResource
to eager-load('profile') in the query provider (or
getEloquentQuery/getTableQuery override) so
TextColumn::make('profile.headline'), 'profile.seniority_level',
'profile.years_experience', and 'profile.available_for_proposals' resolve
correctly.

Comment on lines +71 to +73
Filter::make('created_at')
->label('Criado este mês')
->query(fn (Builder $query) => $query->whereMonth('created_at', now()->month)),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add year constraint to the month filter.

The filter is labeled "Criado este mês" (Created this month) but only checks the month, not the year. This means in June 2026 it will match users created in June of any year (2025, 2024, etc.), not just June 2026.

📅 Proposed fix to check both month and year
 Filter::make('created_at')
     ->label('Criado este mês')
-    ->query(fn (Builder $query) => $query->whereMonth('created_at', now()->month)),
+    ->query(fn (Builder $query) => $query
+        ->whereMonth('created_at', now()->month)
+        ->whereYear('created_at', now()->year)),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Filter::make('created_at')
->label('Criado este mês')
->query(fn (Builder $query) => $query->whereMonth('created_at', now()->month)),
Filter::make('created_at')
->label('Criado este mês')
->query(fn (Builder $query) => $query
->whereMonth('created_at', now()->month)
->whereYear('created_at', now()->year)),
🤖 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-admin/src/Filament/Resources/Users/UserResource.php` around
lines 71 - 73, The "Criado este mês" filter currently only checks month and may
match other years; update the Filter::make('created_at')->query callback to
constrain by both month and year by adding a whereYear('created_at',
now()->year) alongside the existing whereMonth call so the Builder query checks
the current month AND the current year.

@danielhe4rt danielhe4rt force-pushed the feat/256-admin-panel-profile-tab branch from 790e1c0 to 4aa9c9b Compare June 6, 2026 19:00
@danielhe4rt danielhe4rt marked this pull request as draft June 6, 2026 19:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(panel-admin): profile tab on UserResource

2 participants