diff --git a/apps/calendar/apps/web/src/lib/components/settings/CalendarManagement.svelte b/apps/calendar/apps/web/src/lib/components/settings/CalendarManagement.svelte new file mode 100644 index 000000000..ed352d35a --- /dev/null +++ b/apps/calendar/apps/web/src/lib/components/settings/CalendarManagement.svelte @@ -0,0 +1,501 @@ + + +
+
+ +
+ + {#if showNewCalendarForm} +
+
{ + e.preventDefault(); + handleCreateCalendar(); + }} + > +
+ + +
+
+ + +
+
+
+ {/if} + +
+ {#each calendars as calendar} + {#if editingCalendar?.id === calendar.id} +
+
{ + e.preventDefault(); + handleUpdateCalendar(); + }} + > +
+
+ + +
+ +
+ +
+ + {editColor} +
+
+
+ + + +
+ + +
+
+
+ {:else} +
+
+ + {calendar.name} + {#if calendar.isDefault} + {$_('settings.default')} + {/if} +
+
+ + {#if !calendar.isDefault} + + {/if} +
+
+ {/if} + {/each} + + {#if calendars.length === 0} +
+

{$_('settings.noCalendars')}

+
+ {/if} +
+
+ + diff --git a/apps/calendar/apps/web/src/lib/components/settings/SettingsModal.svelte b/apps/calendar/apps/web/src/lib/components/settings/SettingsModal.svelte index 852fde7e1..8990caeb9 100644 --- a/apps/calendar/apps/web/src/lib/components/settings/SettingsModal.svelte +++ b/apps/calendar/apps/web/src/lib/components/settings/SettingsModal.svelte @@ -6,26 +6,15 @@ import { settingsStore } from '$lib/stores/settings.svelte'; import type { TimeFormat, AllDayDisplayMode, SttLanguage } from '$lib/stores/settings.svelte'; import { getContext } from 'svelte'; - import { calendarsStore } from '$lib/stores/calendars.svelte'; - import { getDefaultCalendar } from '$lib/data/queries'; + import CalendarManagement from '$lib/components/settings/CalendarManagement.svelte'; import { - toastStore as toast, GlobalSettingsSection, SettingsSection, SettingsCard, FilterDropdown, type FilterDropdownOption, } from '@manacore/shared-ui'; - import { - X, - CalendarBlank, - Plus, - Eye, - Clock, - Microphone, - Cake, - User, - } from '@manacore/shared-icons'; + import { X, CalendarBlank, Eye, Clock, Microphone, Cake, User } from '@manacore/shared-icons'; import { focusTrap } from '@manacore/shared-ui'; import type { CalendarViewType, Calendar } from '@calendar/shared'; @@ -39,93 +28,6 @@ // Get calendars from layout context (live query) const calendarsCtx: { readonly value: Calendar[] } = getContext('calendars'); - // Calendar management state - let editingCalendar = $state(null); - let editName = $state(''); - let editColor = $state(''); - let editIsDefault = $state(false); - let showNewCalendarForm = $state(false); - let newCalendarName = $state(''); - let newCalendarColor = $state('#3b82f6'); - - function startEditing(calendar: Calendar) { - editingCalendar = calendar; - editName = calendar.name; - editColor = calendar.color || '#3b82f6'; - editIsDefault = calendar.isDefault || false; - } - - function cancelEditing() { - editingCalendar = null; - editName = ''; - editColor = ''; - editIsDefault = false; - } - - // Calendar management functions - async function handleCreateCalendar() { - if (!newCalendarName.trim()) return; - - const result = await calendarsStore.createCalendar({ - name: newCalendarName.trim(), - color: newCalendarColor, - }); - - if (result.error) { - toast.error(`Fehler: ${result.error.message}`); - return; - } - - toast.success('Kalender erstellt'); - newCalendarName = ''; - showNewCalendarForm = false; - } - - async function handleDeleteCalendar(calendar: Calendar) { - if (!confirm(`Möchten Sie "${calendar.name}" wirklich löschen?`)) { - return; - } - - const result = await calendarsStore.deleteCalendar(calendar.id); - - if (result.error) { - toast.error(`Fehler: ${result.error.message}`); - return; - } - - toast.success('Kalender gelöscht'); - } - - async function handleUpdateCalendar() { - if (!editingCalendar || !editName.trim()) return; - - // If setting as default and it wasn't before, use setAsDefault - if (editIsDefault && !editingCalendar.isDefault) { - const defaultResult = await calendarsStore.setAsDefault( - editingCalendar.id, - calendarsCtx.value - ); - if (defaultResult?.error) { - toast.error(`Fehler: ${defaultResult.error.message}`); - return; - } - } - - // Update name and color - const result = await calendarsStore.updateCalendar(editingCalendar.id, { - name: editName.trim(), - color: editColor, - }); - - if (result.error) { - toast.error(`Fehler: ${result.error.message}`); - return; - } - - toast.success('Kalender aktualisiert'); - cancelEditing(); - } - function handleViewChange(view: CalendarViewType) { settingsStore.set('defaultView', view); } @@ -250,145 +152,7 @@ {/snippet}
-
- -
- - {#if showNewCalendarForm} -
-
{ - e.preventDefault(); - handleCreateCalendar(); - }} - > -
- - -
-
- - -
-
-
- {/if} - -
- {#each calendarsCtx.value as calendar} - {#if editingCalendar?.id === calendar.id} -
-
{ - e.preventDefault(); - handleUpdateCalendar(); - }} - > -
-
- - -
- -
- -
- - {editColor} -
-
-
- - - -
- - -
-
-
- {:else} -
-
- - {calendar.name} - {#if calendar.isDefault} - Standard - {/if} -
-
- - {#if !calendar.isDefault} - - {/if} -
-
- {/if} - {/each} - - {#if calendarsCtx.value.length === 0} -
-

Keine Kalender vorhanden

-
- {/if} -
+
@@ -932,286 +696,6 @@ margin-top: 1rem; } - /* Calendar management styles */ - .calendars-toolbar { - display: flex; - justify-content: flex-end; - margin-bottom: 0.75rem; - } - - .new-calendar-form { - margin-bottom: 0.75rem; - padding: 0.75rem; - background: hsl(var(--color-muted) / 0.3); - border-radius: var(--radius-md); - } - - .calendar-form-row { - display: flex; - gap: 0.5rem; - margin-bottom: 0.75rem; - } - - .calendar-form-row .input { - flex: 1; - padding: 0.5rem 0.75rem; - border: 1px solid hsl(var(--color-border)); - border-radius: var(--radius-md); - background: hsl(var(--color-background)); - font-size: 0.875rem; - } - - .color-input { - width: 40px; - height: 36px; - padding: 2px; - border: 2px solid hsl(var(--color-border)); - border-radius: var(--radius-md); - cursor: pointer; - } - - .calendar-form-actions { - display: flex; - justify-content: flex-end; - gap: 0.375rem; - } - - .calendar-list { - display: flex; - flex-direction: column; - gap: 0.375rem; - } - - .calendar-card { - display: flex; - align-items: center; - justify-content: space-between; - padding: 0.5rem 0.75rem; - background: hsl(var(--color-muted) / 0.2); - border-radius: var(--radius-md); - } - - /* Edit form styles */ - .calendar-edit-form { - padding: 1rem; - background: hsl(var(--color-card)); - border: 1px solid hsl(var(--color-border)); - border-radius: var(--radius-lg); - box-shadow: 0 2px 8px hsl(var(--color-foreground) / 0.08); - } - - .edit-form-row { - display: flex; - gap: 0.75rem; - margin-bottom: 0.75rem; - } - - .edit-form-group { - display: flex; - flex-direction: column; - gap: 0.375rem; - } - - .edit-form-group--name { - flex: 1; - } - - .edit-form-group--color { - flex-shrink: 0; - } - - .edit-label { - font-size: 0.75rem; - font-weight: 600; - color: hsl(var(--color-foreground)); - text-transform: uppercase; - letter-spacing: 0.025em; - } - - .edit-input { - width: 100%; - padding: 0.5rem 0.75rem; - font-size: 0.875rem; - color: hsl(var(--color-foreground)); - background: hsl(var(--color-background)); - border: 2px solid hsl(var(--color-border)); - border-radius: var(--radius-md); - outline: none; - transition: - border-color 150ms ease, - box-shadow 150ms ease; - } - - .edit-input:hover { - border-color: hsl(var(--color-muted-foreground) / 0.5); - } - - .edit-input:focus { - border-color: hsl(var(--color-primary)); - box-shadow: 0 0 0 3px hsl(var(--color-primary) / 0.15); - } - - .edit-color-wrapper { - display: flex; - align-items: center; - gap: 0.5rem; - padding: 0.25rem 0.5rem 0.25rem 0.25rem; - background: hsl(var(--color-background)); - border: 2px solid hsl(var(--color-border)); - border-radius: var(--radius-md); - transition: border-color 150ms ease; - } - - .edit-color-input { - width: 28px; - height: 28px; - padding: 0; - border: none; - border-radius: var(--radius-sm); - cursor: pointer; - background: transparent; - } - - .edit-color-input::-webkit-color-swatch-wrapper { - padding: 0; - } - - .edit-color-input::-webkit-color-swatch { - border: none; - border-radius: var(--radius-sm); - } - - .edit-color-value { - font-size: 0.75rem; - font-family: monospace; - color: hsl(var(--color-muted-foreground)); - text-transform: uppercase; - } - - .edit-checkbox { - display: flex; - align-items: center; - gap: 0.5rem; - padding: 0.5rem; - margin-bottom: 0.75rem; - background: hsl(var(--color-muted) / 0.3); - border-radius: var(--radius-md); - cursor: pointer; - transition: background 150ms ease; - font-size: 0.8125rem; - } - - .edit-checkbox:hover { - background: hsl(var(--color-muted) / 0.5); - } - - .edit-checkbox input[type='checkbox'] { - width: 1rem; - height: 1rem; - accent-color: hsl(var(--color-primary)); - cursor: pointer; - } - - .edit-checkbox-text { - font-size: 0.8125rem; - color: hsl(var(--color-foreground)); - } - - .edit-checkbox-hint { - color: hsl(var(--color-muted-foreground)); - font-style: italic; - margin-left: 0.25rem; - } - - .edit-form-actions { - display: flex; - justify-content: flex-end; - gap: 0.375rem; - padding-top: 0.75rem; - border-top: 1px solid hsl(var(--color-border)); - } - - .calendar-info { - display: flex; - align-items: center; - gap: 0.5rem; - } - - .color-dot { - width: 14px; - height: 14px; - border-radius: var(--radius-full); - } - - .calendar-name { - font-weight: 500; - font-size: 0.875rem; - } - - .badge { - font-size: 0.6875rem; - padding: 0.125rem 0.375rem; - background: hsl(var(--color-muted)); - border-radius: var(--radius-sm); - color: hsl(var(--color-muted-foreground)); - } - - .badge-primary { - background: hsl(var(--color-primary) / 0.15); - color: hsl(var(--color-primary)); - font-weight: 500; - } - - .calendar-actions { - display: flex; - gap: 0.375rem; - } - - .btn { - padding: 0.375rem 0.75rem; - font-size: 0.8125rem; - font-weight: 500; - border-radius: var(--radius-md); - cursor: pointer; - transition: all 150ms ease; - border: none; - } - - .btn-ghost { - background: transparent; - color: hsl(var(--color-foreground)); - } - - .btn-ghost:hover { - background: hsl(var(--color-muted) / 0.5); - } - - .btn-primary { - background: hsl(var(--color-primary)); - color: hsl(var(--color-primary-foreground)); - } - - .btn-primary:hover { - background: hsl(var(--color-primary) / 0.9); - } - - .btn-primary:disabled { - opacity: 0.5; - cursor: not-allowed; - } - - .btn-sm { - padding: 0.25rem 0.5rem; - font-size: 0.75rem; - } - - .empty-state { - text-align: center; - padding: 1rem; - color: hsl(var(--color-muted-foreground)); - font-size: 0.875rem; - } - /* Birthday age setting (indented sub-setting) */ .birthday-age-setting { padding-left: 1.5rem; diff --git a/apps/calendar/apps/web/src/routes/(app)/settings/+page.svelte b/apps/calendar/apps/web/src/routes/(app)/settings/+page.svelte index bee91c774..07a3f76ec 100644 --- a/apps/calendar/apps/web/src/routes/(app)/settings/+page.svelte +++ b/apps/calendar/apps/web/src/routes/(app)/settings/+page.svelte @@ -7,10 +7,8 @@ import { settingsStore } from '$lib/stores/settings.svelte'; import type { TimeFormat, AllDayDisplayMode } from '$lib/stores/settings.svelte'; import { getContext } from 'svelte'; - import { calendarsStore } from '$lib/stores/calendars.svelte'; - import { getDefaultCalendar } from '$lib/data/queries'; + import CalendarManagement from '$lib/components/settings/CalendarManagement.svelte'; import { - toastStore as toast, GlobalSettingsSection, SettingsSection, SettingsCard, @@ -21,7 +19,6 @@ import type { CalendarViewType, Calendar } from '@calendar/shared'; import { CalendarBlank, - Plus, ArrowsClockwise, UsersThree, Eye, @@ -34,29 +31,6 @@ // Get calendars from layout context (live query) const calendarsCtx: { readonly value: Calendar[] } = getContext('calendars'); - // Calendar management state - let editingCalendar = $state(null); - let editName = $state(''); - let editColor = $state(''); - let editIsDefault = $state(false); - let showNewCalendarForm = $state(false); - let newCalendarName = $state(''); - let newCalendarColor = $state('#3b82f6'); - - function startEditing(calendar: Calendar) { - editingCalendar = calendar; - editName = calendar.name; - editColor = calendar.color || '#3b82f6'; - editIsDefault = calendar.isDefault || false; - } - - function cancelEditing() { - editingCalendar = null; - editName = ''; - editColor = ''; - editIsDefault = false; - } - onMount(async () => { if (!authStore.isAuthenticated) { goto('/login'); @@ -66,70 +40,6 @@ await userSettings.load(); }); - // Calendar management functions - async function handleCreateCalendar() { - if (!newCalendarName.trim()) return; - - const result = await calendarsStore.createCalendar({ - name: newCalendarName.trim(), - color: newCalendarColor, - }); - - if (result.error) { - toast.error(`${$_('common.error')}: ${result.error.message}`); - return; - } - - toast.success($_('settings.calendarCreated')); - newCalendarName = ''; - showNewCalendarForm = false; - } - - async function handleDeleteCalendar(calendar: Calendar) { - if (!confirm($_('settings.confirmDeleteCalendar', { values: { name: calendar.name } }))) { - return; - } - - const result = await calendarsStore.deleteCalendar(calendar.id); - - if (result.error) { - toast.error(`${$_('common.error')}: ${result.error.message}`); - return; - } - - toast.success($_('settings.calendarDeleted')); - } - - async function handleUpdateCalendar() { - if (!editingCalendar || !editName.trim()) return; - - // If setting as default and it wasn't before, use setAsDefault - if (editIsDefault && !editingCalendar.isDefault) { - const defaultResult = await calendarsStore.setAsDefault( - editingCalendar.id, - calendarsCtx.value - ); - if (defaultResult?.error) { - toast.error(`${$_('common.error')}: ${defaultResult.error.message}`); - return; - } - } - - // Update name and color - const result = await calendarsStore.updateCalendar(editingCalendar.id, { - name: editName.trim(), - color: editColor, - }); - - if (result.error) { - toast.error(`${$_('common.error')}: ${result.error.message}`); - return; - } - - toast.success($_('settings.calendarUpdated')); - cancelEditing(); - } - function handleViewChange(view: CalendarViewType) { settingsStore.set('defaultView', view); } @@ -225,141 +135,7 @@ {/snippet}
-
- -
- - {#if showNewCalendarForm} -
-
{ - e.preventDefault(); - handleCreateCalendar(); - }} - > -
- - -
-
- - -
-
-
- {/if} - -
- {#each calendarsCtx.value as calendar} - {#if editingCalendar?.id === calendar.id} -
-
{ - e.preventDefault(); - handleUpdateCalendar(); - }} - > -
-
- - -
- -
- -
- - {editColor} -
-
-
- - - -
- - -
-
-
- {:else} -
-
- - {calendar.name} - {#if calendar.isDefault} - {$_('settings.default')} - {/if} -
-
- - {#if !calendar.isDefault} - - {/if} -
-
- {/if} - {/each} - - {#if calendarsCtx.value.length === 0} -
-

{$_('settings.noCalendars')}

-
- {/if} -
+
@@ -698,12 +474,6 @@ margin: 0; } - .calendars-toolbar { - display: flex; - justify-content: flex-end; - margin-bottom: 1rem; - } - .setting-item { padding: 1rem 0; border-bottom: 1px solid hsl(var(--color-border) / 0.5); @@ -831,262 +601,6 @@ margin-top: 1.25rem; } - /* Calendar management styles */ - .new-calendar-form { - margin-bottom: 1rem; - padding: 1rem; - background: hsl(var(--color-muted) / 0.3); - border-radius: var(--radius-md); - } - - .calendar-form-row { - display: flex; - gap: 0.75rem; - margin-bottom: 1rem; - } - - .calendar-form-row .input { - flex: 1; - } - - .color-input { - width: 48px; - height: 42px; - padding: 4px; - border: 2px solid hsl(var(--color-border)); - border-radius: var(--radius-md); - cursor: pointer; - } - - .calendar-form-actions { - display: flex; - justify-content: flex-end; - gap: 0.5rem; - } - - .calendar-list { - display: flex; - flex-direction: column; - gap: 0.5rem; - } - - .calendar-card { - display: flex; - align-items: center; - justify-content: space-between; - padding: 0.75rem; - background: hsl(var(--color-muted) / 0.2); - border-radius: var(--radius-md); - } - - /* Edit form styles */ - .calendar-edit-form { - padding: 1.25rem; - background: hsl(var(--color-card)); - border: 1px solid hsl(var(--color-border)); - border-radius: var(--radius-lg); - box-shadow: 0 2px 8px hsl(var(--color-foreground) / 0.08); - } - - .edit-form-row { - display: flex; - gap: 1rem; - margin-bottom: 1rem; - } - - .edit-form-group { - display: flex; - flex-direction: column; - gap: 0.5rem; - } - - .edit-form-group--name { - flex: 1; - } - - .edit-form-group--color { - flex-shrink: 0; - } - - .edit-label { - font-size: 0.8125rem; - font-weight: 600; - color: hsl(var(--color-foreground)); - text-transform: uppercase; - letter-spacing: 0.025em; - } - - .edit-input { - width: 100%; - padding: 0.625rem 0.875rem; - font-size: 0.9375rem; - color: hsl(var(--color-foreground)); - background: hsl(var(--color-background)); - border: 2px solid hsl(var(--color-border)); - border-radius: var(--radius-md); - outline: none; - transition: - border-color 150ms ease, - box-shadow 150ms ease; - } - - .edit-input:hover { - border-color: hsl(var(--color-muted-foreground) / 0.5); - } - - .edit-input:focus { - border-color: hsl(var(--color-primary)); - box-shadow: 0 0 0 3px hsl(var(--color-primary) / 0.15); - } - - .edit-input::placeholder { - color: hsl(var(--color-muted-foreground) / 0.7); - } - - .edit-color-wrapper { - display: flex; - align-items: center; - gap: 0.625rem; - padding: 0.375rem 0.625rem 0.375rem 0.375rem; - background: hsl(var(--color-background)); - border: 2px solid hsl(var(--color-border)); - border-radius: var(--radius-md); - transition: border-color 150ms ease; - } - - .edit-color-wrapper:hover { - border-color: hsl(var(--color-muted-foreground) / 0.5); - } - - .edit-color-wrapper:focus-within { - border-color: hsl(var(--color-primary)); - box-shadow: 0 0 0 3px hsl(var(--color-primary) / 0.15); - } - - .edit-color-input { - width: 32px; - height: 32px; - padding: 0; - border: none; - border-radius: var(--radius-sm); - cursor: pointer; - background: transparent; - } - - .edit-color-input::-webkit-color-swatch-wrapper { - padding: 0; - } - - .edit-color-input::-webkit-color-swatch { - border: none; - border-radius: var(--radius-sm); - } - - .edit-color-input::-moz-color-swatch { - border: none; - border-radius: var(--radius-sm); - } - - .edit-color-value { - font-size: 0.8125rem; - font-family: monospace; - color: hsl(var(--color-muted-foreground)); - text-transform: uppercase; - } - - .edit-checkbox { - display: flex; - align-items: center; - gap: 0.75rem; - padding: 0.75rem; - margin-bottom: 1rem; - background: hsl(var(--color-muted) / 0.3); - border-radius: var(--radius-md); - cursor: pointer; - transition: background 150ms ease; - } - - .edit-checkbox:hover { - background: hsl(var(--color-muted) / 0.5); - } - - .edit-checkbox input[type='checkbox'] { - width: 1.125rem; - height: 1.125rem; - accent-color: hsl(var(--color-primary)); - cursor: pointer; - } - - .edit-checkbox input[type='checkbox']:disabled { - opacity: 0.5; - cursor: not-allowed; - } - - .edit-checkbox-text { - font-size: 0.875rem; - color: hsl(var(--color-foreground)); - } - - .edit-checkbox-hint { - color: hsl(var(--color-muted-foreground)); - font-style: italic; - margin-left: 0.25rem; - } - - .edit-form-actions { - display: flex; - justify-content: flex-end; - gap: 0.5rem; - padding-top: 1rem; - border-top: 1px solid hsl(var(--color-border)); - } - - .calendar-info { - display: flex; - align-items: center; - gap: 0.75rem; - } - - .color-dot { - width: 16px; - height: 16px; - border-radius: var(--radius-full); - } - - .calendar-name { - font-weight: 500; - } - - .badge { - font-size: 0.75rem; - padding: 0.125rem 0.5rem; - background: hsl(var(--color-muted)); - border-radius: var(--radius-sm); - color: hsl(var(--color-muted-foreground)); - } - - .badge-primary { - background: hsl(var(--color-primary) / 0.15); - color: hsl(var(--color-primary)); - font-weight: 500; - } - - .calendar-actions { - display: flex; - gap: 0.5rem; - } - - .btn-sm { - padding: 0.25rem 0.75rem; - font-size: 0.875rem; - } - - .empty-state { - text-align: center; - padding: 1.5rem; - color: hsl(var(--color-muted-foreground)); - } - /* Birthday age setting (indented sub-setting) */ .birthday-age-setting { padding-left: 2rem;