'use client' import { useTranslations } from 'next-intl' import { useState, useEffect } from 'react' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Label } from '@/components/ui/label' import { Switch } from '@/components/ui/switch' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { useToast } from '@/components/ui/use-toast' import { Badge } from '@/components/ui/badge' import { Calendar, Copy, RefreshCw, Loader2, ExternalLink, Check } from 'lucide-react' import { DestructiveConfirmDialog, useDestructiveConfirm } from '@/components/ui/destructive-confirm-dialog' import type { CalendarFeed } from '@/types' interface CalendarFeedWithUrls extends CalendarFeed { webcalUrl: string httpsUrl: string } export function CalendarFeedSettings() { const t = useTranslations('settings_calendar_feed') const { toast } = useToast() const [isLoading, setIsLoading] = useState(true) const [isSaving, setIsSaving] = useState(false) const [isRegenerating, setIsRegenerating] = useState(false) const [feed, setFeed] = useState(null) const [copied, setCopied] = useState(false) const { dialogProps: confirmDialogProps, confirm: confirmAction } = useDestructiveConfirm() useEffect(() => { fetchFeed() // eslint-disable-next-line react-hooks/exhaustive-deps }, []) const fetchFeed = async () => { setIsLoading(true) const response = await fetch('/api/calendar/feed') const { data } = await response.json() setFeed(data) setIsLoading(false) } const createFeed = async () => { setIsSaving(true) try { const response = await fetch('/api/calendar/feed', { method: 'POST', }) if (!response.ok) { throw new Error('Failed to create feed') } const { data } = await response.json() setFeed(data) toast({ title: t('toast_feed_created_title'), description: t('toast_feed_created_description'), }) } catch { toast({ title: t('toast_create_failed'), variant: 'destructive', }) } finally { setIsSaving(false) } } const updateFeed = async (key: keyof CalendarFeed, value: boolean) => { if (!feed) return setIsSaving(true) try { const response = await fetch('/api/calendar/feed', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ [key]: value }), }) if (!response.ok) { throw new Error('Failed to update feed') } const { data } = await response.json() setFeed(data) } catch { toast({ title: t('toast_update_failed'), variant: 'destructive', }) } finally { setIsSaving(false) } } const regenerateToken = async () => { const ok = await confirmAction({ title: t('regen_dialog_title'), description: t('regen_dialog_description'), confirmLabel: t('regen_confirm'), variant: 'warning', }) if (!ok) return setIsRegenerating(true) try { const response = await fetch('/api/calendar/feed', { method: 'DELETE', }) if (!response.ok) { throw new Error('Failed to regenerate token') } const { data } = await response.json() setFeed(data) toast({ title: t('toast_new_link_title'), description: t('toast_new_link_description'), }) } catch { toast({ title: t('toast_regen_failed'), variant: 'destructive', }) } finally { setIsRegenerating(false) } } const copyToClipboard = async (text: string) => { try { await navigator.clipboard.writeText(text) setCopied(true) setTimeout(() => setCopied(false), 2000) toast({ title: t('toast_copied_title'), description: t('toast_copied_description'), }) } catch { toast({ title: t('toast_copy_failed'), variant: 'destructive', }) } } const openWebcal = () => { if (feed?.webcalUrl) { window.location.href = feed.webcalUrl } } if (isLoading) { return (
) } if (!feed) { return ( {t('title')} {t('description')}

{t('empty_intro')}

) } return (
{/* Feed URL */} {t('title')} {t('subscribe_description')} {/* Quick add for Apple Calendar */}
{/* URL display */}

{t('calendar_link_help')}

{/* Stats */} {feed.last_accessed_at && (
{t('last_fetched')} {new Date(feed.last_accessed_at).toLocaleDateString('sv-SE', { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit', })} {t('times_count', { count: feed.access_count })}
)} {/* Regenerate link */}

{t('regen_help')}

{/* Content settings */} {t('content_title')} {t('content_description')}

{t('tax_deadlines_help')}

updateFeed('include_tax_deadlines', checked) } disabled={isSaving} />

{t('invoices_help')}

updateFeed('include_invoices', checked) } disabled={isSaving} />
) }