Align backend plan with codebase
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
fetchAuthSession,
|
||||
fetchDraftFromServer,
|
||||
saveDraftToServer,
|
||||
} from "../../../lib/create/api";
|
||||
import { useCreateFlow } from "./CreateFlowContext";
|
||||
|
||||
const SYNC_ENABLED =
|
||||
process.env.NEXT_PUBLIC_ENABLE_BACKEND_SYNC === "true";
|
||||
|
||||
const DEBOUNCE_MS = 1000;
|
||||
|
||||
/**
|
||||
* When NEXT_PUBLIC_ENABLE_BACKEND_SYNC=true, loads the signed-in user's draft
|
||||
* from the server and debounces saves. Anonymous users keep localStorage-only behavior.
|
||||
*/
|
||||
export function CreateFlowBackendSync() {
|
||||
const { state, replaceState } = useCreateFlow();
|
||||
const [hydrated, setHydrated] = useState(!SYNC_ENABLED);
|
||||
const saveTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!SYNC_ENABLED) return;
|
||||
|
||||
let cancelled = false;
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
const { user } = await fetchAuthSession();
|
||||
if (cancelled || !user) {
|
||||
setHydrated(true);
|
||||
return;
|
||||
}
|
||||
const serverDraft = await fetchDraftFromServer();
|
||||
if (cancelled) return;
|
||||
if (serverDraft && Object.keys(serverDraft).length > 0) {
|
||||
replaceState(serverDraft);
|
||||
}
|
||||
} finally {
|
||||
if (!cancelled) setHydrated(true);
|
||||
}
|
||||
})();
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [replaceState]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!SYNC_ENABLED || !hydrated) return;
|
||||
|
||||
if (saveTimer.current) clearTimeout(saveTimer.current);
|
||||
|
||||
saveTimer.current = setTimeout(() => {
|
||||
saveTimer.current = null;
|
||||
void (async () => {
|
||||
const { user } = await fetchAuthSession();
|
||||
if (!user) return;
|
||||
await saveDraftToServer(state);
|
||||
})();
|
||||
}, DEBOUNCE_MS);
|
||||
|
||||
return () => {
|
||||
if (saveTimer.current) clearTimeout(saveTimer.current);
|
||||
};
|
||||
}, [state, hydrated]);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -79,6 +79,11 @@ export function CreateFlowProvider({
|
||||
}));
|
||||
}, []);
|
||||
|
||||
const replaceState = useCallback((next: CreateFlowState) => {
|
||||
setState(next);
|
||||
writeStateToStorage(STORAGE_KEY, next);
|
||||
}, []);
|
||||
|
||||
const clearState = useCallback(() => {
|
||||
setState({});
|
||||
removeFromStorage(STORAGE_KEY);
|
||||
@@ -89,6 +94,7 @@ export function CreateFlowProvider({
|
||||
state,
|
||||
currentStep,
|
||||
updateState,
|
||||
replaceState,
|
||||
clearState,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user