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
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)),
|
|
};
|