// frontend/components/calendar/EvEditor.tsx — 새 일정 생성/편집 모달 "use client"; import { useState } from "react"; import { Icon } from "@/components/Icon"; import { calendarApi } from "@/lib/calendar/api"; import { addHour } from "@/lib/calendar/time"; import type { Calendar, CalEvent, EventWrite } from "@/lib/calendar/types"; // 쓰기 가능한 캘린더(Google = gcal-*, Outlook = ocal-*, 로컬 = local). function writableCalendars(cals: Calendar[]): Calendar[] { const ok = cals.filter( (c) => c.id.startsWith("gcal-") || c.id.startsWith("ocal-") || c.id === "local", ); return ok.length ? ok : cals; } export function EvEditor({ calendars, initial, defaultDate, defaultTime, onClose, onSaved, onDeleted, }: { calendars: Calendar[]; initial?: CalEvent | null; // 있으면 편집, 없으면 생성 defaultDate: string; // 생성 시 기본 날짜(ISO) defaultTime?: string; // 생성 시 기본 시작시각("HH:MM", 슬롯 클릭) onClose: () => void; onSaved: () => void; onDeleted?: () => void; }) { const editing = !!initial; const writable = writableCalendars(calendars); const [title, setTitle] = useState(initial?.title ?? ""); const [date, setDate] = useState(initial?.date || defaultDate); const [allDay, setAllDay] = useState(editing ? !initial?.start : false); const [start, setStart] = useState(initial?.start || defaultTime || "09:00"); const [end, setEnd] = useState( initial?.end || (defaultTime ? addHour(defaultTime, 1) : "10:00"), ); const [loc, setLoc] = useState(initial?.loc ?? ""); const [note, setNote] = useState(initial?.note ?? ""); const [cal, setCal] = useState(initial?.cal || writable[0]?.id || ""); const [people, setPeople] = useState((initial?.people ?? []).join(", ")); const [rrule, setRrule] = useState(initial?.rrule ?? ""); const [reminder, setReminder] = useState(initial?.reminders?.[0] ?? -1); // -1 = 없음 const [busy, setBusy] = useState(false); const [err, setErr] = useState(""); const save = async () => { if (!title.trim()) { setErr("제목을 입력하세요"); return; } setBusy(true); setErr(""); const body: EventWrite = { title: title.trim(), date, start: allDay ? "" : start, end: allDay ? "" : end, loc: loc.trim(), note: note.trim(), people: people .split(",") .map((p) => p.trim()) .filter(Boolean), cal, rrule, reminders: reminder >= 0 ? [reminder] : [], }; try { if (editing && initial) await calendarApi.updateEvent(initial.id, body); else await calendarApi.createEvent(body); onSaved(); } catch (e) { setErr(e instanceof Error ? e.message : "저장하지 못했어요"); setBusy(false); } }; const del = async () => { if (!initial) return; setBusy(true); setErr(""); try { await calendarApi.deleteEvent(initial.id); onDeleted?.(); } catch (e) { setErr(e instanceof Error ? e.message : "삭제하지 못했어요"); setBusy(false); } }; return ( <>

{editing ? "일정 편집" : "새 일정"}

{!allDay && (
)}