"use client"; import { useState, useRef, useEffect, useCallback } from "react"; import { useTranslations } from "next-intl"; import { Button } from "@/components/ui/button"; import { X, Loader2, Globe } from "lucide-react"; import type { IJMAPClient } from '@/lib/jmap/client-interface'; import { useCalendarStore } from "@/stores/calendar-store"; import { CalendarColorPicker } from "@/components/settings/calendar-management-settings"; import { toast } from "@/stores/toast-store"; interface ICalSubscriptionModalProps { client: IJMAPClient; onClose: () => void; } export function ICalSubscriptionModal({ client, onClose }: ICalSubscriptionModalProps) { const t = useTranslations("calendar.subscription"); const tCommon = useTranslations("common"); const addICalSubscription = useCalendarStore((s) => s.addICalSubscription); const [url, setUrl] = useState(""); const [name, setName] = useState(""); const [color, setColor] = useState("#3b82f6"); const [refreshInterval, setRefreshInterval] = useState(60); const [isSubmitting, setIsSubmitting] = useState(false); const [error, setError] = useState(null); const modalRef = useRef(null); const isValid = url.trim().length > 0 && name.trim().length > 0; const handleSubmit = useCallback(async () => { let trimmedUrl = url.trim(); if (!trimmedUrl || !name.trim()) return; // Convert webcal:// to https:// if (trimmedUrl.startsWith("webcal://")) { trimmedUrl = trimmedUrl.replace(/^webcal:\/\//, "https://"); } try { new URL(trimmedUrl); } catch { setError(t("invalid_url")); return; } setError(null); setIsSubmitting(true); try { const subscription = await addICalSubscription(client, trimmedUrl, name.trim(), color, refreshInterval); if (subscription) { toast.success(t("success", { name: name.trim() })); onClose(); } else { setError(t("error")); } } catch { setError(t("error")); } finally { setIsSubmitting(false); } }, [url, name, color, refreshInterval, client, addICalSubscription, onClose, t]); useEffect(() => { const handleKey = (e: KeyboardEvent) => { if (e.key === "Escape") onClose(); }; window.addEventListener("keydown", handleKey); return () => window.removeEventListener("keydown", handleKey); }, [onClose]); useEffect(() => { const modal = modalRef.current; if (!modal) return; const focusableEls = modal.querySelectorAll( 'input, select, textarea, button, [tabindex]:not([tabindex="-1"])' ); const firstEl = focusableEls[0]; const lastEl = focusableEls[focusableEls.length - 1]; const handler = (e: KeyboardEvent) => { if (e.key !== "Tab") return; if (e.shiftKey && document.activeElement === firstEl) { e.preventDefault(); lastEl?.focus(); } else if (!e.shiftKey && document.activeElement === lastEl) { e.preventDefault(); firstEl?.focus(); } }; modal.addEventListener("keydown", handler); firstEl?.focus(); return () => modal.removeEventListener("keydown", handler); }, []); return (
); }