# Auto Refresh Implementation Report ## 1. Executive Summary Implemented a shared TanStack Query invalidation layer for CRUD and workflow mutations that affect multiple dashboard modules. The change keeps existing URL search params, filters, sorting, pagination, dialogs, and route-handler architecture intact while making related client-side caches stale after successful actions. ## 2. Modules Audited - Users - Employees - Employee Directory - Courses - Training Records - Training Record Reviews - Training Record Certificates - Training Matrix - Online Lessons - Announcements - Training Policies - Permission Management - Employee Import and Master Review - Organizers - Notifications - Products legacy feature ## 3. Problems Found - Several mutations invalidated only their own feature list even when the action changed data used by other pages. - Certificate upload/delete refreshed the certificate list but not the training record detail/list cache that can show certificate preview data. - Course mutations refreshed Course Master but not course option consumers used by training records and matrix screens. - People mutations refreshed users or employees separately, but related directory, permission, and training-record option caches could remain stale. - Content workflow actions could create notifications while only refreshing the content module. ## 4. Root Causes - Cache invalidation lived inside each feature mutation file with no shared dependency map. - Query keys were consistent, but related keys were not grouped by domain. - The app uses server-prefetch plus hydrated TanStack Query; after a client mutation, stale hydrated data needs explicit query invalidation. ## 5. Files Changed - `src/lib/query-invalidation.ts` - Added shared invalidation helpers grouped by domain: people, courses, training records, training matrix, content workflow, permissions, organizers, imports, and policies. - Reason: centralizes related cache dependencies without introducing a new library or changing page architecture. - Impact: mutations can refresh all affected query groups consistently. - Test: lint and TypeScript compile. - `src/features/users/api/mutations.ts` - Switched create/update/delete to `invalidatePeopleData()`. - Reason: user changes affect users, employee-facing selectors, directory consumers, and permission assignment screens. - Impact: user-related pages update after CRUD. - Test: lint and TypeScript compile. - `src/features/employees/api/mutations.ts` - Switched create/update/delete to `invalidatePeopleData()`. - Reason: employee changes affect Employee Directory and training-record participant options. - Impact: employee data consumers refresh after employee CRUD. - Test: lint and TypeScript compile. - `src/features/courses/api/mutations.ts` - Switched create/update/delete to `invalidateCourseData()`. - Reason: course changes affect Course Master, training-record course options, and matrix option/compliance consumers. - Impact: course selectors and matrix-dependent data are refreshed after course CRUD. - Test: lint and TypeScript compile. - `src/features/training-records/api/mutations.ts` - Switched create/update/delete/import to `invalidateTrainingRecordData()`. - Reason: training records affect record lists, employee directory summaries, and training matrix compliance. - Impact: list and related summaries refresh after record actions. - Test: lint and TypeScript compile. - `src/features/training-records/api/review-mutations.ts` - Added related training record invalidation plus detail invalidation for the reviewed record. - Reason: review actions affect pending/approved lists and the detail page. - Impact: pending review and training record views refresh after review actions. - Test: lint and TypeScript compile. - `src/features/training-records/api/certificate-mutations.ts` - Added record list/detail invalidation alongside certificate list invalidation. - Reason: certificate changes can affect preview data shown on record views. - Impact: attachment and record UI update together. - Test: lint and TypeScript compile. - `src/features/training-matrix/api/mutations.ts` - Switched create/update/delete to `invalidateTrainingMatrixData()`. - Reason: matrix target changes affect matrix pages, employee target summaries, and training-record compliance consumers. - Impact: matrix-related screens update after matrix CRUD. - Test: lint and TypeScript compile. - `src/features/employee-directory/api/mutations.ts` - Added matrix/record related invalidation after target upsert while keeping target detail invalidation. - Reason: employee target edits affect matrix compliance and employee-directory views. - Impact: target detail and related summaries refresh after save. - Test: lint and TypeScript compile. - `src/features/online-lessons/api/mutations.ts` - Added content workflow invalidation for lesson CRUD/workflow actions. - Reason: lesson submit/publish/delete can affect lesson lists/details and notifications. - Impact: content and notification data refresh after lesson actions. - Test: lint and TypeScript compile. - `src/features/announcements/api/mutations.ts` - Added content workflow invalidation for announcement CRUD, workflow, pin, and unpin actions. - Reason: announcement actions can affect lists/details and notifications. - Impact: announcement and notification data refresh after content actions. - Test: lint and TypeScript compile. - `src/features/training-policy/api/mutations.ts` - Switched policy actions to `invalidateTrainingPolicyData()`. - Reason: policy changes may affect matrix-related policy views. - Impact: policy and related matrix data refresh after policy actions. - Test: lint and TypeScript compile. - `src/features/import-employees/api/mutations.ts` - Switched import/review actions to `invalidateEmployeeImportData()`. - Reason: imports and master review can change employees, directory data, and participant options. - Impact: employee-facing data refreshes after import and review actions. - Test: lint and TypeScript compile. - `src/features/organizers/api/mutations.ts` - Switched organizer CRUD to `invalidateOrganizerData()`. - Reason: organizer changes can affect user/employee organization context data. - Impact: organizer and related people data refresh after organizer actions. - Test: lint and TypeScript compile. - `src/features/permission-management/api/mutations.ts` - Switched template and user-permission mutations to `invalidatePermissionData()` plus user detail invalidation where needed. - Reason: permission mutations affect template/catalog/user/audit views and user lists. - Impact: permission screens update more consistently after save/clone/activate/deactivate/delete. - Test: lint and TypeScript compile. - `src/features/products/api/mutations.ts` - Added product detail invalidation after update. - Reason: legacy detail view can otherwise show stale data after update. - Impact: product detail cache refreshes after update. - Test: lint and TypeScript compile. ## 6. Refresh Strategy by Module - People data: invalidate users, employees, employee directory, training-record user options, and permission-management users. - Course data: invalidate courses, training-record course options, training matrix options, and training matrix lists. - Training record data: invalidate training records, employee directory, and training matrix compliance. - Training matrix data: invalidate matrix, employee directory, and training record data. - Content workflow data: invalidate announcements, online lessons, and notifications. - Permission data: invalidate permission-management root keys and users. - Import data: invalidate master review, employees, employee directory, and training-record user options. - Organizer data: invalidate organizers, users, employees, and employee directory. - Training policy data: invalidate training policies and training matrix. ## 7. Cache Keys Updated - `['users']` - `['employees']` - `['employee-directory']` - `['courses']` - `['training-records']` - `['training-records', 'course-options']` - `['training-records', 'user-options']` - `['training-matrix']` - `['announcements']` - `['online-lessons']` - `['notifications']` - `['permission-management']` - `['master-review']` - `['organizers']` - `['training-policies']` - `['products']` ## 8. Pagination Handling Existing pagination, search, filter, and sort state remains URL-driven through current table components and `nuqs`. The implementation invalidates query prefixes instead of rewriting search params, so existing table state is preserved. ## 9. Related Data Revalidation Related data is now grouped by domain in `src/lib/query-invalidation.ts`. Mutations call the relevant domain helper rather than refreshing only the immediate feature. ## 10. Full Page Reloads Removed No `window.location.reload()` usage was found in the audited app code. Existing `router.refresh()` calls remain only where the surrounding component/page still uses server component refresh behavior after a mutation. ## 11. Test Results - `npm run lint -- src/lib/query-invalidation.ts ...`: passed. - `npx tsc --noEmit --pretty false`: passed. ## 12. Remaining Risks - Some server-rendered dashboard summary/report widgets may use direct server data without a client query key; those still depend on navigation or `router.refresh()` unless migrated to TanStack Query. - The current working tree already had unrelated edits in `src/app/dashboard/courses/page.tsx` and `src/features/courses/components/course-tables/columns.tsx`; this implementation did not revert or normalize those changes. - Manual browser testing was not completed in this pass. ## 13. Recommendations - Add query keys for dashboard/report summary widgets if they need live client refresh after related mutations. - Keep future mutation files thin by using the shared domain invalidation helpers instead of adding one-off invalidate lists. - Add a small integration test for high-risk flows: training record review, certificate upload/delete, course create/update, and employee import review.