From 57d1e9247be51aef9da010a69edd06b70505559d Mon Sep 17 00:00:00 2001 From: jan Date: Thu, 7 May 2026 11:55:35 +0200 Subject: [PATCH] Dashboard Auto Refresh ergaenzen --- src/components/dashboard/dashboard-shell.tsx | 48 ++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/components/dashboard/dashboard-shell.tsx b/src/components/dashboard/dashboard-shell.tsx index aca0b84..fed8e84 100644 --- a/src/components/dashboard/dashboard-shell.tsx +++ b/src/components/dashboard/dashboard-shell.tsx @@ -280,6 +280,16 @@ function urlBase64ToUint8Array(value: string) { return Uint8Array.from([...rawData], (character) => character.charCodeAt(0)); } +function hasFocusedEditableElement() { + const activeElement = document.activeElement; + + if (!activeElement || activeElement === document.body) { + return false; + } + + return Boolean(activeElement.closest('input, textarea, select, [contenteditable="true"]')); +} + export function DashboardShell({ viewer, workingGroups, @@ -393,11 +403,49 @@ export function DashboardShell({ const [periodEditForm, setPeriodEditForm] = useState(getPeriodEditDraft(currentPeriod)); const [pushStatus, setPushStatus] = useState<"idle" | "enabled" | "blocked" | "unsupported">("idle"); const handledDeepLinkRef = useRef(null); + const busyRef = useRef(busy); useEffect(() => { setSelectedCurrentPeriodId(currentPeriodId); setPeriodForm(getSuggestedPeriodDraft(currentPeriod)); }, [currentPeriod, currentPeriodId]); + useEffect(() => { + busyRef.current = busy; + }, [busy]); + + useEffect(() => { + function refreshIfSafe() { + if (document.visibilityState !== "visible" || busyRef.current || hasFocusedEditableElement()) { + return; + } + + router.refresh(); + } + + function handleVisibilityChange() { + if (document.visibilityState === "visible") { + refreshIfSafe(); + } + } + + function handlePageShow() { + refreshIfSafe(); + } + + document.addEventListener("visibilitychange", handleVisibilityChange); + window.addEventListener("focus", refreshIfSafe); + window.addEventListener("pageshow", handlePageShow); + + const intervalId = window.setInterval(refreshIfSafe, 45_000); + + return () => { + window.clearInterval(intervalId); + document.removeEventListener("visibilitychange", handleVisibilityChange); + window.removeEventListener("focus", refreshIfSafe); + window.removeEventListener("pageshow", handlePageShow); + }; + }, [router]); + useEffect(() => { const selectedPeriod = accountingPeriods.find((period) => period.id === selectedCurrentPeriodId) ?? currentPeriod ?? null; setPeriodEditForm(getPeriodEditDraft(selectedPeriod));