import { api } from "./api"; export type ItemStatus = "coveted" | "acquired" | "renounced"; export type List = { id: string; name: string; emoji: string | null; description: string | null; share_token: string | null; position: number; created_at: string; updated_at: string; }; export type SharedView = { list: List; items: Item[] }; export type Subscription = { id: string; kind: "list" | "item"; created_at: string; list_id: string | null; item_id: string | null; title: string; emoji: string | null; share_token: string | null; url: string | null; image_url: string | null; current_price: number | null; currency: string | null; in_stock: boolean | null; target_price: number | null; }; export type Item = { id: string; list_id: string; title: string; url: string | null; note: string | null; status: ItemStatus; target_price: number | null; position: number; // Filled by the Phase 3 fetcher; null until then. title_fetched: string | null; current_price: number | null; currency: string | null; image_url: string | null; in_stock: boolean | null; source: string | null; fetched_at: string | null; track_enabled: boolean; last_error: string | null; checked_at: string | null; created_at: string; updated_at: string; }; export type PricePoint = { price: number; currency: string; in_stock: boolean | null; fetched_at: string; }; export type NewList = { name: string; emoji?: string | null; description?: string | null; }; export type NewItem = { title: string; url?: string | null; note?: string | null; target_price?: number | null; currency?: string | null; }; // ---- Lists ---------------------------------------------------------------- export const listsApi = { all: () => api.get("/lists"), create: (b: NewList) => api.post("/lists", b), update: (id: string, b: Partial & { position?: number }) => api.patch(`/lists/${id}`, b), remove: (id: string) => api.del<{ deleted: string }>(`/lists/${id}`), share: (id: string) => api.post(`/lists/${id}/share`, {}), unshare: (id: string) => api.del(`/lists/${id}/share`), shared: (token: string) => api.get(`/shared/${token}`), items: (listId: string) => api.get(`/lists/${listId}/items`), addItem: (listId: string, b: NewItem) => api.post(`/lists/${listId}/items`, b), updateItem: ( id: string, b: Partial & { status?: ItemStatus; position?: number }, ) => api.patch(`/items/${id}`, b), removeItem: (id: string) => api.del<{ deleted: string }>(`/items/${id}`), refetch: (id: string) => api.post(`/items/${id}/refetch`, {}), history: (id: string) => api.get(`/items/${id}/history`), subscriptions: () => api.get("/subscriptions"), subscribe: (b: { list_id?: string; item_id?: string }) => api.post<{ id: string }>("/subscriptions", b), unsubscribe: (id: string) => api.del<{ deleted: string }>(`/subscriptions/${id}`), }; /** Reactive store for the user's lists. */ class ListsStore { items = $state([]); loaded = $state(false); async load() { this.items = await listsApi.all(); this.loaded = true; } async create(b: NewList): Promise { const created = await listsApi.create(b); this.items.push(created); return created; } async remove(id: string) { await listsApi.remove(id); this.items = this.items.filter((l) => l.id !== id); } /** Swap in an updated list (e.g. after share/unshare). */ replace(list: List) { const i = this.items.findIndex((l) => l.id === list.id); if (i >= 0) this.items[i] = list; } } export const lists = new ListsStore(); /** The current user's subscriptions, with helpers to toggle by list/item. */ class SubsStore { items = $state([]); loaded = $state(false); async load() { this.items = await listsApi.subscriptions(); this.loaded = true; } /** Existing subscription id for a list, or null. */ forList(listId: string): string | null { return this.items.find((s) => s.list_id === listId)?.id ?? null; } /** Existing subscription id for an item, or null. */ forItem(itemId: string): string | null { return this.items.find((s) => s.item_id === itemId)?.id ?? null; } async subscribeList(listId: string) { if (this.forList(listId)) return; await listsApi.subscribe({ list_id: listId }); await this.load(); } async subscribeItem(itemId: string) { if (this.forItem(itemId)) return; await listsApi.subscribe({ item_id: itemId }); await this.load(); } async unsubscribe(id: string) { await listsApi.unsubscribe(id); this.items = this.items.filter((s) => s.id !== id); } } export const subs = new SubsStore();