feat: edit Vani of the day
This commit is contained in:
+69
@@ -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),
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user