feat(calendar): add drag-create, resize, recurring scope, quick-create, and duplication
- Click-drag on empty time slots to create events with pre-filled time range - Resize events by dragging bottom edge (15-min snap, optimistic JMAP update) - Recurring event edit/delete scope dialog (this/following/all occurrences) - Double-click quick event creation with inline title input - Event duplication button in modal (+1 day offset) - Shared interaction hook for pointer-based calendar interactions Fixes #13
This commit is contained in:
@@ -8,6 +8,7 @@ import {
|
||||
} from "date-fns";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { EventCard } from "./event-card";
|
||||
import { getEventEndDate } from "@/lib/calendar-utils";
|
||||
import type { CalendarEvent, Calendar } from "@/lib/jmap/types";
|
||||
import { useAuthStore } from "@/stores/auth-store";
|
||||
import { useCalendarStore } from "@/stores/calendar-store";
|
||||
@@ -18,21 +19,10 @@ interface CalendarMonthViewProps {
|
||||
events: CalendarEvent[];
|
||||
calendars: Calendar[];
|
||||
onSelectDate: (date: Date) => void;
|
||||
onSelectEvent: (event: CalendarEvent) => void;
|
||||
onSelectEvent: (event: CalendarEvent, anchorRect: DOMRect) => void;
|
||||
firstDayOfWeek?: number;
|
||||
}
|
||||
|
||||
function getEventEndDate(event: CalendarEvent): Date {
|
||||
const start = new Date(event.start);
|
||||
if (!event.duration) return start;
|
||||
const days = parseInt(event.duration.match(/(\d+)D/)?.[1] || "0");
|
||||
const hours = parseInt(event.duration.match(/(\d+)H/)?.[1] || "0");
|
||||
const minutes = parseInt(event.duration.match(/(\d+)M/)?.[1] || "0");
|
||||
const weeks = parseInt(event.duration.match(/(\d+)W/)?.[1] || "0");
|
||||
const totalMs = ((weeks * 7 + days) * 24 * 60 + hours * 60 + minutes) * 60000;
|
||||
return new Date(start.getTime() + totalMs);
|
||||
}
|
||||
|
||||
export function CalendarMonthView({
|
||||
selectedDate,
|
||||
events,
|
||||
@@ -192,7 +182,7 @@ export function CalendarMonthView({
|
||||
event={ev}
|
||||
calendar={calendarMap.get(calId)}
|
||||
variant="chip"
|
||||
onClick={() => onSelectEvent(ev)}
|
||||
onClick={(rect) => onSelectEvent(ev, rect)}
|
||||
draggable
|
||||
/>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user