fix(dashboard): stale punch button/KPIs after attendance changes on other pages
Verified flow: clock in on dashboard -> delete the record in /attendance/admin -> navigate back: 'Zaznamenat odchod', the Pritomni KPI and the presence card still showed the pre-delete state until F5. Root cause: every attendance mutation outside the dashboard invalidated only ["attendance"], never ["dashboard"], so within the dashboard query's 60s staleTime the remount was served from cache. - useAttendanceAdmin create/bulk/edit/delete, /attendance punch + leave-request, AttendanceCreate, LeaveApproval approve/reject now also invalidate ["dashboard"] (CLAUDE.md rule: mutations invalidate every domain that embeds their data) - systemic backstop: dashboardOptions uses refetchOnMount "always" - the dashboard aggregates attendance/offers/invoices/orders/projects/leave, and domain pages can't all be expected to invalidate it; returning to the dashboard must never show pre-mutation data Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1048,6 +1048,10 @@ export default function useAttendanceAdmin({ alert }: AlertContext) {
|
||||
if (result.success) {
|
||||
setShowCreateModal(false);
|
||||
queryClient.invalidateQueries({ queryKey: ["attendance"] });
|
||||
// The dashboard embeds attendance (Přítomní dnes / Docházka dnes /
|
||||
// punch-button state) — without this it serves a stale cache for up
|
||||
// to its staleTime after records change here.
|
||||
queryClient.invalidateQueries({ queryKey: ["dashboard"] });
|
||||
await fetchData(false);
|
||||
await new Promise((resolve) => setTimeout(resolve, 300));
|
||||
alert.success(
|
||||
@@ -1120,6 +1124,10 @@ export default function useAttendanceAdmin({ alert }: AlertContext) {
|
||||
if (result.success) {
|
||||
setShowBulkModal(false);
|
||||
queryClient.invalidateQueries({ queryKey: ["attendance"] });
|
||||
// The dashboard embeds attendance (Přítomní dnes / Docházka dnes /
|
||||
// punch-button state) — without this it serves a stale cache for up
|
||||
// to its staleTime after records change here.
|
||||
queryClient.invalidateQueries({ queryKey: ["dashboard"] });
|
||||
await fetchData(false);
|
||||
await new Promise((resolve) => setTimeout(resolve, 300));
|
||||
alert.success(
|
||||
@@ -1255,6 +1263,10 @@ export default function useAttendanceAdmin({ alert }: AlertContext) {
|
||||
if (result.success) {
|
||||
setShowEditModal(false);
|
||||
queryClient.invalidateQueries({ queryKey: ["attendance"] });
|
||||
// The dashboard embeds attendance (Přítomní dnes / Docházka dnes /
|
||||
// punch-button state) — without this it serves a stale cache for up
|
||||
// to its staleTime after records change here.
|
||||
queryClient.invalidateQueries({ queryKey: ["dashboard"] });
|
||||
await fetchData(false);
|
||||
await new Promise((resolve) => setTimeout(resolve, 300));
|
||||
alert.success(
|
||||
@@ -1285,6 +1297,10 @@ export default function useAttendanceAdmin({ alert }: AlertContext) {
|
||||
if (result.success) {
|
||||
setDeleteConfirm({ show: false, record: null });
|
||||
queryClient.invalidateQueries({ queryKey: ["attendance"] });
|
||||
// The dashboard embeds attendance (Přítomní dnes / Docházka dnes /
|
||||
// punch-button state) — without this it serves a stale cache for up
|
||||
// to its staleTime after records change here.
|
||||
queryClient.invalidateQueries({ queryKey: ["dashboard"] });
|
||||
await fetchData(false);
|
||||
alert.success(
|
||||
result.message || result.data?.message || "Záznam smazán",
|
||||
|
||||
Reference in New Issue
Block a user