added sharing and subscriptions
This commit is contained in:
@@ -7,11 +7,31 @@ export type List = {
|
||||
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;
|
||||
@@ -64,6 +84,9 @@ export const listsApi = {
|
||||
update: (id: string, b: Partial<NewList> & { position?: number }) =>
|
||||
api.patch<List>(`/lists/${id}`, b),
|
||||
remove: (id: string) => api.del<{ deleted: string }>(`/lists/${id}`),
|
||||
share: (id: string) => api.post<List>(`/lists/${id}/share`, {}),
|
||||
unshare: (id: string) => api.del<List>(`/lists/${id}/share`),
|
||||
shared: (token: string) => api.get<SharedView>(`/shared/${token}`),
|
||||
|
||||
items: (listId: string) => api.get<Item[]>(`/lists/${listId}/items`),
|
||||
addItem: (listId: string, b: NewItem) =>
|
||||
@@ -75,6 +98,11 @@ export const listsApi = {
|
||||
removeItem: (id: string) => api.del<{ deleted: string }>(`/items/${id}`),
|
||||
refetch: (id: string) => api.post<Item>(`/items/${id}/refetch`, {}),
|
||||
history: (id: string) => api.get<PricePoint[]>(`/items/${id}/history`),
|
||||
|
||||
subscriptions: () => api.get<Subscription[]>("/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. */
|
||||
@@ -97,6 +125,52 @@ class ListsStore {
|
||||
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<Subscription[]>([]);
|
||||
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();
|
||||
|
||||
Reference in New Issue
Block a user