diff --git a/apps/calendar/apps/web/src/lib/components/calendar/CalendarSidebar.svelte b/apps/calendar/apps/web/src/lib/components/calendar/CalendarSidebar.svelte
index e8dbef1a8..e0b9bf5c5 100644
--- a/apps/calendar/apps/web/src/lib/components/calendar/CalendarSidebar.svelte
+++ b/apps/calendar/apps/web/src/lib/components/calendar/CalendarSidebar.svelte
@@ -1,14 +1,27 @@
+
+ {#if externalCalendarsStore.calendars.length > 0}
+
+
+
+ {#each externalCalendarsStore.calendars as cal}
+
+ {/each}
+
+ {/if}
diff --git a/apps/calendar/apps/web/src/lib/components/event/EventDetailModal.svelte b/apps/calendar/apps/web/src/lib/components/event/EventDetailModal.svelte
index 84a6ae38b..ab7ed9feb 100644
--- a/apps/calendar/apps/web/src/lib/components/event/EventDetailModal.svelte
+++ b/apps/calendar/apps/web/src/lib/components/event/EventDetailModal.svelte
@@ -3,8 +3,10 @@
import { eventsStore } from '$lib/stores/events.svelte';
import { calendarsStore } from '$lib/stores/calendars.svelte';
import EventForm from './EventForm.svelte';
+ import RecurrenceEditDialog from './RecurrenceEditDialog.svelte';
import { TagBadge, toastStore as toast } from '@manacore/shared-ui';
import type { CalendarEvent, UpdateEventInput } from '@calendar/shared';
+ import { describeRecurrence, parseRRule } from '@calendar/shared';
import * as api from '$lib/api/events';
import { format } from 'date-fns';
import { de } from 'date-fns/locale';
@@ -21,6 +23,8 @@
let event = $state(null);
let loading = $state(true);
let isEditing = $state(false);
+ let showRecurrenceDialog = $state(false);
+ let recurrenceDialogMode = $state<'edit' | 'delete'>('delete');
// Load event data
$effect(() => {
@@ -60,6 +64,13 @@
async function handleDelete() {
if (!event) return;
+ // For recurring events, show the recurrence dialog
+ if (event.recurrenceRule || eventsStore.isRecurrenceOccurrence(event.id)) {
+ recurrenceDialogMode = 'delete';
+ showRecurrenceDialog = true;
+ return;
+ }
+
if (!confirm('Möchten Sie diesen Termin wirklich löschen?')) {
return;
}
@@ -75,6 +86,21 @@
onClose();
}
+ async function handleRecurrenceAction(action: 'this' | 'all' | 'this_and_future') {
+ if (!event) return;
+ showRecurrenceDialog = false;
+
+ if (recurrenceDialogMode === 'delete') {
+ let result;
+ if (action === 'this') {
+ result = await eventsStore.deleteRecurrenceOccurrence(event.id);
+ } else {
+ result = await eventsStore.deleteRecurrenceSeries(event.id);
+ }
+ if (!result.error) onClose();
+ }
+ }
+
function handleCancel() {
if (isEditing) {
isEditing = false;
@@ -145,6 +171,13 @@
+ (showRecurrenceDialog = false)}
+/>
+
diff --git a/apps/calendar/apps/web/src/lib/components/event/QuickEventOverlay.svelte b/apps/calendar/apps/web/src/lib/components/event/QuickEventOverlay.svelte
index a7e8b4565..8994167fa 100644
--- a/apps/calendar/apps/web/src/lib/components/event/QuickEventOverlay.svelte
+++ b/apps/calendar/apps/web/src/lib/components/event/QuickEventOverlay.svelte
@@ -3,6 +3,7 @@
import { eventsStore } from '$lib/stores/events.svelte';
import { settingsStore } from '$lib/stores/settings.svelte';
import { contactsStore } from '$lib/stores/contacts.svelte';
+ import RecurrenceEditDialog from './RecurrenceEditDialog.svelte';
import type {
LocationDetails,
CalendarEvent,
@@ -207,6 +208,7 @@
let locationCity = $state('');
let locationCountry = $state('');
let submitting = $state(false);
+ let showRecurrenceDialog = $state(false);
// People state
let responsiblePerson = $state
(null);
@@ -605,6 +607,12 @@
async function handleDelete() {
if (!event) return;
+ // For recurring events, show recurrence dialog
+ if (event.recurrenceRule || eventsStore.isRecurrenceOccurrence(event.id)) {
+ showRecurrenceDialog = true;
+ return;
+ }
+
submitting = true;
try {
const result = await eventsStore.deleteEvent(event.id);
@@ -623,6 +631,26 @@
}
}
+ async function handleRecurrenceDeleteAction(action: 'this' | 'all' | 'this_and_future') {
+ if (!event) return;
+ showRecurrenceDialog = false;
+ submitting = true;
+ try {
+ let result;
+ if (action === 'this') {
+ result = await eventsStore.deleteRecurrenceOccurrence(event.id);
+ } else {
+ result = await eventsStore.deleteRecurrenceSeries(event.id);
+ }
+ if (!result.error) {
+ onDeleted?.();
+ onClose();
+ }
+ } finally {
+ submitting = false;
+ }
+ }
+
function handleKeydown(e: KeyboardEvent) {
if (e.key === 'Escape') {
onClose();
@@ -632,6 +660,13 @@
+ (showRecurrenceDialog = false)}
+/>
+