feat(ui): company-prefix routes, archive company, hide archived from sidebar

Support optional company-prefix in URL paths (e.g. /PAP/issues/PAP-1).
Filter archived companies from sidebar rail, switcher, and auto-select.
Add archive button to company settings with confirmation dialog.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Forgotten
2026-03-02 10:31:54 -06:00
parent ce3b31d2c3
commit 410164a632
5 changed files with 134 additions and 50 deletions

View File

@@ -11,7 +11,7 @@ import { CompanyPatternIcon } from "../components/CompanyPatternIcon";
import { Field, ToggleField, HintIcon } from "../components/agent-config-primitives";
export function CompanySettings() {
const { selectedCompany, selectedCompanyId } = useCompany();
const { companies, selectedCompany, selectedCompanyId, setSelectedCompanyId } = useCompany();
const { setBreadcrumbs } = useBreadcrumbs();
const queryClient = useQueryClient();
@@ -74,6 +74,22 @@ export function CompanySettings() {
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([
@@ -256,6 +272,48 @@ export function CompanySettings() {
)}
</div>
</div>
{/* Archive */}
<div className="space-y-4">
<div className="text-xs font-medium text-amber-700 uppercase tracking-wide">
Archive
</div>
<div className="space-y-3 rounded-md border border-amber-300/60 bg-amber-100/30 px-4 py-4">
<p className="text-sm text-muted-foreground">
Archive this company to hide it from the sidebar. This persists in the database.
</p>
<div className="flex items-center gap-2">
<Button
size="sm"
variant="outline"
disabled={archiveMutation.isPending || selectedCompany.status === "archived"}
onClick={() => {
if (!selectedCompanyId) return;
const confirmed = window.confirm(
`Archive company "${selectedCompany.name}"? It will be hidden from the sidebar.`,
);
if (!confirmed) return;
const nextCompanyId = companies.find((company) =>
company.id !== selectedCompanyId && company.status !== "archived")?.id ?? null;
archiveMutation.mutate({ companyId: selectedCompanyId, nextCompanyId });
}}
>
{archiveMutation.isPending
? "Archiving..."
: selectedCompany.status === "archived"
? "Already archived"
: "Archive company"}
</Button>
{archiveMutation.isError && (
<span className="text-xs text-destructive">
{archiveMutation.error instanceof Error
? archiveMutation.error.message
: "Failed to archive company"}
</span>
)}
</div>
</div>
</div>
</div>
);
}