import { useEffect, useState } from "react"; import { useLocation } from "react-router-dom"; import { useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import z from "zod"; import { zodResolver } from "@hookform/resolvers/zod"; import { ChevronsUpDown, Plus } from "lucide-react"; import { ClientResponseError } from "pocketbase"; import { Button } from "@/components/ui/button"; import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "@/components/ui/breadcrumb"; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Toaster } from "@/components/ui/toaster"; import { useToast } from "@/components/ui/use-toast"; import AccessEdit from "@/components/certimate/AccessEdit"; import DeployList from "@/components/certimate/DeployList"; import EmailsEdit from "@/components/certimate/EmailsEdit"; import StringList from "@/components/certimate/StringList"; import { cn } from "@/lib/utils"; import { PbErrorData } from "@/domain/base"; import { accessTypeMap } from "@/domain/access"; import { EmailsSetting } from "@/domain/settings"; import { DeployConfig, Domain } from "@/domain/domain"; import { save, get } from "@/repository/domains"; import { useConfig } from "@/providers/config"; const Edit = () => { const { config: { accesses, emails }, } = useConfig(); const [domain, setDomain] = useState({} as Domain); const location = useLocation(); const { t } = useTranslation(); const [tab, setTab] = useState<"apply" | "deploy">("apply"); useEffect(() => { // Parsing query parameters const queryParams = new URLSearchParams(location.search); const id = queryParams.get("id"); if (id) { const fetchData = async () => { const data = await get(id); setDomain(data); }; fetchData(); } }, [location.search]); const formSchema = z.object({ id: z.string().optional(), domain: z.string().min(1, { message: "common.errmsg.domain_invalid", }), email: z.string().email("common.errmsg.email_invalid").optional(), access: z.string().regex(/^[a-zA-Z0-9]+$/, { message: "domain.application.form.access.placeholder", }), keyAlgorithm: z.string().optional(), nameservers: z.string().optional(), timeout: z.number().optional(), }); const form = useForm>({ resolver: zodResolver(formSchema), defaultValues: { id: "", domain: "", email: "", access: "", keyAlgorithm: "RSA2048", nameservers: "", timeout: 60, }, }); useEffect(() => { if (domain) { form.reset({ id: domain.id, domain: domain.domain, email: domain.applyConfig?.email, access: domain.applyConfig?.access, keyAlgorithm: domain.applyConfig?.keyAlgorithm, nameservers: domain.applyConfig?.nameservers, timeout: domain.applyConfig?.timeout, }); } }, [domain, form]); const { toast } = useToast(); const onSubmit = async (data: z.infer) => { const req: Domain = { id: data.id as string, crontab: "0 0 * * *", domain: data.domain, email: data.email, access: data.access, applyConfig: { email: data.email ?? "", access: data.access, keyAlgorithm: data.keyAlgorithm, nameservers: data.nameservers, timeout: data.timeout, }, }; try { const resp = await save(req); let description = t("domain.application.form.domain.changed.message"); if (req.id == "") { description = t("domain.application.form.domain.added.message"); } toast({ title: t("common.save.succeeded.message"), description, }); if (!domain?.id) setTab("deploy"); setDomain({ ...resp }); } catch (e) { const err = e as ClientResponseError; Object.entries(err.response.data as PbErrorData).forEach(([key, value]) => { form.setError(key as keyof z.infer, { type: "manual", message: value.message, }); }); return; } }; const handelOnDeployListChange = async (list: DeployConfig[]) => { const req = { ...domain, deployConfig: list, }; try { const resp = await save(req); let description = t("domain.application.form.domain.changed.message"); if (req.id == "") { description = t("domain.application.form.domain.added.message"); } toast({ title: t("common.save.succeeded.message"), description, }); if (!domain?.id) setTab("deploy"); setDomain({ ...resp }); } catch (e) { const err = e as ClientResponseError; Object.entries(err.response.data as PbErrorData).forEach(([key, value]) => { form.setError(key as keyof z.infer, { type: "manual", message: value.message, }); }); return; } }; return ( <>
{t("domain.page.title")} {domain?.id ? t("domain.edit") : t("domain.add")}
{ setTab("apply"); }} > {t("domain.application.tab")}
{ if (!domain?.id) { toast({ title: t("domain.application.unsaved.message"), description: t("domain.application.unsaved.message"), variant: "destructive", }); return; } setTab("deploy"); }} > {t("domain.deployment.tab")}
{/* 域名 */} ( <> { form.setValue("domain", domain); }} /> )} /> {/* 邮箱 */} (
{t("domain.application.form.email.label") + " " + t("domain.application.form.email.tips")}
{t("common.add")}
} /> )} /> {/* DNS 服务商授权 */} (
{t("domain.application.form.access.label")}
{t("common.add")}
} op="add" /> )} />

{t("domain.application.form.advanced_settings.label")}
{/* 证书算法 */} ( {t("domain.application.form.key_algorithm.label")} )} /> {/* DNS */} ( { form.setValue("nameservers", val); }} valueType="dns" > )} /> {/* DNS 超时时间 */} ( {t("domain.application.form.timeout.label")} { form.setValue("timeout", parseInt(e.target.value)); }} /> )} />
{ handelOnDeployListChange(list); }} />
); }; export default Edit;