diff --git a/src/app/(admin)/admin/rounds/[roundId]/page.tsx b/src/app/(admin)/admin/rounds/[roundId]/page.tsx index 48c79f7..c7e3618 100644 --- a/src/app/(admin)/admin/rounds/[roundId]/page.tsx +++ b/src/app/(admin)/admin/rounds/[roundId]/page.tsx @@ -237,16 +237,24 @@ export default function RoundDetailPage() { { enabled: round?.roundType === 'FILTERING', refetchInterval: 5_000 }, ) - // Initialize config from server once on load (or when round changes externally) + // Initialize config from server on load; re-sync after saves const serverConfig = useMemo(() => (round?.configJson as Record) ?? {}, [round?.configJson]) const configInitialized = useRef(false) - if (round && !configInitialized.current) { - const roundConfig = (round.configJson as Record) ?? {} - if (Object.keys(config).length === 0 || JSON.stringify(roundConfig) !== JSON.stringify(config)) { - setConfig(roundConfig) + const savingRef = useRef(false) + + // Sync local config with server: on initial load AND whenever serverConfig + // changes after a save completes (so Zod-applied defaults get picked up) + useEffect(() => { + if (!round) return + if (!configInitialized.current) { + configInitialized.current = true + setConfig(serverConfig) + } else if (!savingRef.current) { + // Server changed (e.g. after save invalidation) — re-sync + setConfig(serverConfig) } - configInitialized.current = true - } + }, [serverConfig, round]) + const hasUnsavedConfig = useMemo( () => configInitialized.current && JSON.stringify(config) !== JSON.stringify(serverConfig), [config, serverConfig], @@ -255,11 +263,13 @@ export default function RoundDetailPage() { // ── Mutations ────────────────────────────────────────────────────────── const updateMutation = trpc.round.update.useMutation({ onSuccess: () => { + savingRef.current = false utils.round.getById.invalidate({ id: roundId }) setAutosaveStatus('saved') setTimeout(() => setAutosaveStatus('idle'), 2000) }, onError: (err) => { + savingRef.current = false setAutosaveStatus('error') toast.error(err.message) }, @@ -393,23 +403,27 @@ export default function RoundDetailPage() { }, []) const saveConfig = useCallback(() => { + savingRef.current = true setAutosaveStatus('saving') updateMutation.mutate({ id: roundId, configJson: config }) }, [config, roundId, updateMutation]) // ── Auto-save: debounce config changes and save automatically ──────── + const configJson = JSON.stringify(config) + const serverJson = JSON.stringify(serverConfig) useEffect(() => { if (!configInitialized.current) return - if (JSON.stringify(config) === JSON.stringify(serverConfig)) return + if (configJson === serverJson) return const timer = setTimeout(() => { + savingRef.current = true setAutosaveStatus('saving') updateMutation.mutate({ id: roundId, configJson: config }) }, 800) return () => clearTimeout(timer) // eslint-disable-next-line react-hooks/exhaustive-deps - }, [config]) + }, [configJson]) // ── Computed values ──────────────────────────────────────────────────── const projectCount = round?._count?.projectRoundStates ?? 0