DocDoeAI / src /hooks /useSyncedStudentActivity.ts
asnannp's picture
deploy: sync backend to Space root (learn-lesson HF cache fix)
65d68f5
Raw History Blame Contribute Delete
2.13 kB
"use client";
import { useEffect, useMemo, useState } from "react";
import { useStudentActivityVersion } from "@/hooks/useStudentActivity";
import {
getSyncedProgress,
syncProgressEvents,
} from "@/lib/api/progress-sync";
import { learnerScopeId } from "@/lib/phase3-learning";
import {
listActivities,
mergeActivityEvents,
type ActivityEvent,
} from "@/lib/student-activity";
export type ActivitySyncState = "device" | "syncing" | "synced" | "error";
/**
* One account-aware activity ledger for Home and Progress. Offline events stay
* visible immediately, then upload idempotently and merge with activity from
* the student's other devices.
*/
export function useSyncedStudentActivity(limit = 50) {
const version = useStudentActivityVersion();
const scopeId = learnerScopeId();
const localEvents = useMemo(() => {
void version;
return listActivities(Math.min(limit, 100));
}, [limit, version]);
const [remoteEvents, setRemoteEvents] = useState<ActivityEvent[]>([]);
const [syncState, setSyncState] = useState<ActivitySyncState>(() =>
scopeId ? "syncing" : "device",
);
useEffect(() => {
let cancelled = false;
async function refresh() {
// Defer state changes so the effect never performs a synchronous state
// write during React's commit phase.
await Promise.resolve();
if (cancelled) return;
if (!scopeId) {
setRemoteEvents([]);
setSyncState("device");
return;
}
setSyncState("syncing");
try {
if (localEvents.length) await syncProgressEvents(localEvents);
const remote = await getSyncedProgress();
if (cancelled) return;
setRemoteEvents(remote.recent_events);
setSyncState("synced");
} catch {
if (!cancelled) setSyncState("error");
}
}
void refresh();
return () => {
cancelled = true;
};
}, [localEvents, scopeId]);
const events = useMemo(
() => mergeActivityEvents(remoteEvents, localEvents).slice(0, limit),
[limit, localEvents, remoteEvents],
);
return { events, syncState, version };
}