admin: descriptive commit messages + dev-mode sync fallback

Server side: writeData() now takes a message, and each action in the
POST handler computes its own — e.g. "admin: add idea "Title"", "admin:
clear note on slug". For setTodos (which ships the whole blob), diff
old vs new per slug to produce messages like "neighbor-sum-avoidance:
add T6" or "mark T1 done, add T5".

Client side: syncFromServer() falls back to the bundled admin-data.json
when /api/admin is unreachable, so the admin panel reflects committed
state under `astro dev` (which doesn't run Netlify Functions).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Neeldhara Misra 2026-04-19 18:26:27 +05:30
parent 0d0365cf6d
commit e7dd3ed8eb
2 changed files with 95 additions and 21 deletions

View file

@ -1,4 +1,5 @@
import type { InteractiveStatus } from "./interactives";
import staticAdminData from "@/data/admin-data.json";
const ADMIN_KEY = "interactives_admin";
const NOTES_KEY = "interactives_notes";
@ -264,23 +265,30 @@ export function getAllTodoCounts(): Record<string, { total: number; done: number
// --- Sync: load server data into localStorage ---
function applyServerData(data: any) {
if (data.statusOverrides !== undefined) {
localStorage.setItem(STATUS_KEY, JSON.stringify(data.statusOverrides));
}
if (data.notes !== undefined) {
localStorage.setItem(NOTES_KEY, JSON.stringify(data.notes));
}
if (data.ideas !== undefined) {
localStorage.setItem(IDEAS_KEY, JSON.stringify(data.ideas));
}
if (data.todos !== undefined) {
localStorage.setItem(TODOS_KEY, JSON.stringify(data.todos));
}
}
export async function syncFromServer(): Promise<void> {
try {
const data = await apiCall("GET");
if (data.error) return; // auth failed
if (data.statusOverrides !== undefined) {
localStorage.setItem(STATUS_KEY, JSON.stringify(data.statusOverrides));
}
if (data.notes !== undefined) {
localStorage.setItem(NOTES_KEY, JSON.stringify(data.notes));
}
if (data.ideas !== undefined) {
localStorage.setItem(IDEAS_KEY, JSON.stringify(data.ideas));
}
if (data.todos !== undefined) {
localStorage.setItem(TODOS_KEY, JSON.stringify(data.todos));
}
if (data.error) throw new Error("auth failed");
applyServerData(data);
} catch {
// Offline or server unavailable — use localStorage as fallback
// API unreachable (e.g. `astro dev` without netlify functions) — fall back
// to the version of admin-data.json bundled at build time so the admin UI
// still reflects the committed state locally.
applyServerData(staticAdminData);
}
}