"use client"; import ConfirmDeleteDialog from "@app/components/ConfirmDeleteDialog"; import { Button } from "@app/components/ui/button"; import { useOrgContext } from "@app/hooks/useOrgContext"; import { toast } from "@app/hooks/useToast"; import { useState, useTransition, useActionState } from "react"; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { z } from "zod"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { createApiClient } from "@app/lib/api"; import { useEnvContext } from "@app/hooks/useEnvContext"; import { formatAxiosError } from "@app/lib/api"; import { AxiosResponse } from "axios"; import { DeleteOrgResponse, ListUserOrgsResponse } from "@server/routers/org"; import { useRouter } from "next/navigation"; import { SettingsContainer, SettingsSection, SettingsSectionHeader, SettingsSectionTitle, SettingsSectionDescription, SettingsSectionBody, SettingsSectionForm, SettingsSectionFooter } from "@app/components/Settings"; import { useUserContext } from "@app/hooks/useUserContext"; import { useTranslations } from "next-intl"; import { build } from "@server/build"; import type { OrgContextType } from "@app/contexts/orgContext"; // Schema for general organization settings const GeneralFormSchema = z.object({ name: z.string(), subnet: z.string().optional() }); export default function GeneralPage() { const { org } = useOrgContext(); return ( {!org.org.isBillingOrg && } ); } type SectionFormProps = { org: OrgContextType["org"]["org"]; }; function DeleteForm({ org }: SectionFormProps) { const t = useTranslations(); const api = createApiClient(useEnvContext()); const router = useRouter(); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [loadingDelete, startTransition] = useTransition(); const { user } = useUserContext(); async function pickNewOrgAndNavigate() { try { const res = await api.get>( `/user/${user.userId}/orgs` ); if (res.status === 200) { if (res.data.data.orgs.length > 0) { const orgId = res.data.data.orgs[0].orgId; // go to `/${orgId}/settings`); router.push(`/${orgId}/settings`); } else { // go to `/setup` router.push("/setup"); } } } catch (err) { console.error(err); toast({ variant: "destructive", title: t("orgErrorFetch"), description: formatAxiosError(err, t("orgErrorFetchMessage")) }); } } async function deleteOrg() { try { const res = await api.delete>( `/org/${org.orgId}` ); toast({ title: t("orgDeleted"), description: t("orgDeletedMessage") }); if (res.status === 200) { pickNewOrgAndNavigate(); } } catch (err) { console.error(err); toast({ variant: "destructive", title: t("orgErrorDelete"), description: formatAxiosError(err, t("orgErrorDeleteMessage")) }); } } return ( <> { setIsDeleteModalOpen(val); }} dialog={

{t("orgQuestionRemove")}

{t("orgMessageRemove")}

} buttonText={t("orgDeleteConfirm")} onConfirm={async () => startTransition(deleteOrg)} string={org.name || ""} title={t("orgDelete")} /> {t("dangerSection")} {t("dangerSectionDescription")} ); } function GeneralSectionForm({ org }: SectionFormProps) { const { updateOrg } = useOrgContext(); const form = useForm({ resolver: zodResolver( GeneralFormSchema.pick({ name: true, subnet: true }) ), defaultValues: { name: org.name, subnet: org.subnet || "" // Add default value for subnet }, mode: "onChange" }); const t = useTranslations(); const router = useRouter(); const [, formAction, loadingSave] = useActionState(performSave, null); const api = createApiClient(useEnvContext()); async function performSave() { const isValid = await form.trigger(); if (!isValid) return; const data = form.getValues(); try { const reqData = { name: data.name } as any; // Update organization await api.post(`/org/${org.orgId}`, reqData); // Update the org context to reflect the change in the info card updateOrg({ name: data.name }); toast({ title: t("orgUpdated"), description: t("orgUpdatedDescription") }); router.refresh(); } catch (e) { toast({ variant: "destructive", title: t("orgErrorUpdate"), description: formatAxiosError(e, t("orgErrorUpdateMessage")) }); } } return ( {t("general")} {t("orgGeneralSettingsDescription")}
( {t("name")} {t("orgDisplayName")} )} />
); }