'use client'; import { useTranslations } from 'next-intl'; import { useEffect, useMemo, useState } from 'react'; import { useQuery } from '@tanstack/react-query'; import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { ProxyRouteService } from '@/lib/services/openflare'; type UptimeKumaSiteSelectModalProps = { open: boolean; selectedSites: string[]; onOpenChange: (open: boolean) => void; onSave: (sites: string[]) => void; }; export function UptimeKumaSiteSelectModal({ open, selectedSites, onOpenChange, onSave, }: UptimeKumaSiteSelectModalProps) { const t = useTranslations('openflareOps.siteModal'); const tCommon = useTranslations('common'); const [searchTerm, setSearchTerm] = useState(''); const [tempSelected, setTempSelected] = useState>(new Set()); const routesQuery = useQuery({ queryKey: ['openflare', 'proxy-routes'], queryFn: () => ProxyRouteService.list(), enabled: open, }); useEffect(() => { if (!open) return; setTempSelected( new Set(selectedSites.map((site) => site.trim()).filter(Boolean)), ); setSearchTerm(''); }, [open, selectedSites]); const filteredRoutes = useMemo(() => { const routes = routesQuery.data ?? []; const keyword = searchTerm.trim().toLowerCase(); if (!keyword) return routes; return routes.filter((route) => { const domains = (route.zone_domains ?? []) .map((item) => item.domain) .join(' '); return ( route.site_name.toLowerCase().includes(keyword) || domains.toLowerCase().includes(keyword) ); }); }, [routesQuery.data, searchTerm]); const toggleSite = (siteName: string) => { setTempSelected((previous) => { const next = new Set(previous); if (next.has(siteName)) next.delete(siteName); else next.add(siteName); return next; }); }; const handleSelectAll = () => { setTempSelected((previous) => { const next = new Set(previous); filteredRoutes.forEach((route) => next.add(route.site_name)); return next; }); }; const handleDeselectAll = () => { setTempSelected((previous) => { const next = new Set(previous); filteredRoutes.forEach((route) => next.delete(route.site_name)); return next; }); }; return ( {t('title')} {t('description')}
setSearchTerm(event.target.value)} placeholder={t('searchPlaceholder')} />
{routesQuery.isLoading ? (

{t('loading')}

) : routesQuery.isError ? (

{routesQuery.error instanceof Error ? routesQuery.error.message : t('loadFailed')}

) : filteredRoutes.length === 0 ? (

{t('noMatch')}

) : ( {filteredRoutes.map((route) => { const checked = tempSelected.has(route.site_name); return ( toggleSite(route.site_name)} > ); })}
{t('select')} {t('siteName')} {t('primaryDomain')}
event.stopPropagation()} > toggleSite(route.site_name)} className='size-4 rounded border-input' /> {route.site_name} {(route.zone_domains ?? []) .map((item) => item.domain) .join(', ') || '—'}
)}

{t('selectedCount', { count: tempSelected.size })}

); }