"use client"; import ConfirmDeleteDialog from "@app/components/ConfirmDeleteDialog"; import { Button } from "@app/components/ui/button"; import { useOrgContext } from "@app/hooks/useOrgContext"; import { userOrgUserContext } from "@app/hooks/useOrgUserContext"; import { toast } from "@app/hooks/useToast"; import { useState } 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 { AlertTriangle, Trash2 } from "lucide-react"; import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"; import { AxiosResponse } from "axios"; import { DeleteOrgResponse, ListOrgsResponse } from "@server/routers/org"; import { redirect, useRouter } from "next/navigation"; import { SettingsContainer, SettingsSection, SettingsSectionHeader, SettingsSectionTitle, SettingsSectionDescription, SettingsSectionBody, SettingsSectionForm, SettingsSectionFooter } from "@app/components/Settings"; const GeneralFormSchema = z.object({ name: z.string() }); type GeneralFormValues = z.infer; export default function GeneralPage() { const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const { orgUser } = userOrgUserContext(); const router = useRouter(); const { org } = useOrgContext(); const api = createApiClient(useEnvContext()); const [loadingDelete, setLoadingDelete] = useState(false); const [loadingSave, setLoadingSave] = useState(false); const form = useForm({ resolver: zodResolver(GeneralFormSchema), defaultValues: { name: org?.org.name }, mode: "onChange" }); async function deleteOrg() { setLoadingDelete(true); try { const res = await api.delete>( `/org/${org?.org.orgId}` ); toast({ title: "Organization deleted", description: "The organization and its data has been deleted." }); if (res.status === 200) { pickNewOrgAndNavigate(); } } catch (err) { console.error(err); toast({ variant: "destructive", title: "Failed to delete org", description: formatAxiosError( err, "An error occurred while deleting the org." ) }); } finally { setLoadingDelete(false); } } async function pickNewOrgAndNavigate() { try { const res = await api.get>(`/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: "Failed to fetch orgs", description: formatAxiosError( err, "An error occurred while listing your orgs" ) }); } } async function onSubmit(data: GeneralFormValues) { setLoadingSave(true); await api .post(`/org/${org?.org.orgId}`, { name: data.name }) .then(() => { toast({ title: "Organization updated", description: "The organization has been updated." }); router.refresh(); }) .catch((e) => { toast({ variant: "destructive", title: "Failed to update org", description: formatAxiosError( e, "An error occurred while updating the org." ) }); }) .finally(() => { setLoadingSave(false); }); } return ( { setIsDeleteModalOpen(val); }} dialog={

Are you sure you want to delete the organization{" "} {org?.org.name}?

This action is irreversible and will delete all associated data.

To confirm, type the name of the organization below.

} buttonText="Confirm Delete Organization" onConfirm={deleteOrg} string={org?.org.name || ""} title="Delete Organization" /> Organization Settings Manage your organization details and configuration
( Name This is the display name of the org )} />
Danger Zone Once you delete this org, there is no going back. Please be certain.
); }