'use client'; import { zodResolver } from '@hookform/resolvers/zod'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useEffect, useState } from 'react'; import { useForm } from 'react-hook-form'; import { InlineMessage } from '@/components/feedback/inline-message'; import { AppModal } from '@/components/ui/app-modal'; import { applyTlsCertificate, updateAcmeCertificate } from '@/features/tls-certificates/api/tls-certificates'; import type { TlsCertificateItem } from '@/features/tls-certificates/types'; import { getDnsAccounts } from '@/features/dns-accounts/api/dns-accounts'; import { getDefaultAcmeAccount } from '@/features/acme-accounts/api/acme-accounts'; import { acmeApplySchema, defaultAcmeApplyValues, type AcmeApplyFormValues, } from '@/features/websites/schemas'; import { getErrorMessage } from '@/features/websites/utils'; import { PrimaryButton, ResourceField, ResourceInput, ResourceSelect, ToggleField, } from '@/features/shared/components/resource-primitives'; interface CertificateApplyModalProps { isOpen: boolean; onClose: () => void; onApplied?: (certificate: TlsCertificateItem) => void; editCertificate?: TlsCertificateItem | null; } export function CertificateApplyModal({ isOpen, onClose, onApplied, editCertificate, }: CertificateApplyModalProps) { const queryClient = useQueryClient(); const [feedback, setFeedback] = useState<{ tone: 'success' | 'danger'; message: string } | null>(null); const [showAdvanced, setShowAdvanced] = useState(false); const dnsAccountsQuery = useQuery({ queryKey: ['dns-accounts'], queryFn: getDnsAccounts, enabled: isOpen, }); const defaultAcmeAccountQuery = useQuery({ queryKey: ['acme-accounts', 'default'], queryFn: getDefaultAcmeAccount, enabled: isOpen, }); const form = useForm({ resolver: zodResolver(acmeApplySchema), defaultValues: defaultAcmeApplyValues, }); useEffect(() => { if (!isOpen) return; setFeedback(null); setShowAdvanced(false); if (editCertificate) { form.reset({ name: editCertificate.name, primary_domain: editCertificate.primary_domain || '', other_domains: editCertificate.other_domains || '', remark: editCertificate.remark || '', acme_account_id: editCertificate.acme_account_id, dns_account_id: editCertificate.dns_account_id, key_algorithm: editCertificate.key_algorithm as any || 'EC256', auto_renew: editCertificate.auto_renew, dns1: editCertificate.dns1 || '', dns2: editCertificate.dns2 || '', disable_cname: editCertificate.disable_cname, skip_dns: editCertificate.skip_dns, }); if (editCertificate.dns1 || editCertificate.dns2 || editCertificate.disable_cname || editCertificate.skip_dns) { setShowAdvanced(true); } } else { form.reset(defaultAcmeApplyValues); } }, [isOpen, form, editCertificate]); useEffect(() => { if (defaultAcmeAccountQuery.data) { form.setValue('acme_account_id', defaultAcmeAccountQuery.data.id); } }, [defaultAcmeAccountQuery.data, form]); const applyMutation = useMutation({ mutationFn: (values: AcmeApplyFormValues) => editCertificate ? updateAcmeCertificate(editCertificate.id, values) : applyTlsCertificate(values), onSuccess: async (certificate) => { await queryClient.invalidateQueries({ queryKey: ['tls-certificates'] }); onApplied?.(certificate); onClose(); }, onError: (error) => { setFeedback({ tone: 'danger', message: getErrorMessage(error) }); }, }); const onSubmit = form.handleSubmit((values) => { setFeedback(null); applyMutation.mutate(values); }); return (
{feedback ? ( ) : null}