"use client"; import { Credenza, CredenzaBody, CredenzaClose, CredenzaContent, CredenzaDescription, CredenzaFooter, CredenzaHeader, CredenzaTitle } from "@app/components/Credenza"; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@app/components/ui/form"; import { Button } from "@app/components/ui/button"; import { Checkbox } from "@app/components/ui/checkbox"; import { Input } from "@app/components/ui/input"; import { Alert, AlertDescription, AlertTitle } from "@app/components/ui/alert"; import { useEnvContext } from "@app/hooks/useEnvContext"; import { toast } from "@app/hooks/useToast"; import { createApiClient, formatAxiosError } from "@app/lib/api"; import { CreateSiteProvisioningKeyResponse } from "@server/routers/siteProvisioning/types"; import { AxiosResponse } from "axios"; import { InfoIcon } from "lucide-react"; import { useTranslations } from "next-intl"; import { useRouter } from "next/navigation"; import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { z } from "zod"; import { zodResolver } from "@hookform/resolvers/zod"; import CopyTextBox from "@app/components/CopyTextBox"; import { DateTimePicker, DateTimeValue } from "@app/components/DateTimePicker"; const FORM_ID = "create-site-provisioning-key-form"; type CreateSiteProvisioningKeyCredenzaProps = { open: boolean; setOpen: (open: boolean) => void; orgId: string; }; export default function CreateSiteProvisioningKeyCredenza({ open, setOpen, orgId }: CreateSiteProvisioningKeyCredenzaProps) { const t = useTranslations(); const router = useRouter(); const api = createApiClient(useEnvContext()); const [loading, setLoading] = useState(false); const [created, setCreated] = useState(null); const createFormSchema = z .object({ name: z .string() .min(1, { message: t("nameMin", { len: 1 }) }) .max(255, { message: t("nameMax", { len: 255 }) }), unlimitedBatchSize: z.boolean(), maxBatchSize: z .number() .int() .min(1, { message: t("provisioningKeysMaxBatchSizeInvalid") }) .max(1_000_000, { message: t("provisioningKeysMaxBatchSizeInvalid") }), validUntil: z.string().optional(), approveNewSites: z.boolean() }) .superRefine((data, ctx) => { const v = data.validUntil; if (v == null || v.trim() === "") { return; } if (Number.isNaN(Date.parse(v))) { ctx.addIssue({ code: "custom", message: t("provisioningKeysValidUntilInvalid"), path: ["validUntil"] }); } }); type CreateFormValues = z.infer; const form = useForm({ resolver: zodResolver(createFormSchema), defaultValues: { name: "", unlimitedBatchSize: false, maxBatchSize: 100, validUntil: "", approveNewSites: true } }); useEffect(() => { if (!open) { setCreated(null); form.reset({ name: "", unlimitedBatchSize: false, maxBatchSize: 100, validUntil: "", approveNewSites: true }); } }, [open, form]); async function onSubmit(data: CreateFormValues) { setLoading(true); try { const res = await api .put>( `/org/${orgId}/site-provisioning-key`, { name: data.name, maxBatchSize: data.unlimitedBatchSize ? null : data.maxBatchSize, validUntil: data.validUntil == null || data.validUntil.trim() === "" ? undefined : data.validUntil, approveNewSites: data.approveNewSites } ) .catch((e) => { toast({ variant: "destructive", title: t("provisioningKeysErrorCreate"), description: formatAxiosError(e) }); }); if (res && res.status === 201) { setCreated(res.data.data); router.refresh(); } } finally { setLoading(false); } } const credential = created && created.siteProvisioningKey; const unlimitedBatchSize = form.watch("unlimitedBatchSize"); return ( {created ? t("provisioningKeysList") : t("provisioningKeysCreate")} {!created && ( {t("provisioningKeysCreateDescription")} )} {!created && (
( {t("name")} )} /> ( {t( "provisioningKeysMaxBatchSize" )} { const v = e.target.value; field.onChange( v === "" ? 100 : Number(v) ); }} value={field.value} /> )} /> ( field.onChange( c === true ) } /> {t( "provisioningKeysUnlimitedBatchSize" )} )} /> { const dateTimeValue: DateTimeValue = (() => { if (!field.value) return {}; const d = new Date(field.value); if (isNaN(d.getTime())) return {}; const hours = d .getHours() .toString() .padStart(2, "0"); const minutes = d .getMinutes() .toString() .padStart(2, "0"); const seconds = d .getSeconds() .toString() .padStart(2, "0"); return { date: d, time: `${hours}:${minutes}:${seconds}` }; })(); return ( {t( "provisioningKeysValidUntil" )} { if (!value.date) { field.onChange( "" ); return; } const d = new Date( value.date ); if (value.time) { const [h, m, s] = value.time.split( ":" ); d.setHours( parseInt( h, 10 ), parseInt( m, 10 ), parseInt( s || "0", 10 ) ); } field.onChange( d.toISOString() ); }} /> {t( "provisioningKeysValidUntilHint" )} ); }} /> ( field.onChange( c === true ) } />
{t( "provisioningKeysApproveNewSites" )} {t( "provisioningKeysApproveNewSitesDescription" )}
)} /> )} {created && credential && (
{t("provisioningKeysSave")} {t("provisioningKeysSaveDescription")}
)}
{!created ? ( <> ) : ( )}
); }