// 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(r: Response): Promise { 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; } export const calendarApi = { week: () => fetch("/api/calendar/week", { cache: "no-store" }).then((r) => ok(r)), createEvent: (body: EventWrite) => fetch("/api/calendar/events", { method: "POST", headers: J, body: JSON.stringify(body) }).then( (r) => ok(r), ), updateEvent: (id: string, body: EventWrite) => fetch(`/api/calendar/events/${id}`, { method: "PATCH", headers: J, body: JSON.stringify(body), }).then((r) => ok(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(r)), day: (d: number) => fetch(`/api/calendar/day/${d}`, { cache: "no-store" }).then((r) => ok(r)), meeting: (id: string) => fetch(`/api/calendar/meetings/${id}`, { cache: "no-store" }).then((r) => ok(r)), materialize: (mid: string, idx: number) => fetch(`/api/calendar/meetings/${mid}/actions/${idx}/materialize`, { method: "POST" }).then( (r) => ok(r), ), materializeAll: (mid: string) => fetch(`/api/calendar/meetings/${mid}/actions/materialize-all`, { method: "POST" }).then((r) => ok(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)), };