You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

77 lines
2.3 KiB
TypeScript

// frontend/lib/calendar/api.ts — calendarApi (week/day/meeting/materialize/focus/events)
import type {
WeekBundle,
DayBundle,
Meeting,
MaterializeResult,
FocusBlock,
CalEvent,
EventWrite,
} from "./types";
const J = { "Content-Type": "application/json" };
async function ok<T>(r: Response): Promise<T> {
if (!r.ok) {
let msg = `${r.status} ${r.statusText}`;
try {
const j = await r.json();
if (j?.detail) msg = j.detail;
} catch {
/* 본문 없음 */
}
throw new Error(msg);
}
return r.json() as Promise<T>;
}
export const calendarApi = {
week: () => fetch("/api/calendar/week", { cache: "no-store" }).then((r) => ok<WeekBundle>(r)),
createEvent: (body: EventWrite) =>
fetch("/api/calendar/events", { method: "POST", headers: J, body: JSON.stringify(body) }).then(
(r) => ok<CalEvent>(r),
),
updateEvent: (id: string, body: EventWrite) =>
fetch(`/api/calendar/events/${id}`, {
method: "PATCH",
headers: J,
body: JSON.stringify(body),
}).then((r) => ok<CalEvent>(r)),
deleteEvent: (id: string) =>
fetch(`/api/calendar/events/${id}`, { method: "DELETE" }).then((r) =>
ok<{ ok: boolean; id: string }>(r),
),
rsvp: (id: string, status: "accepted" | "declined" | "tentative") =>
fetch(`/api/calendar/events/${id}/rsvp`, {
method: "POST",
headers: J,
body: JSON.stringify({ status }),
}).then((r) => ok<CalEvent>(r)),
day: (d: number) =>
fetch(`/api/calendar/day/${d}`, { cache: "no-store" }).then((r) => ok<DayBundle>(r)),
meeting: (id: string) =>
fetch(`/api/calendar/meetings/${id}`, { cache: "no-store" }).then((r) => ok<Meeting>(r)),
materialize: (mid: string, idx: number) =>
fetch(`/api/calendar/meetings/${mid}/actions/${idx}/materialize`, { method: "POST" }).then(
(r) => ok<MaterializeResult>(r),
),
materializeAll: (mid: string) =>
fetch(`/api/calendar/meetings/${mid}/actions/materialize-all`, { method: "POST" }).then((r) =>
ok<MaterializeResult[]>(r),
),
focusSuggest: (day: number, min_minutes = 20, create = false) =>
fetch("/api/calendar/focus/suggest", {
method: "POST",
headers: J,
body: JSON.stringify({ day, min_minutes, create }),
}).then((r) => ok<{ day: number; suggestions: FocusBlock[]; created: boolean }>(r)),
};