M9 S3 (frontend): recall views adopt useNoteList + AsyncState/EmptyState
CI & Build / Python lint (push) Successful in 3s
CI & Build / TypeScript typecheck (push) Successful in 6s
CI & Build / Python tests (push) Successful in 10s
CI & Build / Build & push image (push) Successful in 34s

The Search / Timeline / Reminders views each hand-rolled the same
items+loading+error scaffold, retry button, and editor-host glue.

- useNoteList(fetcher, fallbackError) (new): the load-a-note-list scaffold
  (items/loading/error + a load() that never leaves a half-state). Views
  supply just the fetcher; the refs drive <AsyncState>.
- SearchView / TimelineView / RemindersView: adopt useNoteList + useNoteEditor
  + <AsyncState>/<EmptyState>; drop the local list/loading/error refs, the
  duplicated retry blocks, and the notes.items-shadowing navigate glue.
- GraphView: editor host now via useNoteEditor (openNode/closeEditor/onNavigate
  collapse to navigate); loading/error via <AsyncState>. Its two empty states
  keep inline markup/buttons, so they stay custom (not forced into EmptyState).
- reminders store: fetchReminders() is the single owner of /api/notes/reminders;
  both the background poll (check) and RemindersView read through it.

Frontend-only; CI vue-tsc is the type gate (no local typecheck, rule 10).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRgehjoz7Yv8LkUfADxACm
This commit is contained in:
2026-07-23 21:36:24 -04:00
co-authored by Claude Opus 4.8
parent f1033da75e
commit 590d3ff2f6
6 changed files with 173 additions and 251 deletions
+8 -2
View File
@@ -20,11 +20,17 @@ export const useReminderStore = defineStore("reminders", () => {
let timer: ReturnType<typeof setInterval> | undefined;
let primed = false;
// Single owner of the reminders endpoint — the RemindersView reads its list through
// this too, so the URL + response shape live in one place.
async function fetchReminders(): Promise<Note[]> {
return (await api.get<{ notes: Note[] }>("/api/notes/reminders")).notes;
}
async function check(): Promise<void> {
const ui = useUiStore();
let notes: Note[];
try {
notes = (await api.get<{ notes: Note[] }>("/api/notes/reminders")).notes;
notes = await fetchReminders();
} catch {
return;
}
@@ -66,5 +72,5 @@ export const useReminderStore = defineStore("reminders", () => {
osEnabled.value = (await Notification.requestPermission()) === "granted";
}
return { osSupported, osEnabled, start, stop, enableOs };
return { osSupported, osEnabled, start, stop, enableOs, fetchReminders };
});