diff --git a/public/locales/de.json b/public/locales/de.json index dd9025c..29466b8 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -1010,7 +1010,12 @@ "caldavRefreshCalendars": "Kalender aktualisieren", "caldavSyncSuccess": "CalDAV-Synchronisation erfolgreich", "caldavSyncFailed": "CalDAV-Synchronisation fehlgeschlagen", - "caldavConnectionFailed": "Verbindung zum CalDAV-Server fehlgeschlagen" + "caldavConnectionFailed": "Verbindung zum CalDAV-Server fehlgeschlagen", + "calendarEnabled": "Kalender aktiviert", + "calendarDisabled": "Kalender deaktiviert", + "calendarsRefreshed": "Kalender aktualisiert", + "deleteAccountConfirm": "CalDAV-Konto wirklich löschen? Alle synchronisierten Kalender werden entfernt.", + "lastSync": "Zuletzt synchronisiert" }, "login": { "tagline": "Familienplanung. Sicher. Datenschutzfreundlich. Open Source.", diff --git a/public/pages/calendar.js b/public/pages/calendar.js index 5611262..190ce48 100644 --- a/public/pages/calendar.js +++ b/public/pages/calendar.js @@ -1253,6 +1253,59 @@ function bindTimeInputs(root) { }); } +// -------------------------------------------------------- +// CalDAV Target Helpers +// -------------------------------------------------------- + +async function loadCalDAVTargets(selectElement, currentEvent = null) { + if (!selectElement) return; + + try { + const accountsRes = await api.get('/calendar/caldav/accounts'); + const accounts = accountsRes.data || []; + + // Keep only the "local" option + selectElement.replaceChildren(); + const localOption = document.createElement('option'); + localOption.value = ''; + localOption.textContent = t('calendar.caldavTargetLocal'); + selectElement.appendChild(localOption); + + // Load calendars for each account and build options + for (const account of accounts) { + try { + const calendarsRes = await api.get(`/calendar/caldav/accounts/${account.id}/calendars`); + const calendars = calendarsRes.data || []; + const enabledCalendars = calendars.filter((cal) => cal.enabled); + + if (enabledCalendars.length === 0) continue; + + const optgroup = document.createElement('optgroup'); + optgroup.label = account.name; + + for (const calendar of enabledCalendars) { + const option = document.createElement('option'); + option.value = `${account.id}|${calendar.url}`; + option.textContent = calendar.display_name || calendar.url; + optgroup.appendChild(option); + } + + selectElement.appendChild(optgroup); + } catch (err) { + console.warn(`Failed to load calendars for account ${account.id}:`, err); + } + } + + // Pre-select current event's target if editing + if (currentEvent?.target_caldav_account_id && currentEvent?.target_caldav_calendar_url) { + const targetValue = `${currentEvent.target_caldav_account_id}|${currentEvent.target_caldav_calendar_url}`; + selectElement.value = targetValue; + } + } catch (err) { + console.warn('Failed to load CalDAV targets:', err); + } +} + // -------------------------------------------------------- // Event-Modal (Erstellen / Bearbeiten) // -------------------------------------------------------- @@ -1465,6 +1518,12 @@ function openEventModal({ mode, event = null, date = null, reminder = null }) { if (reminderCustom) reminderCustom.hidden = reminderOffset.value !== 'custom'; }); + // Load CalDAV targets + const caldavTargetSelect = panel.querySelector('#event-caldav-target'); + if (caldavTargetSelect) { + loadCalDAVTargets(caldavTargetSelect, event); + } + panel.querySelector('#modal-cancel').addEventListener('click', closeModal); panel.querySelector('#modal-delete')?.addEventListener('click', async () => { @@ -1611,6 +1670,14 @@ function buildEventModalContent({ mode, event, date, reminder = null }) { +
${t('settings.caldavDescription')}
+ + + + + ${user?.role === 'admin' ? ` + + ` : ''} +