diff --git a/src/app/admin/_components/FormField.tsx b/src/app/admin/_components/FormField.tsx index 9457f3e..6f5534e 100644 --- a/src/app/admin/_components/FormField.tsx +++ b/src/app/admin/_components/FormField.tsx @@ -585,7 +585,7 @@ export function TimeRangeField({ label, value, onChange, onBlur }: TimeRangeFiel } function handleEndChange(newEnd: string) { - if (start && newEnd && newEnd <= start) return; + // Always allow the change — validation handles the error display update(start, newEnd); } diff --git a/src/app/admin/_components/SectionEditor.tsx b/src/app/admin/_components/SectionEditor.tsx index d590c08..30632ff 100644 --- a/src/app/admin/_components/SectionEditor.tsx +++ b/src/app/admin/_components/SectionEditor.tsx @@ -28,6 +28,7 @@ export function SectionEditor({ const [error, setError] = useState(""); const timerRef = useRef | null>(null); const initialLoadRef = useRef(true); + const pendingSaveRef = useRef(false); useEffect(() => { adminFetch(`/api/admin/sections/${sectionKey}`) @@ -68,6 +69,7 @@ export function SectionEditor({ return; } + pendingSaveRef.current = true; if (timerRef.current) clearTimeout(timerRef.current); timerRef.current = setTimeout(() => { if (validate && !validate(data)) return; @@ -79,6 +81,41 @@ export function SectionEditor({ }; }, [data, save]); + // Clear pending flag after save completes + useEffect(() => { + if (status === "saved") pendingSaveRef.current = false; + }, [status]); + + // Warn before leaving with unsaved changes + useEffect(() => { + function onBeforeUnload(e: BeforeUnloadEvent) { + if (pendingSaveRef.current) e.preventDefault(); + } + function onLinkClick(e: MouseEvent) { + if (!pendingSaveRef.current) return; + const link = (e.target as HTMLElement).closest("a"); + if (!link || link.target === "_blank") return; + const href = link.getAttribute("href"); + if (!href || href.startsWith("#")) return; + // Force save immediately before navigating + if (timerRef.current) clearTimeout(timerRef.current); + if (data && (!validate || validate(data))) { + e.preventDefault(); + e.stopPropagation(); + save(data).then(() => { + pendingSaveRef.current = false; + window.location.href = href; + }); + } + } + window.addEventListener("beforeunload", onBeforeUnload); + document.addEventListener("click", onLinkClick, true); + return () => { + window.removeEventListener("beforeunload", onBeforeUnload); + document.removeEventListener("click", onLinkClick, true); + }; + }, [data, save, validate]); + if (loading) { return (
diff --git a/src/app/admin/contact/page.tsx b/src/app/admin/contact/page.tsx index d843399..5efe77d 100644 --- a/src/app/admin/contact/page.tsx +++ b/src/app/admin/contact/page.tsx @@ -230,12 +230,6 @@ export default function ContactEditorPage() { />
- update({ ...data, workingHours: v })} - /> - -
- -