feat: broadcast

This commit is contained in:
gosangam
2026-08-29 18:34:33 +05:30
parent 7ff5610477
commit c9ac2bd3b4
3 changed files with 351 additions and 0 deletions
+57
View File
@@ -379,3 +379,60 @@ export const api = {
});
},
};
// ─── Broadcasts ─────────────────────────────────────────────────────────────
/**
* Announcements pushed to every user and shown once, in a modal.
*
* No history is kept on the user's side: there is no notification row and no
* tray entry, so a broadcast exists only until each person dismisses it.
*/
export type Broadcast = {
id: string;
title: string;
body: string;
banner_url?: string | null;
cta_label?: string | null;
cta_url?: string | null;
published_at?: string | null;
expires_at?: string | null;
created_at: string;
/** How many people have dismissed it — the only delivery signal there is. */
seen_count: number;
};
export type NewBroadcast = {
title: string;
body: string;
banner_key?: string | null;
cta_label?: string | null;
cta_url?: string | null;
expires_at?: string | null;
publish: boolean;
};
export const broadcasts = {
list: () => listed<Broadcast>("/admin/broadcasts?limit=50"),
create: (input: NewBroadcast) =>
call<Broadcast>("/admin/broadcasts", {
method: "POST",
body: JSON.stringify(input),
}).then((r) => r.data),
publish: (id: string) =>
call<Broadcast>(`/admin/broadcasts/${id}/publish`, { method: "POST" }).then(
(r) => r.data,
),
remove: (id: string) =>
call<void>(`/admin/broadcasts/${id}`, { method: "DELETE" }),
/** Presign a banner upload; returns the PUT URL and the key to submit. */
presignBanner: (contentType: string) =>
call<{ upload_url: string; key: string }>(
"/admin/broadcasts/banner-presign",
{ method: "POST", body: JSON.stringify({ content_type: contentType }) },
).then((r) => r.data),
};