()
| 77 | // removes the workspace and all of its data for every member, cancels billing, |
| 78 | // and logs the caller out. |
| 79 | function DangerZoneSection() { |
| 80 | const auth = useAuth(); |
| 81 | const membersResult = useAtomValue(orgMembersAtom); |
| 82 | const doDelete = useAtomSet(deleteOrganization, { mode: "promiseExit" }); |
| 83 | const [open, setOpen] = useState(false); |
| 84 | const [confirmText, setConfirmText] = useState(""); |
| 85 | const [deleting, setDeleting] = useState(false); |
| 86 | |
| 87 | const organizationName = auth.status === "authenticated" ? auth.organization?.name : undefined; |
| 88 | |
| 89 | // Only admins may delete. Derive the caller's role from the members list |
| 90 | // (already loaded for this page); render nothing while it loads or for |
| 91 | // members, so a delete control never flashes for someone who can't use it. |
| 92 | const isAdmin = AsyncResult.match(membersResult, { |
| 93 | onInitial: () => false, |
| 94 | onFailure: () => false, |
| 95 | onSuccess: ({ value }) => |
| 96 | value.members.some((m) => m.isCurrentUser && m.status === "active" && m.role === "admin"), |
| 97 | }); |
| 98 | |
| 99 | if (!isAdmin || !organizationName) return null; |
| 100 | |
| 101 | const confirmed = confirmText.trim() === organizationName.trim(); |
| 102 | |
| 103 | const handleDelete = async () => { |
| 104 | if (!confirmed || deleting) return; |
| 105 | setDeleting(true); |
| 106 | const exit = await doDelete({ |
| 107 | payload: { confirmName: confirmText.trim() }, |
| 108 | reactivityKeys: authWriteKeys, |
| 109 | }); |
| 110 | trackEvent("org_deleted", { success: Exit.isSuccess(exit) }); |
| 111 | if (Exit.isSuccess(exit)) { |
| 112 | // The org (and the caller's session) are gone. A full navigation resets |
| 113 | // all app state and lets the auth gate rehydrate to another membership or |
| 114 | // the create-org screen. |
| 115 | toast.success(`Deleted ${organizationName}`); |
| 116 | window.location.href = "/"; |
| 117 | return; |
| 118 | } |
| 119 | setDeleting(false); |
| 120 | toast.error("Failed to delete organization"); |
| 121 | }; |
| 122 | |
| 123 | return ( |
| 124 | <section className="mb-2 border-t border-border pt-8"> |
| 125 | <div className="flex items-center justify-between rounded-lg border border-destructive/30 bg-destructive/5 px-4 py-3"> |
| 126 | <div className="min-w-0"> |
| 127 | <h2 className="text-sm font-medium text-destructive">Delete organization</h2> |
| 128 | <p className="mt-0.5 text-sm text-muted-foreground"> |
| 129 | Permanently delete this organization and all of its data for every member. This cannot |
| 130 | be undone. |
| 131 | </p> |
| 132 | </div> |
| 133 | <Button |
| 134 | size="sm" |
| 135 | variant="destructive" |
| 136 | className="ml-4 shrink-0" |
nothing calls this directly
no test coverage detected