11 KiB
Implementation Plan: Admin Page Overhaul
Overview
Replace the current inline UserManagement modal rendering on the admin page with a full-page, themed AdminPage component. The new component lives at frontend/src/components/pages/AdminPage.js and provides three tabbed panels — User Management, Audit Log, and System Info — all styled with the dark tactical intelligence theme. No new backend endpoints are needed; the component reuses existing /api/users and /api/audit-logs routes. Existing modal components (UserManagement, AuditLog) are preserved for quick-access from UserMenu.
Tasks
-
1. Create AdminPage component with page header and tab navigation
-
1.1 Create
frontend/src/components/pages/AdminPage.jswith the page shell- Import React, useState, useAuth from AuthContext, and lucide-react icons (Shield, Clock, Activity)
- Define
API_BASEconstant matching project convention - Define
TABSarray:[{ id: 'users', label: 'User Management', icon: Shield }, { id: 'audit', label: 'Audit Log', icon: Clock }, { id: 'system', label: 'System Info', icon: Activity }] - Render page header with "Admin Panel" title in monospace uppercase with
--intel-accenttext glow - Render tab navigation bar with monospace uppercase text,
--intel-accentactive styling, and muted inactive styling matching the CompliancePage team-tab pattern - Manage
activeTabstate defaulting to'users' - Conditionally render placeholder
<div>for each panel based onactiveTab - Requirements: 1.1, 1.2, 1.3, 2.1, 2.2, 2.3, 2.4
-
1.2 Integrate AdminPage into App.js
- Import
AdminPagefrom./components/pages/AdminPage - Replace the existing
{currentPage === 'admin' && isAdmin() && (<div className="space-y-6"><UserManagement onClose={() => setCurrentPage('home')} /></div>)}block with{currentPage === 'admin' && isAdmin() && <AdminPage />} - Add non-admin redirect:
{currentPage === 'admin' && !isAdmin() && setCurrentPage('home')}(or useEffect equivalent) - Keep existing
{showUserManagement && <UserManagement onClose={...} />}and{showAuditLog && <AuditLog onClose={...} />}modal triggers unchanged - Requirements: 1.2, 6.1, 6.2, 6.3, 6.4
- Import
-
-
[-] 2. Implement UserManagementPanel
-
2.1 Build the themed user table and group badges
- Define
GROUP_BADGE_THEMEDmap with themed colors: Admin → danger, Standard_User → accent, Leadership → warning, Read_Only → muted - Fetch users from
GET /api/userswithcredentials: 'include'on panel mount - Render user table with columns: username, email, group, active status, last login
- Style table with dark theme rows using
data-rowhover effects and--text-primary/--text-secondarytext colors - Render group badges using the themed color map with severity-style badge coloring
- Display loading spinner (
loading-spinnerclass,--intel-accentcolor) while fetching - Display error banner with
--intel-dangerstyling on fetch failure - Requirements: 3.1, 3.2, 3.3, 7.1, 7.2
- Define
-
2.2 Implement inline add/edit form and CRUD operations
- Add "Add User" button styled with
intel-buttonprimary variant - Show inline form with
intel-inputstyled fields for username, email, password, and group dropdown - On edit action: populate form with selected user's data (username, email, group; password blank)
- On form submit: POST (create) or PATCH (update) to
/api/usersor/api/users/:id - On delete action: show confirmation prompt, then DELETE to
/api/users/:id - On active status toggle: PATCH to
/api/users/:idwithis_activetoggled, update UI without full reload - Prevent self-modification: disable group dropdown and active toggle for the current authenticated user's row
- Display form validation errors with
--intel-dangercolor - Display success toast with
--intel-successcolor, auto-dismiss after 2 seconds - Requirements: 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 7.3
- Add "Add User" button styled with
-
2.3 Write property test: Group badge color mapping is total and correct
- Property 1: Group badge color mapping is total and correct
- Install
fast-checkas a dev dependency infrontend/ - Create test file
frontend/src/components/pages/__tests__/AdminPage.property.test.js - Generate random strings including the four valid groups and arbitrary invalid strings
- Verify the badge function returns correct themed colors for valid groups and default muted styling for invalid groups
- Use
fc.assert(property, { numRuns: 100 }) - Validates: Requirements 3.3
-
2.4 Write property test: Edit form population preserves user data
- Property 2: Edit form population preserves user data
- Generate random user objects with arbitrary username, email, and group values
- Verify that populating the edit form results in
formData.username === user.username,formData.email === user.email,formData.group === user.group, andformData.password === '' - Use
fc.assert(property, { numRuns: 100 }) - Validates: Requirements 3.5
-
2.5 Write property test: Self-modification prevention
- Property 3: Self-modification prevention
- Generate random user lists that include a user matching the current admin's ID
- Verify the admin's own row has group dropdown disabled and active toggle disabled
- Verify all other users have those controls enabled
- Use
fc.assert(property, { numRuns: 100 }) - Validates: Requirements 3.8
-
-
3. Checkpoint — Verify user management panel
- Ensure all tests pass, ask the user if questions arise.
-
[-] 4. Implement AuditLogPanel
-
4.1 Build the themed audit log table with action badges and filters
- Define
ACTION_BADGE_THEMEDmap with themed colors: login/success → green, delete → danger, create → accent, update → warning, default → muted - Fetch audit logs from
GET /api/audit-logs?page=1&limit=25withcredentials: 'include'on panel mount - Fetch action types from
GET /api/audit-logs/actionsfor the action filter dropdown - Render log table with columns: timestamp, username, action, entity type, entity ID, details, IP address
- Style timestamps and IP addresses with monospace font
- Render action type badges using the themed color map
- Style table with dark theme rows and
data-rowhover effects - Display loading spinner while fetching, error banner on failure
- Display "No audit log entries found" message with
--text-mutedcolor when results are empty - Requirements: 4.1, 4.2, 4.3, 4.4, 4.9, 4.10, 7.1, 7.2
- Define
-
4.2 Implement filter controls and pagination
- Render filter bar with: username text input, action type dropdown, entity type dropdown, start date picker, end date picker
- Style all filter controls with
intel-inputandintel-buttoncomponents - On filter apply: re-fetch audit logs from page 1 with selected filter parameters
- Render pagination controls showing current page, total pages, and total entry count
- On page change: fetch the requested page
- Requirements: 4.5, 4.6, 4.7, 4.8
-
4.3 Write property test: Action badge color mapping is total and correct
- Property 4: Action badge color mapping is total and correct
- Generate random action strings including all known actions and arbitrary unknown strings
- Verify the badge function returns correct themed colors for known actions and default muted styling for unknown actions
- Use
fc.assert(property, { numRuns: 100 }) - Validates: Requirements 4.4
-
4.4 Write property test: Applying filters resets pagination to page 1
- Property 5: Applying filters resets pagination to page 1
- Generate random filter combinations (username text, action type, entity type, start date, end date) and random current page numbers
- Verify that applying filters results in a fetch call with
page=1 - Use
fc.assert(property, { numRuns: 100 }) - Validates: Requirements 4.7
-
-
[-] 5. Implement SystemInfoPanel
-
5.1 Build stat cards and recent activity list
- Fetch users from
GET /api/usersand recent audit logs fromGET /api/audit-logs?limit=10&page=1on panel mount - Compute derived stats: total users (
users.length), active users (users.filter(u => u.is_active)), recent logins (users withlast_loginwithin last 7 days), total audit entries (from pagination.total) - Render four stat cards using the
stat-cardpattern with accent-colored top bar and hover lift effect - Render "Recent Activity" section showing the 10 most recent audit log entries in a compact list format
- Show "Unable to load" fallback in affected stat cards when individual API requests fail
- Display loading spinner while fetching
- Requirements: 5.1, 5.2, 5.3, 5.4, 5.5, 7.1
- Fetch users from
-
5.2 Write property test: Recent login count computation
- Property 6: Recent login count computation
- Generate random user lists with random
last_logintimestamps (including null values) - Verify the computed "recent logins" count equals the number of users whose
last_loginis non-null and falls within the last 7 days - Use
fc.assert(property, { numRuns: 100 }) - Validates: Requirements 5.1
-
-
6. Checkpoint — Verify all panels and integration
- Ensure all tests pass, ask the user if questions arise.
-
[-] 7. Access control and final wiring
-
7.1 Verify access control integration
- Confirm
AdminPagereads auth context viauseAuth()and only renders content for Admin-group users - Confirm
App.jsredirects non-admin users to home whencurrentPage === 'admin' - Confirm
NavDrawercontinues to show "Admin Panel" only for Admin-group users (no changes needed — verify existing behavior) - Confirm
UserMenuquick-access links ("Manage Users", "Audit Log") continue to open existing modal components (no changes needed — verify existing behavior) - Requirements: 6.1, 6.2, 6.3, 6.4
- Confirm
-
7.2 Write property test: Admin-only access control
- Property 7: Admin-only access control
- Generate random user objects with random group values
- Verify admin page content renders if and only if
user.group === 'Admin' - Verify non-Admin groups trigger redirect to home
- Use
fc.assert(property, { numRuns: 100 }) - Validates: Requirements 6.1, 6.2
-
-
8. Final checkpoint — Ensure all tests pass
- Ensure all tests pass, ask the user if questions arise.
Notes
- Tasks marked with
*are optional and can be skipped for faster MVP - Each task references specific requirements for traceability
- Checkpoints ensure incremental validation
- Property tests validate universal correctness properties from the design document using fast-check
- Unit tests validate specific examples and edge cases
- Existing
UserManagement.jsandAuditLog.jsmodal components are not modified — they remain for UserMenu quick-access - All styling follows the project convention of inline styles + App.css classes (no Tailwind in the new component)
- The
fast-checklibrary must be installed as a dev dependency before running property tests