'use client'; /** * Modal zum Bearbeiten eines Kalenders (PATCH /api/calendars/[id]) * inkl. Mitgliederverwaltung (DB-Suche) und Reservierungsregeln. * * Einstellungen: * - Titel, Beschreibung, Zeitzone, Aktiv-Status * - Maximale Reservierungsdauer (15-Minuten-Schritte, 0 = unbegrenzt) * - Sichtbarkeit von Titel/Notizen fremder Reservierungen fuer Member * - Mitglieder per E-Mail-Suche hinzufuegen/entfernen * * Selbststaendig: fuehrt den PATCH selbst aus und aktualisiert die * Seite per router.refresh(). Wird von der Kalenderverwaltung und vom * Dashboard verwendet (DRY). Schliessen via X-Icon, ESC oder * Hintergrund-Klick; waehrend des Speicherns ist Schliessen blockiert. */ import { appFetch } from '@/lib/client-fetch'; import { useState } from 'react'; import { useRouter } from 'next/navigation'; import { Button, ErrorMessage, Input, Label } from '@/components/ui/ui'; import { ModalShell } from '@/components/ui/ModalShell'; import { MemberSection } from '@/components/admin/MemberSection'; import type { ManagedCalendar } from '@/components/admin/CalendarManager'; /** Auswahl der maximalen Reservierungsdauer in Minuten. */ const MAX_DURATION_OPTIONS = [ { value: 30, label: '30 Minuten' }, { value: 45, label: '45 Minuten' }, { value: 60, label: '1 Stunde' }, { value: 90, label: '1,5 Stunden' }, { value: 120, label: '2 Stunden' }, { value: 180, label: '3 Stunden' }, { value: 240, label: '4 Stunden' }, { value: 480, label: '8 Stunden' }, { value: 720, label: '12 Stunden' }, { value: 1440, label: '24 Stunden' }, { value: 2880, label: '48 Stunden' }, { value: 4320, label: '72 Stunden' }, { value: 0, label: 'Unbegrenzt' }, ] as const; export function EditCalendarModal({ calendar, isAdmin = true, onClose, }: { calendar: ManagedCalendar; /** Nur Admins sehen Einstellungen und Mitgliederverwaltung. */ isAdmin?: boolean; onClose: () => void; }) { const router = useRouter(); const [isPending, setIsPending] = useState(false); const [error, setError] = useState(null); /** Sendet die Formularwerte an PATCH /api/calendars/[id]. */ async function handleSubmit(event: React.FormEvent) { event.preventDefault(); setIsPending(true); setError(null); const formData = new FormData(event.currentTarget); try { const response = await appFetch(`/api/calendars/${calendar.id}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: String(formData.get('title') ?? '').trim(), description: String(formData.get('description') ?? '').trim() || null, timezone: String(formData.get('timezone') ?? '').trim(), isActive: formData.get('isActive') === 'on', maxReservationMinutes: Number(formData.get('maxReservationMinutes')), showTitleToMembers: formData.get('showTitleToMembers') === 'on', showNotesToMembers: formData.get('showNotesToMembers') === 'on', }), }); if (!response.ok) { const data = (await response.json().catch(() => ({}))) as { error?: string }; setError(data.error ?? 'Speichern fehlgeschlagen.'); return; } router.refresh(); onClose(); } catch { setError('Netzwerkfehler. Bitte erneut versuchen.'); } finally { setIsPending(false); } } return (
{/* Reservierungsregeln. */}
Reservierungsregeln

Ohne Haken sehen Member nur ihre eigenen Titel/Notizen; fremde Reservierungen erscheinen als "Gebucht".

{calendar.memberCount} Mitglieder · {calendar.reservationCount} Reservierungen

{isAdmin && (
)} {/* Aktionsleiste unten im Modal (ausserhalb des Formulars; der Speichern-Button ist via form-Attribut mit dem Formular verbunden und loest dessen Submit aus). */}
); }