feat: improvements admin ui#117
Conversation
…es for message and meeting types
WalkthroughAdds Filament StatsOverview widgets (events, seasons, tenants, users), registers them in admin panel plugins, refactors Season resources into an Admin namespace and updates tests, adds navigation sort/badges to resources, introduces User::isAdmin(), reorganizes admin navigation into groups, and extends BaseSeeder with meetings/messages and a shifted season end date. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Filament
participant Widget as StatsOverviewWidget
participant Auth as Auth
participant DB as Database
Filament->>Widget: render()
Widget->>Auth: auth()->user()
Auth-->>Widget: User
alt non-admin (tenant-scoped)
Widget->>DB: query scoped to tenant (where tenant_id = ...)
else admin/global
Widget->>DB: global query
end
DB-->>Widget: aggregated metrics (counts, relations)
Widget->>Filament: render stats (labels/icons/colors)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
app-modules/user/src/Models/User.php (1)
25-29: Define theTwo points here:
- Phpstan failure (
undefined property $email)
The newisAdmin()method accesses$this->email, but the model’s phpdoc only documentsid,username, andis_donator. Phpstan is complaining because it doesn’t see anUser. You can fix this cleanly by extending the docblock to include the email column:/** * @property string $id * @property string $username * @property bool $is_donator + * @property string|null $email */This matches the existing
fillablearray and should satisfy phpstan without changing runtime behavior.
- Hard‑coded admin email (optional refactor)
isAdmin()currently hard‑codesadmin@admin.com. That’s fine for now, but if you ever need multiple admins or a configurable address, consider delegating this to a role/permission system or a config value (e.g.,config('auth.admin_email')) to avoid scattering this literal across the codebase.Also applies to: 48-51
🧹 Nitpick comments (4)
app-modules/events/src/Filament/Shared/Widgets/ActiveEventsStats.php (1)
56-59: Inconsistent counting approach across stats.Line 56 calls
$event->talks()->count()(relationship query), while lines 46 and 51 access count attributes (attendees_count,waitlist_count). For consistency and to avoid extra queries, consider loadingtalks_countviawithCount()as well (see earlier comment on lines 20-26) and then accessing it as$event->talks_count.If you apply the
withCount()fix from the earlier comment, also access talks consistently:- Stat::make('Talks cadastradas', $event->talks()->count()) + Stat::make('Talks cadastradas', $event->talks_count)app/Providers/Filament/AdminPanelProvider.php (1)
12-12: Navigation groups are well structured; consider fixing the “Gamefication” labelThe new
navigationGroups()call cleanly organizes the admin menu into logical sections and should work well with resources that setprotected static ?string $navigationGroup.Very small nit: if this isn’t intentional branding, you may want to rename:
- NavigationGroup::make()->label('Gamefication'), + NavigationGroup::make()->label('Gamification'),to avoid a visible typo in the UI.
Also applies to: 44-58
app-modules/user/src/Filament/Admin/Resources/Users/UserResource.php (1)
34-34: User navigation sort and badge follow existing resource patternsSetting
protected static ?int $navigationSort = 1;and usinggetNavigationBadge()to return the user count is consistent with how other resources expose badges and ordering. This should integrate smoothly into the new navigation groups.If the users table grows very large, you might later consider caching this count, but for typical admin usage this is fine as-is.
Also applies to: 46-49
app-modules/tenant/src/Filament/Admin/Resources/Tenants/TenantResource.php (1)
28-28: Tenant navigation ordering and badge are consistent with the rest of the panel
$navigationSort = 2positions tenants right after users in the Administration group, andgetNavigationBadge()mirrors the count‑badge pattern used in other resources. Implementation looks straightforward and consistent. For very large tenant datasets, you could later cache this value if needed.Also applies to: 34-37
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (24)
app-modules/events/src/AdminEventPanelPlugin.php(2 hunks)app-modules/events/src/Filament/Shared/Widgets/ActiveEventsStats.php(1 hunks)app-modules/meeting/database/factories/MeetingTypeFactory.php(1 hunks)app-modules/season/src/AdminSeasonPanelPlugin.php(2 hunks)app-modules/season/src/Filament/Admin/Resources/Seasons/Pages/CreateSeason.php(1 hunks)app-modules/season/src/Filament/Admin/Resources/Seasons/Pages/EditSeason.php(1 hunks)app-modules/season/src/Filament/Admin/Resources/Seasons/Pages/ListSeasons.php(1 hunks)app-modules/season/src/Filament/Admin/Resources/Seasons/Schemas/SeasonForm.php(1 hunks)app-modules/season/src/Filament/Admin/Resources/Seasons/SeasonResource.php(1 hunks)app-modules/season/src/Filament/Admin/Resources/Seasons/Tables/SeasonsTable.php(2 hunks)app-modules/season/src/Filament/Shared/Widgets/SeasonStatsOverview.php(1 hunks)app-modules/season/tests/Feature/Filament/Admin/CreateSeasonTest.php(1 hunks)app-modules/season/tests/Feature/Filament/Admin/EditSeasonTest.php(1 hunks)app-modules/season/tests/Feature/Filament/Admin/ListSeasonTest.php(1 hunks)app-modules/tenant/src/Filament/Admin/Resources/Tenants/TenantResource.php(1 hunks)app-modules/tenant/src/Filament/Admin/Widgets/TenantsStatsOverview.php(1 hunks)app-modules/tenant/src/Plugins/AdminTenantPanelPlugin.php(2 hunks)app-modules/user/src/Filament/Admin/Resources/Users/Pages/ListUsers.php(1 hunks)app-modules/user/src/Filament/Admin/Resources/Users/UserResource.php(2 hunks)app-modules/user/src/Filament/Shared/Widgets/UsersStatsOverview.php(1 hunks)app-modules/user/src/Models/User.php(1 hunks)app-modules/user/src/Plugins/AdminUserPanelPlugin.php(2 hunks)app/Providers/Filament/AdminPanelProvider.php(2 hunks)database/seeders/BaseSeeder.php(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (22)
app-modules/season/src/Filament/Admin/Resources/Seasons/Pages/CreateSeason.php (1)
app-modules/season/src/Filament/Admin/Resources/Seasons/SeasonResource.php (1)
SeasonResource(20-48)
app-modules/user/src/Filament/Shared/Widgets/UsersStatsOverview.php (1)
app-modules/user/src/Models/User.php (1)
isAdmin(48-51)
app-modules/user/src/Filament/Admin/Resources/Users/Pages/ListUsers.php (2)
app-modules/user/src/Filament/Shared/Widgets/UsersStatsOverview.php (1)
UsersStatsOverview(13-49)app-modules/user/src/Filament/Admin/Resources/Users/UserResource.php (1)
UserResource(24-69)
app-modules/tenant/src/Filament/Admin/Widgets/TenantsStatsOverview.php (1)
app-modules/tenant/src/Models/Tenant.php (1)
Tenant(22-94)
app-modules/user/src/Filament/Admin/Resources/Users/UserResource.php (3)
app-modules/tenant/src/Filament/Admin/Resources/Tenants/TenantResource.php (1)
getNavigationBadge(34-37)app-modules/events/src/Filament/Admin/Resources/Events/EventResource.php (1)
getNavigationBadge(32-35)app-modules/events/src/Filament/Admin/Resources/Talks/TalkResource.php (1)
getNavigationBadge(32-35)
app-modules/user/src/Models/User.php (3)
app-modules/user/database/factories/UserFactory.php (2)
UserFactory(10-22)definition(14-21)app-modules/user/src/Repositories/UserEloquentRepository.php (1)
createUser(73-88)app-modules/user/src/Entities/UserEntity.php (1)
UserEntity(11-42)
app-modules/season/src/Filament/Admin/Resources/Seasons/Pages/EditSeason.php (1)
app-modules/season/src/Filament/Admin/Resources/Seasons/SeasonResource.php (1)
SeasonResource(20-48)
app-modules/tenant/src/Filament/Admin/Resources/Tenants/TenantResource.php (3)
app-modules/user/src/Filament/Admin/Resources/Users/UserResource.php (1)
getNavigationBadge(46-49)app-modules/events/src/Filament/Admin/Resources/Events/EventResource.php (1)
getNavigationBadge(32-35)app-modules/events/src/Filament/Admin/Resources/Talks/TalkResource.php (1)
getNavigationBadge(32-35)
app-modules/season/tests/Feature/Filament/Admin/CreateSeasonTest.php (1)
app-modules/season/src/Filament/Admin/Resources/Seasons/Pages/CreateSeason.php (1)
CreateSeason(10-13)
database/seeders/BaseSeeder.php (4)
app-modules/meeting/src/Models/Meeting.php (2)
Meeting(17-89)Meeting(15-67)app-modules/message/src/Models/Message.php (1)
Message(16-63)app-modules/meeting/database/factories/MeetingFactory.php (1)
MeetingFactory(12-32)app-modules/season/src/Models/Season.php (1)
meetings(39-42)
app-modules/meeting/database/factories/MeetingTypeFactory.php (2)
app-modules/meeting/src/Models/MeetingType.php (5)
startAt(35-40)generateStartAt(42-51)value(38-38)MeetingType(18-52)newFactory(30-33)app-modules/meeting/database/factories/MeetingFactory.php (2)
definition(16-26)MeetingFactory(12-32)
app-modules/user/src/Plugins/AdminUserPanelPlugin.php (1)
app-modules/user/src/Filament/Shared/Widgets/UsersStatsOverview.php (1)
UsersStatsOverview(13-49)
app-modules/season/src/AdminSeasonPanelPlugin.php (2)
app-modules/season/src/Filament/Admin/Resources/Seasons/SeasonResource.php (1)
SeasonResource(20-48)app-modules/season/src/Filament/Shared/Widgets/SeasonStatsOverview.php (1)
SeasonStatsOverview(12-51)
app-modules/season/src/Filament/Admin/Resources/Seasons/SeasonResource.php (5)
app-modules/season/src/Filament/Admin/Resources/Seasons/Pages/CreateSeason.php (1)
CreateSeason(10-13)app-modules/season/src/Filament/Admin/Resources/Seasons/Pages/EditSeason.php (1)
EditSeason(11-21)app-modules/season/src/Filament/Admin/Resources/Seasons/Pages/ListSeasons.php (1)
ListSeasons(11-21)app-modules/season/src/Filament/Admin/Resources/Seasons/Schemas/SeasonForm.php (1)
SeasonForm(13-48)app-modules/season/src/Filament/Admin/Resources/Seasons/Tables/SeasonsTable.php (1)
SeasonsTable(13-59)
app-modules/events/src/AdminEventPanelPlugin.php (1)
app-modules/events/src/Filament/Shared/Widgets/ActiveEventsStats.php (1)
ActiveEventsStats(12-67)
app-modules/season/tests/Feature/Filament/Admin/ListSeasonTest.php (1)
app-modules/season/src/Filament/Admin/Resources/Seasons/Pages/ListSeasons.php (1)
ListSeasons(11-21)
app-modules/season/tests/Feature/Filament/Admin/EditSeasonTest.php (1)
app-modules/season/src/Filament/Admin/Resources/Seasons/Pages/EditSeason.php (1)
EditSeason(11-21)
app-modules/season/src/Filament/Shared/Widgets/SeasonStatsOverview.php (2)
app-modules/season/src/Models/Season.php (4)
Season(29-85)badges(34-37)Season(15-48)meetings(39-42)app-modules/season/database/migrations/2023_01_30_174411_create_seasons_table.php (1)
Blueprint(17-28)
app-modules/season/src/Filament/Admin/Resources/Seasons/Tables/SeasonsTable.php (4)
app-modules/season/src/Models/Season.php (2)
Season(29-85)Season(15-48)app-modules/season/database/migrations/2023_01_30_174411_create_seasons_table.php (1)
Blueprint(17-28)app-modules/season/src/Entities/SeasonEntity.php (1)
SeasonEntity(10-45)app-modules/season/database/factories/SeasonFactory.php (1)
SeasonFactory(10-28)
app-modules/events/src/Filament/Shared/Widgets/ActiveEventsStats.php (4)
app-modules/user/src/Filament/Shared/Widgets/UsersStatsOverview.php (1)
getStats(17-48)app-modules/user/src/Models/User.php (1)
isAdmin(48-51)app-modules/events/src/Models/Talk.php (1)
event(46-49)app-modules/events/src/Models/EventModel.php (2)
talks(146-149)attendees(67-79)
app-modules/tenant/src/Plugins/AdminTenantPanelPlugin.php (1)
app-modules/tenant/src/Filament/Admin/Widgets/TenantsStatsOverview.php (1)
TenantsStatsOverview(12-55)
app-modules/season/src/Filament/Admin/Resources/Seasons/Pages/ListSeasons.php (1)
app-modules/season/src/Filament/Admin/Resources/Seasons/SeasonResource.php (1)
SeasonResource(20-48)
🪛 GitHub Check: Perform Phpstan Check / Run
app-modules/user/src/Models/User.php
[failure] 50-50:
Access to an undefined property He4rt\User\Models\User::$email.
🔇 Additional comments (22)
app-modules/season/tests/Feature/Filament/Admin/ListSeasonTest.php (1)
7-7: LGTM! Namespace refactor aligns with Admin restructuring.The import path correctly reflects the new Admin namespace structure for Season resources.
app-modules/season/src/Filament/Admin/Resources/Seasons/Schemas/SeasonForm.php (1)
5-5: LGTM! Namespace refactor aligns with Admin restructuring.The namespace correctly reflects the new Admin structure for Season schemas.
app-modules/season/tests/Feature/Filament/Admin/EditSeasonTest.php (1)
7-7: LGTM! Namespace refactor aligns with Admin restructuring.The import path correctly reflects the new Admin namespace structure.
app-modules/season/src/AdminSeasonPanelPlugin.php (2)
10-11: LGTM! Namespace refactor and new widget import.The SeasonResource import is correctly updated to the Admin namespace, and the SeasonStatsOverview widget import aligns with the PR's dashboard widget additions.
25-28: LGTM! Widget registration added.The SeasonStatsOverview widget is properly registered with the admin panel, enabling the new dashboard statistics for seasons.
app-modules/season/src/Filament/Admin/Resources/Seasons/Pages/ListSeasons.php (1)
5-9: LGTM! Namespace refactor aligns with Admin restructuring.Both the namespace declaration and the SeasonResource import are correctly updated to the Admin namespace structure.
app-modules/season/tests/Feature/Filament/Admin/CreateSeasonTest.php (1)
7-7: LGTM! Namespace refactor aligns with Admin restructuring.The import path correctly reflects the new Admin namespace structure.
app-modules/season/src/Filament/Admin/Resources/Seasons/Pages/CreateSeason.php (1)
5-8: LGTM! Namespace refactor aligns with Admin restructuring.Both the namespace declaration and the SeasonResource import are correctly updated to the Admin namespace structure.
app-modules/season/src/Filament/Admin/Resources/Seasons/Tables/SeasonsTable.php (2)
5-5: LGTM! Namespace refactor aligns with Admin restructuring.The namespace correctly reflects the new Admin structure for Season tables.
27-27: Excellent defensive improvement with nullsafe operator!The nullsafe operator (
?->) correctly handles the nullableended_atfield, preventing potential null reference errors when formatting the date. This aligns with the database schema whereended_atis nullable, especially for active seasons without an end date.app-modules/season/src/Filament/Admin/Resources/Seasons/Pages/EditSeason.php (1)
5-9: LGTM! Clean namespace refactor.The namespace and import path updates correctly align with the Admin directory structure reorganization described in the PR objectives.
app-modules/season/src/Filament/Shared/Widgets/SeasonStatsOverview.php (1)
18-24: LGTM! Active season query logic is sound.The query correctly identifies the current active season by checking
started_at <= now()and eitherended_atis null orended_at > now().app-modules/season/src/Filament/Admin/Resources/Seasons/SeasonResource.php (1)
5-16: LGTM! Comprehensive namespace migration to Admin structure.All namespace and import paths have been consistently updated to reflect the new Admin directory organization. The refactor includes the resource itself and all related dependencies (Pages, Schemas, Tables).
app-modules/events/src/Filament/Shared/Widgets/ActiveEventsStats.php (1)
22-24: Admin check relies on hardcoded email comparison.The
isAdmin()method (defined in the User model) checks whether the user's email equals'admin@admin.com'. While this may be acceptable for a development or proof-of-concept environment, it's a weak authorization mechanism for production.Consider verifying whether a role-based or permission-based authorization system should be used instead. If this is intentional for the current stage, document it clearly.
Based on learnings.
app-modules/events/src/AdminEventPanelPlugin.php (1)
12-12: LGTM!The import and registration of the
ActiveEventsStatswidget follow the standard Filament plugin pattern correctly.Also applies to: 28-30
database/seeders/BaseSeeder.php (3)
10-11: LGTM!The imports are correctly added to support the new seeding operations for meetings and messages.
73-73: Good improvement for test data.Changing the season end date to a future date creates an active season for testing, which is more useful than a season that ends today.
80-83: Original review comment is based on incorrect assumptions about the Message factory structure.The Message factory does not define a
season()relationship. It hardcodes'season_id' => 2as a direct integer value. Therefore, the proposed solution using->recycle($season)will not work—the factory has no relationship to recycle.While the concern about season associations is valid (the hardcoded
season_idof 2 may not exist in a fresh database), the suggested fix is incompatible with the current factory design. If the season ID should be dynamic based on the seeder, the factory definition would need to be modified to define a season relationship, or the seeder would need to override it using->state(['season_id' => $season->id]).Likely an incorrect or invalid review comment.
app-modules/tenant/src/Plugins/AdminTenantPanelPlugin.php (1)
11-11: Tenants stats widget registration looks consistentImporting and registering
TenantsStatsOverviewvia$panel->widgets([...])aligns with the existing plugin pattern and should correctly expose the new stats widget on the tenant admin panel.Also applies to: 26-28
app-modules/user/src/Plugins/AdminUserPanelPlugin.php (1)
11-11: Users stats widget is wired correctly into the admin panelRegistering
UsersStatsOverviewvia$panel->widgets([...])is consistent with the other plugins and should surface the stats overview on the user admin panel as intended.Also applies to: 26-28
app-modules/user/src/Filament/Admin/Resources/Users/Pages/ListUsers.php (1)
10-21: Header widget integration for user stats looks goodUsing
getHeaderWidgets()to includeUsersStatsOverview::classis idiomatic Filament and will display the stats block at the top of the ListUsers page. No issues spotted.app-modules/user/src/Filament/Shared/Widgets/UsersStatsOverview.php (1)
7-12: Users stats widget logic is solid; consider guarding against missing tenant in non-admin contextsThe widget’s query composition looks good:
- Starts from
User::query().- For non-admins, scopes by
tenantsso users only see stats for their tenant.- Reuses the base query via
clonefor donators, today, and month counts.- Output
Statcards are clear and consistent with the rest of the dashboard.One thing to double‑check: in the non‑admin branch you call:
$query->whereHas('tenants', fn (Builder $q) => $q->where('tenants.id', Filament::getTenant()->getKey()));If there is any scenario where a non‑admin can hit this widget without an active tenant (i.e.,
Filament::getTenant()returnsnull), this will throw. If that scenario is possible, consider a null‑safe guard, e.g. early‑returning zeros or skipping thewhereHaswhen no tenant is set.Otherwise, the implementation is concise and matches the intended tenancy behavior.
Also applies to: 17-47
…ed this month using date range
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
app-modules/season/src/Filament/Shared/Widgets/SeasonStatsOverview.php(1 hunks)app-modules/tenant/src/Filament/Admin/Widgets/TenantsStatsOverview.php(1 hunks)app-modules/user/src/Models/User.php(2 hunks)database/seeders/BaseSeeder.php(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- app-modules/season/src/Filament/Shared/Widgets/SeasonStatsOverview.php
- database/seeders/BaseSeeder.php
- app-modules/user/src/Models/User.php
🧰 Additional context used
🧬 Code graph analysis (1)
app-modules/tenant/src/Filament/Admin/Widgets/TenantsStatsOverview.php (1)
app-modules/tenant/src/Models/Tenant.php (1)
Tenant(22-94)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Perform Pest Tests / Run
🔇 Additional comments (2)
app-modules/tenant/src/Filament/Admin/Widgets/TenantsStatsOverview.php (2)
14-26: Overall widget logic and basic stats look solid
getStats()is straightforward and readable: active count, “created this month” window withwhereBetween, andwithCount('members')for the “most users” tenant are all correct and handle nulls nicely via the null‑safe operator when building the Stat cards. No issues here.
35-55: Stat card rendering is consistent and null‑safeThe four
Stat::make(...)calls are cohesive, handle the “no tenant” case gracefully ('Nenhum'+ empty description), and use consistent icon/color conventions. This matches the patterns used in other admin widgets and should integrate cleanly into the Filament dashboard.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
app-modules/meeting/database/factories/MeetingTypeFactory.php (1)
17-23: Factory generatesH:istrings but model accessor still assumes integer minutes, causing incorrect times
MeetingTypeFactorynow sets'start_at' => fake()->time('H:i'), butHe4rt\Meeting\Models\MeetingType::startAt()callsgenerateStartAt($value)which doesintdiv($value, 60)and$value % 60. With a value like"14:30", PHP coerces it to14, producing"00:14"instead of"14:30", so seeded/fixture data will have corrupted times and an inconsistent contract between model and factory.Unless you simultaneously update
generateStartAt()(and possibly the DB column) to work withH:istrings, this change should be reverted to generate integer minutes (0–1439):- 'start_at' => fake()->time('H:i'), + 'start_at' => fake()->numberBetween(0, 1439),If you truly want
H:istorage, adjustgenerateStartAt()to parseH:i(e.g., viaexplodeor Carbon) instead of doing integer division/modulo on the raw string, and ensure migrations and casts are aligned.
🧹 Nitpick comments (1)
database/seeders/BaseSeeder.php (1)
76-79: Consider reusing the existing admin user.The tenant association is now correctly handled with
->recycle($tenant). However, the factory will create newUserinstances for theadmin_idrelationship, which may be unnecessary in a seeding context.You can optionally reuse the existing
$userfor the admin relationship to reduce seeded data:Meeting::factory() ->count(5) ->recycle($tenant) + ->recycle($user) ->create();
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
app-modules/meeting/database/factories/MeetingTypeFactory.php(1 hunks)app-modules/tenant/src/Filament/Admin/Widgets/TenantsStatsOverview.php(1 hunks)database/seeders/BaseSeeder.php(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- app-modules/tenant/src/Filament/Admin/Widgets/TenantsStatsOverview.php
🧰 Additional context used
🧬 Code graph analysis (2)
database/seeders/BaseSeeder.php (3)
app-modules/meeting/src/Models/Meeting.php (2)
Meeting(17-89)Meeting(15-67)app-modules/message/src/Models/Message.php (1)
Message(16-63)app-modules/meeting/database/factories/MeetingFactory.php (1)
MeetingFactory(12-32)
app-modules/meeting/database/factories/MeetingTypeFactory.php (1)
app-modules/meeting/src/Models/MeetingType.php (4)
value(38-38)startAt(35-40)generateStartAt(42-51)newFactory(30-33)
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
app-modules/tenant/src/Filament/Admin/Widgets/TenantsStatsOverview.php(1 hunks)app-modules/tenant/src/Models/Tenant.php(2 hunks)database/seeders/BaseSeeder.php(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- database/seeders/BaseSeeder.php
🧰 Additional context used
🧬 Code graph analysis (2)
app-modules/tenant/src/Models/Tenant.php (2)
app-modules/message/src/Models/Message.php (2)
Message(16-63)Message(12-34)database/migrations/2023_01_18_211845_create_messages_table.php (1)
Blueprint(17-27)
app-modules/tenant/src/Filament/Admin/Widgets/TenantsStatsOverview.php (1)
app-modules/tenant/src/Models/Tenant.php (1)
Tenant(23-103)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Perform Pest Tests / Run
🔇 Additional comments (4)
app-modules/tenant/src/Filament/Admin/Widgets/TenantsStatsOverview.php (4)
15-19: LGTM!The date filtering correctly uses
whereBetween()withstartOfMonth()andendOfMonth(), which properly restricts to the current month of the current year and is index-friendly. This addresses the previous issue withwhereMonth()that ignored the year component.
21-24: LGTM!The
withCount('members')approach correctly leverages Laravel's aggregation and avoids N+1 queries. Themembers()relationship exists on the Tenant model, so this will work as expected.
26-28: LGTM!Using
withCount('messages')is the correct approach and cleanly avoids the Cartesian product and double-counting issues from the previous LEFT JOIN implementation. This depends on themessages()relationship added to the Tenant model in this PR.
30-51: LGTM!The stats array properly uses null-safe operators (
?->) and ternary checks to handle cases where no tenants are found. The Portuguese labels, icons, and colors are appropriate and consistent.
This pull request introduces new dashboard widgets for the admin panels of the Events, Season, Tenant, and User modules, providing richer statistics and insights for administrators. It also refactors the Season module to use a more consistent directory structure and improves some resource and table definitions for better reliability and navigation.
Dashboard Widget Additions:
ActiveEventsStatswidget to the Events admin panel, displaying live statistics about the current event, attendees, waitlist, talks, and sponsors. [1] [2] [3]SeasonStatsOverviewwidget to the Season admin panel, showing statistics about the active season, XP, messages, and participants. [1] [2] [3]TenantsStatsOverviewwidget to the Tenant admin panel, with stats on active tenants, new tenants this month, tenants with most users, and most messages. [1] [2] [3]UsersStatsOverviewwidget to the User admin panel, showing users created today, this month, and total donators. [1] [2]Season Module Refactor:
Filament\Admin\Resources\Seasonsnamespace for better organization and maintainability. This includes renaming and updating imports in several files. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10]Resource and Table Improvements:
ended_atdates.Other Minor Improvements:
MeetingTypeFactoryto use a time string forstart_atinstead of a number, improving test data realism.Summary by CodeRabbit
New Features
UX / Navigation
Bug Fixes
Chores
✏️ Tip: You can customize this high-level summary in your review settings.