'use client'; import {zodResolver} from '@hookform/resolvers/zod'; import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'; import {useEffect} from 'react'; import {useForm} from 'react-hook-form'; import {Loader2} from 'lucide-react'; import {Button} from '@/components/ui/button'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import {EmptyStateWithBorder} from '@/components/layout/empty'; import {ErrorInline} from '@/components/layout/error'; import {LoadingStateWithBorder} from '@/components/layout/loading'; import {Input} from '@/components/ui/input'; import {Label} from '@/components/ui/label'; import {Textarea} from '@/components/ui/textarea'; import type {TlsCertificateItem} from '@/lib/services/openflare'; import {TlsCertificateService} from '@/lib/services/openflare'; import {defaultManualImportValues, type ManualImportFormValues, manualImportSchema,} from './schemas'; import {getErrorMessage, toManualPayload} from './website-utils'; const certificatesQueryKey = ['openflare', 'tls-certificates']; interface CertificateEditorDialogProps { certificateId: number | null; open: boolean; onOpenChange: (open: boolean) => void; onSaved?: (certificate: TlsCertificateItem) => void; onConvert?: (certificate: TlsCertificateItem) => void; } export function CertificateEditorDialog({ certificateId, open, onOpenChange, onSaved, onConvert, }: CertificateEditorDialogProps) { const queryClient = useQueryClient(); const form = useForm({ resolver: zodResolver(manualImportSchema), defaultValues: defaultManualImportValues, }); const certificateQuery = useQuery({ queryKey: ['openflare', 'tls-certificates', 'content', certificateId], queryFn: () => TlsCertificateService.getContent(certificateId as number), enabled: open && certificateId !== null, }); const updateMutation = useMutation({ mutationFn: (values: ManualImportFormValues) => TlsCertificateService.update(certificateId as number, toManualPayload(values)), onSuccess: async (certificate) => { await Promise.all([ queryClient.invalidateQueries({queryKey: certificatesQueryKey}), queryClient.invalidateQueries({queryKey: ['openflare', 'managed-domains']}), ]); onSaved?.(certificate); handleClose(); }, }); useEffect(() => { if (!open || !certificateQuery.data) return; form.reset({ name: certificateQuery.data.name, cert_pem: certificateQuery.data.cert_pem, key_pem: certificateQuery.data.key_pem, remark: certificateQuery.data.remark || '', }); }, [certificateQuery.data, form, open]); const handleSubmit = form.handleSubmit((values) => { updateMutation.mutate(values); }); const handleClose = () => { updateMutation.reset(); form.reset(defaultManualImportValues); onOpenChange(false); }; const canConvert = certificateQuery.data?.provider === 'upload' && certificateQuery.data.apply_status !== 'applying'; return ( !next && handleClose()}> 编辑证书 可以修改证书名称、备注,以及重新上传 PEM 证书和私钥内容。 {certificateQuery.isLoading ? ( ) : certificateQuery.isError ? ( ) : !certificateQuery.data ? ( ) : (
{updateMutation.isError ? (

{getErrorMessage(updateMutation.error)}

) : null}