"use client"; import api from "@app/api"; import { Button, buttonVariants } from "@app/components/ui/button"; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from "@app/components/ui/form"; import { Input } from "@app/components/ui/input"; import { useToast } from "@app/hooks/useToast"; import { zodResolver } from "@hookform/resolvers/zod"; import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { z } from "zod"; import { Credenza, CredenzaBody, CredenzaClose, CredenzaContent, CredenzaDescription, CredenzaFooter, CredenzaHeader, CredenzaTitle, } from "@app/components/Credenza"; import { useOrgContext } from "@app/hooks/useOrgContext"; import { useParams, useRouter } from "next/navigation"; import { PickSiteDefaultsResponse } from "@server/routers/site"; import { generateKeypair } from "../[niceId]/components/wireguardConfig"; import CopyTextBox from "@app/components/CopyTextBox"; import { Checkbox } from "@app/components/ui/checkbox"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@app/components/ui/select"; const method = [ { label: "Wireguard", value: "wg" }, { label: "Newt", value: "newt" }, ] as const; const accountFormSchema = z.object({ name: z .string() .min(2, { message: "Name must be at least 2 characters.", }) .max(30, { message: "Name must not be longer than 30 characters.", }), method: z.enum(["wg", "newt"]), }); type AccountFormValues = z.infer; const defaultValues: Partial = { name: "", method: "wg", }; type CreateSiteFormProps = { open: boolean; setOpen: (open: boolean) => void; }; export default function CreateSiteForm({ open, setOpen }: CreateSiteFormProps) { const { toast } = useToast(); const [loading, setLoading] = useState(false); const params = useParams(); const orgId = params.orgId; const router = useRouter(); const [keypair, setKeypair] = useState<{ publicKey: string; privateKey: string; } | null>(null); const [isLoading, setIsLoading] = useState(true); const [isChecked, setIsChecked] = useState(false); const [siteDefaults, setSiteDefaults] = useState(null); const handleCheckboxChange = (checked: boolean) => { setIsChecked(checked); }; const form = useForm({ resolver: zodResolver(accountFormSchema), defaultValues, }); useEffect(() => { if (!open) return; if (typeof window !== "undefined") { const generatedKeypair = generateKeypair(); setKeypair(generatedKeypair); setIsLoading(false); api.get(`/org/${orgId}/pick-site-defaults`) .catch((e) => { toast({ title: "Error picking site defaults", }); }) .then((res) => { if (res && res.status === 200) { setSiteDefaults(res.data.data); } }); } }, [open]); async function onSubmit(data: AccountFormValues) { setLoading(true); const res = await api .put(`/org/${orgId}/site/`, { name: data.name, subnet: siteDefaults?.subnet, exitNodeId: siteDefaults?.exitNodeId, pubKey: keypair?.publicKey, }) .catch((e) => { toast({ title: "Error creating site", }); }); if (res && res.status === 201) { const niceId = res.data.data.niceId; // navigate to the site page router.push(`/${orgId}/settings/sites/${niceId}`); // close the modal setOpen(false); } setLoading(false); } const wgConfig = keypair && siteDefaults ? `[Interface] Address = ${siteDefaults.subnet} ListenPort = 51820 PrivateKey = ${keypair.privateKey} [Peer] PublicKey = ${siteDefaults.publicKey} AllowedIPs = ${siteDefaults.address.split("/")[0]}/32 Endpoint = ${siteDefaults.endpoint}:${siteDefaults.listenPort} PersistentKeepalive = 5` : ""; const newtConfig = `curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh`; return ( <> { setOpen(val); setLoading(false); // reset all values form.reset(); setIsChecked(false); setKeypair(null); setSiteDefaults(null); }} > Create Site Create a new site to start connecting your resources
( Name This is the name that will be displayed for this site. )} /> ( Method This is how you will connect your site to Fossorial. )} />
{form.watch("method") === "wg" && !isLoading ? ( ) : form.watch("method") === "wg" && isLoading ? (

Loading WireGuard configuration...

) : ( )}
You will only be able to see the configuration once.
); }