import { useState, useEffect } from "react"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useCompany } from "../context/CompanyContext"; import { useDialog } from "../context/DialogContext"; import { useBreadcrumbs } from "../context/BreadcrumbContext"; import { companiesApi } from "../api/companies"; import { queryKeys } from "../lib/queryKeys"; import { formatCents, relativeTime } from "../lib/utils"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Pencil, Check, X, Plus, MoreHorizontal, Trash2, Users, CircleDot, DollarSign, Calendar, } from "lucide-react"; export function Companies() { const { companies, selectedCompanyId, setSelectedCompanyId, loading, error, } = useCompany(); const { openOnboarding } = useDialog(); const { setBreadcrumbs } = useBreadcrumbs(); const queryClient = useQueryClient(); const { data: stats } = useQuery({ queryKey: queryKeys.companies.stats, queryFn: () => companiesApi.stats(), }); // Inline edit state const [editingId, setEditingId] = useState(null); const [editName, setEditName] = useState(""); const [confirmDeleteId, setConfirmDeleteId] = useState(null); const editMutation = useMutation({ mutationFn: ({ id, newName }: { id: string; newName: string }) => companiesApi.update(id, { name: newName }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: queryKeys.companies.all }); setEditingId(null); }, }); const deleteMutation = useMutation({ mutationFn: (id: string) => companiesApi.remove(id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: queryKeys.companies.all }); queryClient.invalidateQueries({ queryKey: queryKeys.companies.stats }); setConfirmDeleteId(null); }, }); useEffect(() => { setBreadcrumbs([{ label: "Companies" }]); }, [setBreadcrumbs]); function startEdit(companyId: string, currentName: string) { setEditingId(companyId); setEditName(currentName); } function saveEdit() { if (!editingId || !editName.trim()) return; editMutation.mutate({ id: editingId, newName: editName.trim() }); } function cancelEdit() { setEditingId(null); setEditName(""); } return (
{loading &&

Loading companies...

} {error &&

{error.message}

}
{companies.map((company) => { const selected = company.id === selectedCompanyId; const isEditing = editingId === company.id; const isConfirmingDelete = confirmDeleteId === company.id; const companyStats = stats?.[company.id]; const agentCount = companyStats?.agentCount ?? 0; const issueCount = companyStats?.issueCount ?? 0; const budgetPct = company.budgetMonthlyCents > 0 ? Math.round( (company.spentMonthlyCents / company.budgetMonthlyCents) * 100, ) : 0; return (
setSelectedCompanyId(company.id)} onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); setSelectedCompanyId(company.id); } }} className={`group text-left bg-card border rounded-lg p-5 transition-colors cursor-pointer ${ selected ? "border-primary ring-1 ring-primary" : "border-border hover:border-muted-foreground/30" }`} > {/* Header row: name + menu */}
{isEditing ? (
e.stopPropagation()} > setEditName(e.target.value)} className="h-7 text-sm" autoFocus onKeyDown={(e) => { if (e.key === "Enter") saveEdit(); if (e.key === "Escape") cancelEdit(); }} />
) : (

{company.name}

{company.status}
)} {company.description && !isEditing && (

{company.description}

)}
{/* Three-dot menu */}
e.stopPropagation()}> startEdit(company.id, company.name)} > Rename setConfirmDeleteId(company.id)} > Delete Company
{/* Stats row */}
{agentCount} {agentCount === 1 ? "agent" : "agents"}
{issueCount} {issueCount === 1 ? "issue" : "issues"}
{formatCents(company.spentMonthlyCents)} {company.budgetMonthlyCents > 0 ? <> / {formatCents(company.budgetMonthlyCents)} ({budgetPct}%) : Unlimited budget}
Created {relativeTime(company.createdAt)}
{/* Delete confirmation */} {isConfirmingDelete && (
e.stopPropagation()} >

Delete this company and all its data? This cannot be undone.

)}
); })}
); }