Enhance the admin user management interface to display vehicle information associated with each user, and add a system-wide total vehicles widget to the admin dashboard.
Requirements
1. Total Vehicles Widget (Admin Dashboard)
Add a new widget displaying the total number of vehicles across all users
Match the existing "Total Users" widget style exactly (same card design, different icon/number)
Position: To the right of the Total Users widget
2. User Vehicle List (Admin User Management)
Display vehicles associated with each user in an expandable accordion row
Display format: Year / Make / Model only (privacy consideration - no additional details)
Interaction: Click on user row to expand/collapse vehicle list inline
Accordion style keeps context, no navigation away from user list
3. User Profile Page
Users should be able to see their own vehicles on their profile page
Same Year / Make / Model format
Security Requirements
Admin Only: Vehicle-per-user viewing is restricted to admin accounts
Strict User Separation: Normal users cannot see any other user's information
Users can only view their own vehicle information on their profile
UI/UX Specifications
Component
Style
Total Vehicles Widget
Match Total Users widget exactly (card, typography, spacing)
Vehicle Count Icon
Vehicle/car icon (differentiate from user icon)
Accordion Row
Inline expansion below user row
Vehicle List
Simple table: Year
Acceptance Criteria
Total Vehicles widget displays correct system-wide count
Widget positioned to right of Total Users widget
Widget styling matches Total Users exactly
Admin can expand user row to see their vehicles
Vehicle list shows only Year/Make/Model
Non-admin users cannot access other users' vehicle data
Users can see their own vehicles on profile page
Mobile responsive (both widgets and accordion)
Desktop responsive
## Summary
Enhance the admin user management interface to display vehicle information associated with each user, and add a system-wide total vehicles widget to the admin dashboard.
## Requirements
### 1. Total Vehicles Widget (Admin Dashboard)
- Add a new widget displaying the total number of vehicles across all users
- Match the existing "Total Users" widget style exactly (same card design, different icon/number)
- Position: To the right of the Total Users widget
### 2. User Vehicle List (Admin User Management)
- Display vehicles associated with each user in an expandable accordion row
- **Display format**: Year / Make / Model only (privacy consideration - no additional details)
- **Interaction**: Click on user row to expand/collapse vehicle list inline
- Accordion style keeps context, no navigation away from user list
### 3. User Profile Page
- Users should be able to see their own vehicles on their profile page
- Same Year / Make / Model format
## Security Requirements
- **Admin Only**: Vehicle-per-user viewing is restricted to admin accounts
- **Strict User Separation**: Normal users cannot see any other user's information
- Users can only view their own vehicle information on their profile
## UI/UX Specifications
| Component | Style |
|-----------|-------|
| Total Vehicles Widget | Match Total Users widget exactly (card, typography, spacing) |
| Vehicle Count Icon | Vehicle/car icon (differentiate from user icon) |
| Accordion Row | Inline expansion below user row |
| Vehicle List | Simple table: Year | Make | Model |
## Acceptance Criteria
- [ ] Total Vehicles widget displays correct system-wide count
- [ ] Widget positioned to right of Total Users widget
- [ ] Widget styling matches Total Users exactly
- [ ] Admin can expand user row to see their vehicles
- [ ] Vehicle list shows only Year/Make/Model
- [ ] Non-admin users cannot access other users' vehicle data
- [ ] Users can see their own vehicles on profile page
- [ ] Mobile responsive (both widgets and accordion)
- [ ] Desktop responsive
This plan implements three features for issue #11: (1) Total Vehicles widget on admin dashboard, (2) expandable user rows showing vehicle details in admin user management, and (3) My Vehicles section on user profile page. The approach uses separate API endpoints for stats and vehicle details, enabling cacheable stats queries and lazy-loading of vehicle data on row expansion.
Planning Context
Decision Log
Decision
Reasoning Chain
Separate stats + vehicles endpoints
Dashboard needs total count for widget -> embedding in user list would require client-side aggregation -> separate /api/admin/stats endpoint is cacheable and single-purpose
Lazy-load vehicles on row expansion
Users may not expand most rows -> fetching all vehicles upfront wastes bandwidth -> on-demand fetch via /api/admin/users/:id/vehicles reduces payload
Year/Make/Model only for admin view
Issue specifies privacy consideration -> VIN/license plate are sensitive -> minimal data exposure follows principle of least privilege
MUI Collapse for row expansion
AdminUsersPage uses MUI Table -> Collapse integrates natively with TableRow -> maintains consistent UI patterns
Reuse existing vehicles API for profile
User profile shows own vehicles -> /api/vehicles is already user-scoped via JWT -> no new endpoint needed for profile feature
M1 and M2 can execute in parallel (both backend).
M3 requires M1 and M2 (frontend needs backend APIs).
M4 can start immediately (uses existing API).
M5 requires M3 and M4 patterns established.
M6 follows all implementation.
Verdict: AWAITING_REVIEW | Next: Quality review of plan
## Plan: Admin User Management - Vehicle Display Features
**Phase**: Planning | **Agent**: Planner | **Status**: AWAITING_REVIEW
## Overview
This plan implements three features for issue #11: (1) Total Vehicles widget on admin dashboard, (2) expandable user rows showing vehicle details in admin user management, and (3) My Vehicles section on user profile page. The approach uses separate API endpoints for stats and vehicle details, enabling cacheable stats queries and lazy-loading of vehicle data on row expansion.
## Planning Context
### Decision Log
| Decision | Reasoning Chain |
|----------|-----------------|
| Separate stats + vehicles endpoints | Dashboard needs total count for widget -> embedding in user list would require client-side aggregation -> separate /api/admin/stats endpoint is cacheable and single-purpose |
| Lazy-load vehicles on row expansion | Users may not expand most rows -> fetching all vehicles upfront wastes bandwidth -> on-demand fetch via /api/admin/users/:id/vehicles reduces payload |
| Year/Make/Model only for admin view | Issue specifies privacy consideration -> VIN/license plate are sensitive -> minimal data exposure follows principle of least privilege |
| MUI Collapse for row expansion | AdminUsersPage uses MUI Table -> Collapse integrates natively with TableRow -> maintains consistent UI patterns |
| Reuse existing vehicles API for profile | User profile shows own vehicles -> /api/vehicles is already user-scoped via JWT -> no new endpoint needed for profile feature |
| React Query hooks for data fetching | Admin feature uses useUsers pattern (React Query) -> consistent data fetching patterns -> automatic cache invalidation |
| requireAdmin guard on all new endpoints | Existing admin routes use this guard -> protects admin-only data -> consistent authorization pattern |
### Rejected Alternatives
| Alternative | Why Rejected |
|-------------|--------------|
| Include VIN/license plate in admin view | Issue #11 explicitly requires Year/Make/Model only for privacy; additional data exposure unnecessary |
| Embed vehicles array in user list response | Performance impact with many users; would require loading all vehicles for all users on page load |
| Calculate total from sum of vehicleCounts | Client-side calculation inaccurate during pagination; server-side count is authoritative |
| Single combined stats+vehicles endpoint | Violates single responsibility; stats are cacheable while vehicle lists are user-specific |
### Constraints & Assumptions
- **Technical**: TypeScript 5.x, React 18.x, MUI 5.x, PostgreSQL 16.x, Jest for testing
- **Pattern**: Feature capsule structure in backend/src/features/
- **Convention**: snake_case DB columns -> camelCase API via mapRow()
- **Requirement**: Mobile + Desktop responsive (320px, 768px, 1920px viewports)
- **Testing**: Integration tests preferred per default-conventions domain='testing'
### Known Risks
| Risk | Mitigation | Anchor |
|------|------------|--------|
| Stats query performance with large vehicle count | Single COUNT(*) query with index on is_active; no joins needed | N/A (new code) |
| Admin accessing deactivated user's vehicles | Use existing is_active filter in vehicle query | vehicles.repository.ts:47 `WHERE user_id = $1 AND is_active = true` |
## Invisible Knowledge
### Architecture
```
Admin Dashboard Flow:
Browser
|
+--> GET /api/admin/stats --> {totalVehicles, totalUsers}
|
+--> GET /api/admin/users --> [{user, vehicleCount}]
|
+--> [click row] --> GET /api/admin/users/:id/vehicles
--> [{year, make, model}]
User Profile Flow:
Browser --> GET /api/vehicles --> [{user's own vehicles}]
```
### Data Flow
```
Stats Endpoint:
Request --> requireAdmin guard --> Query vehicles table (COUNT)
--> Query user_profiles table (COUNT) --> Response
User Vehicles Endpoint:
Request --> requireAdmin guard --> Query vehicles table (WHERE user_id)
--> Map to {year, make, model} --> Response
```
### Invariants
- Admin endpoints always require valid admin JWT (requireAdmin guard)
- Vehicle data for other users is admin-only; users can only see own vehicles
- Vehicle display format is Year/Make/Model for all contexts (privacy)
## Milestones
### Milestone 1: Backend - Admin Stats Endpoint
**Files**:
- `backend/src/features/user-profile/data/user-profile.repository.ts`
- `backend/src/features/admin/api/users.controller.ts`
- `backend/src/features/admin/api/admin.routes.ts`
**Requirements**:
- Add `getTotalVehicleCount()` method to user-profile.repository.ts
- Add `getAdminStats()` handler to users.controller.ts
- Register GET /api/admin/stats route with requireAdmin guard
- Return `{totalVehicles: number, totalUsers: number}`
**Acceptance Criteria**:
- GET /api/admin/stats returns correct totalVehicles count
- GET /api/admin/stats returns correct totalUsers count
- Endpoint requires admin authentication (401 without valid admin JWT)
- Response time < 100ms for typical dataset
**Tests**:
- **Test files**: `backend/src/features/admin/tests/integration/admin-stats.integration.test.ts`
- **Test type**: integration
- **Backing**: default-derived
- **Scenarios**:
- Normal: Returns correct counts with populated data
- Edge: Returns zero counts with empty database
- Error: Returns 401 for non-admin user
---
### Milestone 2: Backend - User Vehicles Endpoint
**Files**:
- `backend/src/features/user-profile/data/user-profile.repository.ts`
- `backend/src/features/admin/api/users.controller.ts`
- `backend/src/features/admin/api/admin.routes.ts`
- `backend/src/features/admin/types/admin.types.ts`
**Requirements**:
- Add `getUserVehiclesForAdmin(auth0Sub)` method returning `[{year, make, model}]`
- Add `getUserVehicles()` handler to users.controller.ts
- Register GET /api/admin/users/:auth0Sub/vehicles route
- Filter to active vehicles only (is_active = true)
**Acceptance Criteria**:
- GET /api/admin/users/:auth0Sub/vehicles returns vehicle list
- Response contains only year, make, model fields (no VIN, license plate)
- Returns empty array for users with no vehicles
- Endpoint requires admin authentication
**Tests**:
- **Test files**: `backend/src/features/admin/tests/integration/admin-user-vehicles.integration.test.ts`
- **Test type**: integration
- **Backing**: default-derived
- **Scenarios**:
- Normal: Returns vehicles for user with vehicles
- Edge: Returns empty array for user with no vehicles
- Edge: Returns empty array for non-existent user
- Error: Returns 401 for non-admin user
---
### Milestone 3: Frontend Desktop - Admin Dashboard Updates
**Files**:
- `frontend/src/features/admin/api/admin.api.ts`
- `frontend/src/features/admin/hooks/useUsers.ts`
- `frontend/src/features/admin/types/admin.types.ts`
- `frontend/src/pages/admin/AdminUsersPage.tsx`
**Requirements**:
- Add `getAdminStats()` and `getUserVehicles(auth0Sub)` to admin.api.ts
- Add `useAdminStats()` and `useUserVehicles(auth0Sub)` hooks
- Update AdminSectionHeader stats array to include Total Vehicles
- Add MUI Collapse component for expandable vehicle rows
- Display vehicles as Year / Make / Model table within collapsed section
**Acceptance Criteria**:
- Total Vehicles widget displays correct count next to Total Users
- Widget styling matches Total Users widget exactly
- Clicking user row expands to show vehicle list
- Vehicle list shows Year | Make | Model columns
- Collapse animation is smooth
- Works on desktop viewport (1920px)
**Tests**:
- **Test files**: `frontend/src/features/admin/__tests__/AdminUsersPage.test.tsx`
- **Test type**: integration (React Testing Library)
- **Backing**: default-derived
- **Scenarios**:
- Normal: Stats display correctly
- Normal: Row expansion shows vehicles
- Edge: Empty vehicle list displays appropriate message
---
### Milestone 4: Frontend Desktop - Profile Vehicles Section
**Files**:
- `frontend/src/pages/SettingsPage.tsx`
**Requirements**:
- Add My Vehicles Card section after Profile section
- Use existing `useVehicles()` hook from vehicles feature
- Display vehicles as Year / Make / Model list
- Link to garage for vehicle management
**Acceptance Criteria**:
- My Vehicles section appears on Settings page
- Displays user's vehicles in Year / Make / Model format
- Shows count of vehicles in section header
- Handles empty state (no vehicles message)
- Works on desktop viewport
**Tests**:
- **Test files**: `frontend/src/pages/__tests__/SettingsPage.test.tsx`
- **Test type**: integration (React Testing Library)
- **Backing**: default-derived
- **Scenarios**:
- Normal: Vehicles displayed correctly
- Edge: Empty state with no vehicles
---
### Milestone 5: Frontend Mobile - Admin + Profile Updates
**Files**:
- `frontend/src/features/admin/mobile/AdminUsersMobileScreen.tsx`
- `frontend/src/features/settings/mobile/MobileSettingsScreen.tsx`
**Requirements**:
- Add Total Vehicles stat to AdminUsersMobileScreen header
- Add accordion expansion for user vehicles in mobile list
- Add My Vehicles section to MobileSettingsScreen
- Ensure touch targets >= 44px
- Test on 320px and 768px viewports
**Acceptance Criteria**:
- Total Vehicles widget visible in mobile admin view
- User cards expand to show vehicles on tap
- My Vehicles section works on mobile Settings
- All touch targets meet 44px minimum
- No horizontal scrolling required
**Tests**:
- **Test files**: `frontend/src/features/admin/mobile/__tests__/AdminUsersMobileScreen.test.tsx`
- **Test type**: integration (React Testing Library)
- **Backing**: default-derived
- **Scenarios**:
- Normal: Stats and accordion work on mobile
- Normal: Profile vehicles display on mobile
---
### Milestone 6: Documentation
**Files**:
- `backend/src/features/admin/README.md`
**Requirements**:
- Document new admin stats and user vehicles endpoints
- Update API endpoint list with new routes
- Note privacy consideration for Year/Make/Model only
**Acceptance Criteria**:
- README documents both new endpoints
- Request/response formats are specified
- Admin-only access requirement is noted
## Milestone Dependencies
```
M1 ----+
|
M2 ----+--> M3 --> M5
|
+--> M4 --> M5
|
+--> M6
```
M1 and M2 can execute in parallel (both backend).
M3 requires M1 and M2 (frontend needs backend APIs).
M4 can start immediately (uses existing API).
M5 requires M3 and M4 patterns established.
M6 follows all implementation.
---
*Verdict*: AWAITING_REVIEW | *Next*: Quality review of plan
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Enhance the admin user management interface to display vehicle information associated with each user, and add a system-wide total vehicles widget to the admin dashboard.
Requirements
1. Total Vehicles Widget (Admin Dashboard)
2. User Vehicle List (Admin User Management)
3. User Profile Page
Security Requirements
UI/UX Specifications
Acceptance Criteria
Plan: Admin User Management - Vehicle Display Features
Phase: Planning | Agent: Planner | Status: AWAITING_REVIEW
Overview
This plan implements three features for issue #11: (1) Total Vehicles widget on admin dashboard, (2) expandable user rows showing vehicle details in admin user management, and (3) My Vehicles section on user profile page. The approach uses separate API endpoints for stats and vehicle details, enabling cacheable stats queries and lazy-loading of vehicle data on row expansion.
Planning Context
Decision Log
Rejected Alternatives
Constraints & Assumptions
Known Risks
WHERE user_id = $1 AND is_active = trueInvisible Knowledge
Architecture
Data Flow
Invariants
Milestones
Milestone 1: Backend - Admin Stats Endpoint
Files:
backend/src/features/user-profile/data/user-profile.repository.tsbackend/src/features/admin/api/users.controller.tsbackend/src/features/admin/api/admin.routes.tsRequirements:
getTotalVehicleCount()method to user-profile.repository.tsgetAdminStats()handler to users.controller.ts{totalVehicles: number, totalUsers: number}Acceptance Criteria:
Tests:
backend/src/features/admin/tests/integration/admin-stats.integration.test.tsMilestone 2: Backend - User Vehicles Endpoint
Files:
backend/src/features/user-profile/data/user-profile.repository.tsbackend/src/features/admin/api/users.controller.tsbackend/src/features/admin/api/admin.routes.tsbackend/src/features/admin/types/admin.types.tsRequirements:
getUserVehiclesForAdmin(auth0Sub)method returning[{year, make, model}]getUserVehicles()handler to users.controller.tsAcceptance Criteria:
Tests:
backend/src/features/admin/tests/integration/admin-user-vehicles.integration.test.tsMilestone 3: Frontend Desktop - Admin Dashboard Updates
Files:
frontend/src/features/admin/api/admin.api.tsfrontend/src/features/admin/hooks/useUsers.tsfrontend/src/features/admin/types/admin.types.tsfrontend/src/pages/admin/AdminUsersPage.tsxRequirements:
getAdminStats()andgetUserVehicles(auth0Sub)to admin.api.tsuseAdminStats()anduseUserVehicles(auth0Sub)hooksAcceptance Criteria:
Tests:
frontend/src/features/admin/__tests__/AdminUsersPage.test.tsxMilestone 4: Frontend Desktop - Profile Vehicles Section
Files:
frontend/src/pages/SettingsPage.tsxRequirements:
useVehicles()hook from vehicles featureAcceptance Criteria:
Tests:
frontend/src/pages/__tests__/SettingsPage.test.tsxMilestone 5: Frontend Mobile - Admin + Profile Updates
Files:
frontend/src/features/admin/mobile/AdminUsersMobileScreen.tsxfrontend/src/features/settings/mobile/MobileSettingsScreen.tsxRequirements:
Acceptance Criteria:
Tests:
frontend/src/features/admin/mobile/__tests__/AdminUsersMobileScreen.test.tsxMilestone 6: Documentation
Files:
backend/src/features/admin/README.mdRequirements:
Acceptance Criteria:
Milestone Dependencies
M1 and M2 can execute in parallel (both backend).
M3 requires M1 and M2 (frontend needs backend APIs).
M4 can start immediately (uses existing API).
M5 requires M3 and M4 patterns established.
M6 follows all implementation.
Verdict: AWAITING_REVIEW | Next: Quality review of plan