feat: edit Vani of the day

This commit is contained in:
gosangam
2026-08-31 12:15:19 +05:30
parent df9af9dbac
commit 53e00863f7
3 changed files with 288 additions and 0 deletions
+69
View File
@@ -480,3 +480,72 @@ export const rewardGifts = {
body: JSON.stringify({ reward_key: rewardKey }),
}).then((r) => r.data),
};
// ─── Vāṇī of the Day ────────────────────────────────────────────────────────
/** One decided day. `payload` is the blob the home-page CTA renders. */
export type VaniPick = {
day: string;
kind: "verse" | "prose" | "transcript";
ref_id: string;
payload: {
kind: string;
label: string;
title: string;
subtitle: string;
href: string;
book_title?: string;
date?: string;
};
};
/** A search hit, narrowed to what pinning needs. */
export type VaniCandidate = {
collection: string;
doc_id: string;
title: string;
snippet: string;
url: string;
};
/** Typesense collection → the kind the vani picker uses. */
const VANI_KINDS: Record<string, VaniPick["kind"]> = {
verses: "verse",
prose: "prose",
transcriptions: "transcript",
};
export function vaniKindFor(collection: string): VaniPick["kind"] | null {
return VANI_KINDS[collection] ?? null;
}
export const vani = {
/** Decided days from today onward. */
schedule: () => call<VaniPick[]>("/admin/vani?limit=30").then((r) => r.data),
/** Pin one item to a day. Only the reference travels — the BFF rebuilds the
* display blob, so a pinned pick renders exactly like an automatic one. */
set: (input: { day: string; kind: VaniPick["kind"]; ref_id: string }) =>
call<VaniPick>("/admin/vani", {
method: "POST",
body: JSON.stringify(input),
}).then((r) => r.data),
/** Hand the day back to the random picker. */
clear: (day: string) =>
call<void>(`/admin/vani/${encodeURIComponent(day)}`, { method: "DELETE" }),
/**
* Search the three vāṇī-eligible collections. Uses the public search
* endpoint — the same index the app searches — and keeps only hits that map
* to a pinnable kind.
*/
search: async (q: string): Promise<VaniCandidate[]> => {
const { data } = await call<{ results: VaniCandidate[] }>(
`/search?type=all&limit=20&q=${encodeURIComponent(q)}`,
);
return (data?.results ?? []).filter(
(r) => r.doc_id && vaniKindFor(r.collection),
);
},
};