Files
alla-tms/plans/action-auto-refresh-implementation-report.md
2026-07-16 09:53:14 +07:00

10 KiB

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.

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.