S1: frontend infra — AsyncState/EmptyState + useNoteEditor, adopted in BoardView
M9 section S1, commit 4 (frontend). Introduce the shared UI primitives the 7 data views + 5 editor hosts were hand-rolling: - components/AsyncState.vue: the loading / error(+Retry) wrapper (emits `retry`). - components/EmptyState.vue: the centered title/subtitle "nothing here" block. - composables/useNoteEditor.ts: the editing/open/close/navigate glue every editor host duplicated, as one controller (onClose hook + local-list resolution for [[wiki-link]] navigation). BoardView adopts all three: its three hand-rolled loading/error/empty blocks collapse into <AsyncState> + <EmptyState>, and its editor glue into useNoteEditor. The other views + editor hosts adopt these in the Organize (S3) and Auth (S5) sections. Behavior-preserving. Frontend has no local typecheck (rule 10); CI's vue-tsc is the gate. 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:
@@ -0,0 +1,33 @@
|
||||
import { ref } from "vue";
|
||||
import { useNotesStore, type Note } from "../stores/notes";
|
||||
|
||||
// Shared controller for hosting the NoteEditor modal. Every view that opens the
|
||||
// editor used to re-declare the same editing/open/close/navigate glue; this is the
|
||||
// single implementation.
|
||||
//
|
||||
// - `onClose` lets a host clean up its own state (e.g. a board's compose flag).
|
||||
// - `list` is the host's local note array, tried first when resolving a navigated
|
||||
// [[wiki-link]] target before falling back to the store, then a fetch — so views
|
||||
// that keep their own list (reminders, timeline, search, graph) still resolve
|
||||
// locally without duplicating the lookup.
|
||||
export function useNoteEditor(options: { onClose?: () => void; list?: () => Note[] } = {}) {
|
||||
const notes = useNotesStore();
|
||||
const editing = ref<Note | null>(null);
|
||||
|
||||
function open(note: Note): void {
|
||||
editing.value = note;
|
||||
}
|
||||
|
||||
function close(): void {
|
||||
editing.value = null;
|
||||
options.onClose?.();
|
||||
}
|
||||
|
||||
async function navigate(id: string): Promise<void> {
|
||||
const local = options.list?.() ?? notes.items;
|
||||
const found = local.find((n) => n.id === id) ?? notes.items.find((n) => n.id === id) ?? (await notes.fetchOne(id));
|
||||
if (found) editing.value = found;
|
||||
}
|
||||
|
||||
return { editing, open, close, navigate };
|
||||
}
|
||||
Reference in New Issue
Block a user