import { useEffect, useState } from "react"; import { useMutation, useQueryClient } from "@tanstack/react-query"; import { useCompany } from "../context/CompanyContext"; import { useBreadcrumbs } from "../context/BreadcrumbContext"; import { companiesApi } from "../api/companies"; import { accessApi } from "../api/access"; import { queryKeys } from "../lib/queryKeys"; import { Button } from "@/components/ui/button"; import { Settings } from "lucide-react"; import { CompanyPatternIcon } from "../components/CompanyPatternIcon"; import { Field, ToggleField, HintIcon } from "../components/agent-config-primitives"; export function CompanySettings() { const { companies, selectedCompany, selectedCompanyId, setSelectedCompanyId } = useCompany(); const { setBreadcrumbs } = useBreadcrumbs(); const queryClient = useQueryClient(); // General settings local state const [companyName, setCompanyName] = useState(""); const [description, setDescription] = useState(""); const [brandColor, setBrandColor] = useState(""); // Sync local state from selected company useEffect(() => { if (!selectedCompany) return; setCompanyName(selectedCompany.name); setDescription(selectedCompany.description ?? ""); setBrandColor(selectedCompany.brandColor ?? ""); }, [selectedCompany]); const [inviteLink, setInviteLink] = useState(null); const [inviteError, setInviteError] = useState(null); const generalDirty = !!selectedCompany && (companyName !== selectedCompany.name || description !== (selectedCompany.description ?? "") || brandColor !== (selectedCompany.brandColor ?? "")); const generalMutation = useMutation({ mutationFn: (data: { name: string; description: string | null; brandColor: string | null }) => companiesApi.update(selectedCompanyId!, data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: queryKeys.companies.all }); }, }); const settingsMutation = useMutation({ mutationFn: (requireApproval: boolean) => companiesApi.update(selectedCompanyId!, { requireBoardApprovalForNewAgents: requireApproval, }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: queryKeys.companies.all }); }, }); const inviteMutation = useMutation({ mutationFn: () => accessApi.createCompanyInvite(selectedCompanyId!, { allowedJoinTypes: "both", expiresInHours: 72, }), onSuccess: (invite) => { setInviteError(null); const base = window.location.origin.replace(/\/+$/, ""); const absoluteUrl = invite.inviteUrl.startsWith("http") ? invite.inviteUrl : `${base}${invite.inviteUrl}`; setInviteLink(absoluteUrl); queryClient.invalidateQueries({ queryKey: queryKeys.sidebarBadges(selectedCompanyId!) }); }, onError: (err) => { setInviteError(err instanceof Error ? err.message : "Failed to create invite"); }, }); const archiveMutation = useMutation({ mutationFn: ({ companyId, nextCompanyId, }: { companyId: string; nextCompanyId: string | null; }) => companiesApi.archive(companyId).then(() => ({ nextCompanyId })), onSuccess: async ({ nextCompanyId }) => { if (nextCompanyId) { setSelectedCompanyId(nextCompanyId); } await queryClient.invalidateQueries({ queryKey: queryKeys.companies.all }); await queryClient.invalidateQueries({ queryKey: queryKeys.companies.stats }); }, }); useEffect(() => { setBreadcrumbs([ { label: selectedCompany?.name ?? "Company", href: "/dashboard" }, { label: "Settings" }, ]); }, [setBreadcrumbs, selectedCompany?.name]); if (!selectedCompany) { return (
No company selected. Select a company from the switcher above.
); } function handleSaveGeneral() { generalMutation.mutate({ name: companyName.trim(), description: description.trim() || null, brandColor: brandColor || null, }); } return (

Company Settings

{/* General */}
General
setCompanyName(e.target.value)} /> setDescription(e.target.value)} />
{/* Appearance */}
Appearance
setBrandColor(e.target.value)} className="h-8 w-8 cursor-pointer rounded border border-border bg-transparent p-0" /> { const v = e.target.value; if (v === "" || /^#[0-9a-fA-F]{0,6}$/.test(v)) { setBrandColor(v); } }} placeholder="Auto" className="w-28 rounded-md border border-border bg-transparent px-2.5 py-1.5 text-sm font-mono outline-none" /> {brandColor && ( )}
{/* Save button for General + Appearance */} {generalDirty && (
{generalMutation.isSuccess && ( Saved )} {generalMutation.isError && ( {generalMutation.error instanceof Error ? generalMutation.error.message : "Failed to save"} )}
)} {/* Hiring */}
Hiring
settingsMutation.mutate(v)} />
{/* Invites */}
Invites
Generate a link to invite humans or agents to this company.
{inviteLink && ( )}
{inviteError &&

{inviteError}

} {inviteLink && (
Share link
{inviteLink}
)}
{/* Archive */}
Archive

Archive this company to hide it from the sidebar. This persists in the database.

{archiveMutation.isError && ( {archiveMutation.error instanceof Error ? archiveMutation.error.message : "Failed to archive company"} )}
); }