This commit is contained in:
2026-07-16 09:53:14 +07:00
parent 0fc112a2e8
commit 29cec708a3
1236 changed files with 212848 additions and 0 deletions

View File

@@ -0,0 +1,196 @@
# 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.