From 10d4170ee8197e8993d571247ef6993cd47e69e3 Mon Sep 17 00:00:00 2001 From: Till-JS <101404291+Till-JS@users.noreply.github.com> Date: Sat, 13 Dec 2025 14:24:08 +0100 Subject: [PATCH] feat(calendar): add event context menu and fix event persistence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add reusable ContextMenu component to shared-ui with icon support - Create EventContextMenu for calendar with actions: - Edit, Duplicate, Change Calendar, Change Color - Export to .ics, Delete with confirmation - Integrate context menu in DayView, WeekView, and AgendaView - Fix event creation not showing success/error feedback - Fix events store to properly handle API response format - Add API logging for debugging event operations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../apps/web/src/lib/api/base-client.ts | 5 +- apps/calendar/apps/web/src/lib/api/events.ts | 10 + .../lib/components/calendar/AgendaView.svelte | 22 +- .../lib/components/calendar/DayView.svelte | 20 ++ .../lib/components/calendar/WeekView.svelte | 18 ++ .../components/event/EventContextMenu.svelte | 198 ++++++++++++++++++ .../components/event/QuickEventOverlay.svelte | 7 +- .../apps/web/src/lib/stores/events.svelte.ts | 12 +- .../src/context-menu/ContextMenu.svelte | 2 +- packages/shared-ui/src/context-menu/types.ts | 7 +- 10 files changed, 287 insertions(+), 14 deletions(-) create mode 100644 apps/calendar/apps/web/src/lib/components/event/EventContextMenu.svelte diff --git a/apps/calendar/apps/web/src/lib/api/base-client.ts b/apps/calendar/apps/web/src/lib/api/base-client.ts index 06f9ba7c7..383a33a06 100644 --- a/apps/calendar/apps/web/src/lib/api/base-client.ts +++ b/apps/calendar/apps/web/src/lib/api/base-client.ts @@ -58,7 +58,10 @@ export function createApiClient(config: ApiClientConfig) { headers['Authorization'] = `Bearer ${authToken}`; } - const response = await fetch(`${baseUrl}${apiPrefix}${endpoint}`, { + const url = `${baseUrl}${apiPrefix}${endpoint}`; + console.log(`[API Client] ${method} ${url}`, { hasToken: !!authToken }); + + const response = await fetch(url, { method, headers, body: isFormData ? (body as FormData) : body ? JSON.stringify(body) : undefined, diff --git a/apps/calendar/apps/web/src/lib/api/events.ts b/apps/calendar/apps/web/src/lib/api/events.ts index 1ce53b469..893cf5f3d 100644 --- a/apps/calendar/apps/web/src/lib/api/events.ts +++ b/apps/calendar/apps/web/src/lib/api/events.ts @@ -23,7 +23,14 @@ export async function getEvents(params: QueryEventsParams) { if (params.search) { searchParams.set('search', params.search); } + console.log('[Calendar API] Fetching events:', params); const result = await fetchApi<{ events: CalendarEvent[] }>(`/events?${searchParams.toString()}`); + console.log( + '[Calendar API] Fetch events result:', + result.data?.events?.length, + 'events', + result.error + ); if (result.error || !result.data) { return { data: null, error: result.error }; } @@ -57,11 +64,14 @@ export async function getEventsByCalendar(calendarId: string) { } export async function createEvent(data: CreateEventInput) { + console.log('[Calendar API] Creating event:', data); const result = await fetchApi<{ event: CalendarEvent }>('/events', { method: 'POST', body: data, }); + console.log('[Calendar API] Create event result:', result); if (result.error || !result.data) { + console.error('[Calendar API] Create event failed:', result.error); return { data: null, error: result.error }; } return { data: result.data.event, error: null }; diff --git a/apps/calendar/apps/web/src/lib/components/calendar/AgendaView.svelte b/apps/calendar/apps/web/src/lib/components/calendar/AgendaView.svelte index 6fc284435..a8202c9bf 100644 --- a/apps/calendar/apps/web/src/lib/components/calendar/AgendaView.svelte +++ b/apps/calendar/apps/web/src/lib/components/calendar/AgendaView.svelte @@ -2,6 +2,8 @@ import { viewStore } from '$lib/stores/view.svelte'; import { eventsStore } from '$lib/stores/events.svelte'; import { calendarsStore } from '$lib/stores/calendars.svelte'; + import { eventContextMenuStore } from '$lib/stores/eventContextMenu.svelte'; + import EventContextMenu from '$lib/components/event/EventContextMenu.svelte'; import { format, parseISO, isToday, isTomorrow, startOfDay } from 'date-fns'; import { de } from 'date-fns/locale'; import type { CalendarEvent } from '@calendar/shared'; @@ -65,6 +67,18 @@ onEventClick(event); } } + + function handleEventContextMenu(event: CalendarEvent, e: MouseEvent) { + e.preventDefault(); + e.stopPropagation(); + eventContextMenuStore.show(event, e.clientX, e.clientY); + } + + function handleContextMenuEdit(event: CalendarEvent) { + if (onEventClick) { + onEventClick(event); + } + }
@@ -90,7 +104,11 @@
{#each group.events as event} -