Local-first sync: on-device store + offline mutation queue, idempotent server upserts
All checks were successful
Build & Release APK / build (push) Successful in 10m54s

Screens render synchronously from an AsyncStorage-backed store; every
mutation applies locally and drains to the API in the background
(last-write-wins, client-generated UUIDs). Sydney round-trips are off the
interaction path and the app works fully offline.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-07 19:19:51 -07:00
parent 4d6031d007
commit ad16522461
13 changed files with 417 additions and 216 deletions

View File

@@ -34,7 +34,7 @@ export const api = {
return req<Task[]>(`/v1/tasks${q ? `?${q}` : ""}`);
},
get: (id: string) => req<Task>(`/v1/tasks/${id}`),
create: (data: Partial<Task> & { title: string }) =>
create: (data: Partial<Task> & { title: string; id?: string }) =>
req<Task>("/v1/tasks", { method: "POST", body: JSON.stringify(data) }),
update: (id: string, data: Partial<Task>) =>
req<Task>(`/v1/tasks/${id}`, { method: "PATCH", body: JSON.stringify(data) }),
@@ -42,7 +42,7 @@ export const api = {
},
projects: {
list: () => req<Project[]>("/v1/projects"),
create: (data: Partial<Project> & { name: string }) =>
create: (data: Partial<Project> & { name: string; id?: string }) =>
req<Project>("/v1/projects", { method: "POST", body: JSON.stringify(data) }),
update: (id: string, data: Partial<Project>) =>
req<Project>(`/v1/projects/${id}`, { method: "PATCH", body: JSON.stringify(data) }),