From 5f937f3217055d6acef5a528f3c28e9fcf182c4c Mon Sep 17 00:00:00 2001 From: Ishaan Gupta Date: Wed, 27 May 2026 22:44:08 +0530 Subject: [PATCH] implement update org name in settings --- apps/web/components/settings/account.tsx | 256 +++++++++++++++++------ 1 file changed, 189 insertions(+), 67 deletions(-) diff --git a/apps/web/components/settings/account.tsx b/apps/web/components/settings/account.tsx index 155659b5..9de7124b 100644 --- a/apps/web/components/settings/account.tsx +++ b/apps/web/components/settings/account.tsx @@ -41,10 +41,11 @@ import { MoreHorizontal, UserMinus, X, + Pencil, Tag, Plus, } from "lucide-react" -import { useMemo, useRef, useState } from "react" +import { useEffect, useMemo, useRef, useState } from "react" import { toast } from "sonner" import { useContainerTags } from "@/hooks/use-container-tags" import { PopoverAnchor } from "@ui/components/popover" @@ -141,6 +142,7 @@ export default function Account() { organizations: allOrgs, setActiveOrg, refetchActiveOrg, + refetchOrganizations, } = useAuth() const autumn = useCustomer() const [switchingOrgId, setSwitchingOrgId] = useState(null) @@ -156,6 +158,8 @@ export default function Account() { >([]) const [tagQuery, setTagQuery] = useState("") const [tagDropdownOpen, setTagDropdownOpen] = useState(false) + const [isEditingOrgName, setIsEditingOrgName] = useState(false) + const [orgNameDraft, setOrgNameDraft] = useState("") const tagInputRef = useRef(null) const tagAnchorRef = useRef(null) const { allProjects: allContainerTags } = useContainerTags() @@ -191,6 +195,11 @@ export default function Account() { const { currentPlan } = useTokenUsage(autumn) + useEffect(() => { + setOrgNameDraft(org?.name ?? "") + setIsEditingOrgName(false) + }, [org?.id, org?.name]) + const activeMemberRoleQuery = useQuery({ queryKey: ["organization", org?.id, "active-member-role"], queryFn: async () => { @@ -346,12 +355,53 @@ export default function Account() { }, }) + const updateOrgNameMutation = useMutation({ + mutationFn: async (name: string) => { + if (!org?.id) throw new Error("No active organization") + const trimmed = name.trim() + if (!trimmed) throw new Error("Enter an organization name") + const result = await authClient.organization.update({ + organizationId: org.id, + data: { name: trimmed }, + }) + if (result.error) { + throw new Error( + result.error.message ?? "Failed to update organization name", + ) + } + return trimmed + }, + onSuccess: async (name) => { + setOrgNameDraft(name) + setIsEditingOrgName(false) + await Promise.all([refetchActiveOrg(), refetchOrganizations()]) + toast.success("Organization name updated") + }, + onError: (error) => { + toast.error( + getErrorMessage(error, "Failed to update organization name"), + ) + }, + }) + const handleInviteSubmit = (event: React.FormEvent) => { event.preventDefault() if (!canManageTeam || inviteMemberMutation.isPending) return inviteMemberMutation.mutate() } + const handleOrgNameSubmit = (event: React.FormEvent) => { + event.preventDefault() + if (!canManageTeam || updateOrgNameMutation.isPending) return + const trimmed = orgNameDraft.trim() + if (!trimmed || trimmed === org?.name) { + setOrgNameDraft(org?.name ?? "") + setIsEditingOrgName(false) + return + } + updateOrgNameMutation.mutate(trimmed) + } + const planByOrgId = useMemo(() => { const map = new Map() for (const summary of orgSummaries ?? []) { @@ -438,15 +488,130 @@ export default function Account() { > Organization

- {canSwitchOrg ? ( - - + setOrgNameDraft(event.target.value)} + disabled={updateOrgNameMutation.isPending} + autoFocus + maxLength={80} className={cn( - "flex min-w-0 max-w-full items-center gap-2 transition-opacity", - "cursor-pointer hover:opacity-90", dmSans125ClassName(), + "h-9 min-w-0 flex-1 rounded-[9px] border border-white/10 bg-black/30 px-3 text-[14px] font-medium tracking-[-0.14px] text-[#FAFAFA] outline-none transition-colors placeholder:text-[#525252] focus:border-[#4BA0FA]/60", )} - > + placeholder="Organization name" + /> +
+ + +
+ + ) : ( +
+ {canSwitchOrg ? ( + + + + {org?.name ?? "Personal"} + + + + + {sortedOrgsForMenu.map((organization) => { + const isCurrent = organization.id === org?.id + const isSwitching = switchingOrgId === organization.id + const plan = resolveOrgPlan( + organization.id, + isCurrent, + currentPlan, + planByOrgId, + ) + return ( + + ) + })} + + + ) : ( {org?.name ?? "Personal"} - - - - {sortedOrgsForMenu.map((organization) => { - const isCurrent = organization.id === org?.id - const isSwitching = switchingOrgId === organization.id - const plan = resolveOrgPlan( - organization.id, - isCurrent, - currentPlan, - planByOrgId, - ) - return ( - - ) - })} - - - ) : ( - - {org?.name ?? "Personal"} - + {canManageTeam ? ( + + ) : null} +
)}