desktop M10.3: frontend data-source adapter seam (repo interface + rest.ts)
Extract a typed repository interface (adapters/repo.ts) from the scattered store/view -> api.* calls, backed by adapters/rest.ts (verbatim HTTP mapping) and selected through adapters/index.ts. Every store and the notes-facing views now depend on `repo`, never the HTTP client directly -- the seam the offline local source (M10.5, over Tauri invoke) plugs into next. Behavior-preserving for web: rest.ts maps each semantic method to the exact endpoint the code called before; query-string and multipart building moved out of the stores/views into rest.ts (the one place that knows the URL shape). Client-side logic (reconcile/sort/optimistic reorder/toasts) stays in the stores. GraphView + admin SettingsView keep direct api calls -- out of the offline-core scope (M10.5 is board/editor/capture/search/filter/labels/ checklists/reminders). Task 1992. 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:
@@ -1,8 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, watch } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
import { api } from "../api/client";
|
||||
import { type Note } from "../stores/notes";
|
||||
import { repo } from "../adapters";
|
||||
import { useNoteList } from "../composables/useNoteList";
|
||||
import { useNoteEditor } from "../composables/useNoteEditor";
|
||||
import AsyncState from "../components/AsyncState.vue";
|
||||
@@ -17,7 +16,7 @@ const noMatchSubtitle = computed(() => `Nothing found for "${query.value}".`);
|
||||
const { items: results, loading, error, load: run } = useNoteList(async () => {
|
||||
const q = query.value.trim();
|
||||
if (!q) return [];
|
||||
return (await api.get<{ notes: Note[] }>(`/api/notes/search?q=${encodeURIComponent(q)}`)).notes;
|
||||
return repo.notes.search(q);
|
||||
}, "Search failed.");
|
||||
|
||||
const { editing, open: openEditor, close: closeEditor, navigate: onNavigate } = useNoteEditor({
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref, watch } from "vue";
|
||||
import { api } from "../api/client";
|
||||
import { repo } from "../adapters";
|
||||
import type { NoteListQuery } from "../adapters/repo";
|
||||
import { type Note } from "../stores/notes";
|
||||
import { addLocalDays, parseLocalDate } from "../notes/datetime";
|
||||
import { useNoteList } from "../composables/useNoteList";
|
||||
@@ -19,18 +20,22 @@ const fromDate = ref("");
|
||||
const toDate = ref("");
|
||||
const hasRange = computed(() => !!fromDate.value || !!toDate.value);
|
||||
|
||||
function buildQuery(): string {
|
||||
const params = new URLSearchParams({ filter: "active", sort: "created" });
|
||||
function buildQuery(): NoteListQuery {
|
||||
const from = parseLocalDate(fromDate.value);
|
||||
if (from) params.set("created_after", from.toISOString());
|
||||
const to = parseLocalDate(toDate.value);
|
||||
// Half-open upper bound: start of the day AFTER `to`, so the whole `to` day is included.
|
||||
if (to) params.set("created_before", addLocalDays(to, 1).toISOString());
|
||||
return params.toString();
|
||||
return {
|
||||
view: "active",
|
||||
sort: "created",
|
||||
facets: {
|
||||
created_after: from ? from.toISOString() : undefined,
|
||||
// Half-open upper bound: start of the day AFTER `to`, so the whole `to` day is included.
|
||||
created_before: to ? addLocalDays(to, 1).toISOString() : undefined,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const { items, loading, error, load } = useNoteList(
|
||||
async () => (await api.get<{ notes: Note[] }>(`/api/notes?${buildQuery()}`)).notes,
|
||||
async () => repo.notes.list(buildQuery()),
|
||||
"Couldn't load the timeline.",
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user