'use client'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useMemo, useState } from 'react'; import Link from 'next/link'; import { useForm } from 'react-hook-form'; import { EmptyState } from '@/components/feedback/empty-state'; import { ErrorState } from '@/components/feedback/error-state'; import { InlineMessage } from '@/components/feedback/inline-message'; import { LoadingState } from '@/components/feedback/loading-state'; import { PageHeader } from '@/components/layout/page-header'; import { AppCard } from '@/components/ui/app-card'; import { AppModal } from '@/components/ui/app-modal'; import { deleteDnsAccount, getDnsAccounts, createDnsAccount, } from '@/features/dns-accounts/api/dns-accounts'; import type { DnsAccountItem } from '@/features/dns-accounts/types'; import { getErrorMessage } from '@/features/websites/utils'; import { DangerButton, PrimaryButton, ResourceField, ResourceInput, ResourceSelect, } from '@/features/shared/components/resource-primitives'; import { formatDateTime } from '@/lib/utils/date'; export function DnsAccountsPage() { const queryClient = useQueryClient(); const [feedback, setFeedback] = useState<{ tone: 'info' | 'success' | 'danger'; message: string; } | null>(null); const [isCreateOpen, setIsCreateOpen] = useState(false); const dnsAccountsQuery = useQuery({ queryKey: ['dns-accounts'], queryFn: getDnsAccounts, }); const deleteMutation = useMutation({ mutationFn: deleteDnsAccount, onSuccess: async () => { setFeedback({ tone: 'success', message: 'DNS 账号已删除。' }); await queryClient.invalidateQueries({ queryKey: ['dns-accounts'] }); }, onError: (error) => { setFeedback({ tone: 'danger', message: getErrorMessage(error) }); }, }); const handleDelete = (account: DnsAccountItem) => { if (!window.confirm(`确认删除 DNS 账号 ${account.name} 吗?`)) { return; } setFeedback(null); deleteMutation.mutate(account.id); }; const accounts = useMemo( () => dnsAccountsQuery.data ?? [], [dnsAccountsQuery.data], ); return ( <>
返回 setIsCreateOpen(true)} > 添加账号
} /> {feedback ? ( ) : null} {dnsAccountsQuery.isLoading ? ( ) : dnsAccountsQuery.isError ? ( ) : accounts.length === 0 ? ( ) : (
{accounts.map((account) => (

{account.name}{' '} ({account.type})

创建于:{formatDateTime(account.created_at)}

handleDelete(account)} disabled={deleteMutation.isPending} className="px-3 py-2 text-xs" > 删除
))}
)}
{isCreateOpen && ( setIsCreateOpen(false)} onCreated={() => { setFeedback({ tone: 'success', message: 'DNS 账号已添加。' }); setIsCreateOpen(false); queryClient.invalidateQueries({ queryKey: ['dns-accounts'] }); }} /> )} ); } function DnsAccountCreateModal({ isOpen, onClose, onCreated, }: { isOpen: boolean; onClose: () => void; onCreated: () => void; }) { const [error, setError] = useState(''); const { register, handleSubmit, formState } = useForm({ defaultValues: { name: '', type: 'cloudflare', authorization: '' }, }); const createMutation = useMutation({ mutationFn: createDnsAccount, onSuccess: onCreated, onError: (err) => setError(getErrorMessage(err)), }); const onSubmit = handleSubmit((values) => { setError(''); // for cloudflare we wrap the token in JSON if it isn't already (the backend expects JSON) let auth = values.authorization; if (!auth.startsWith('{')) { auth = JSON.stringify({ api_token: values.authorization }); } createMutation.mutate({ ...values, authorization: auth }); }); return (
{error && } {createMutation.isPending ? '提交中...' : '提交'}
); }