Menu
popagent
publicLatest change fadf21d1cd584745f6f92eaa60509e0bef19d242 - fix task orchestration and compact overview cards by AkurAI Build
import { useEffect, useState } from "react";
import { Building2, Mail, Users } from "lucide-react";
import type { CompanyDepartment, CompanyRosterResponse } from "../api-types";
import { apiFetch } from "./api";
export function CompanyRosterPanel() {
const [departments, setDepartments] = useState<CompanyDepartment[]>();
const [error, setError] = useState("");
useEffect(() => {
let active = true;
void apiFetch("/api/company")
.then(async (response) => {
if (!response.ok) throw new Error("Unable to load company roster");
const result = (await response.json()) as CompanyRosterResponse;
if (active) setDepartments(result.departments);
})
.catch((reason: unknown) => {
if (active) setError(reason instanceof Error ? reason.message : "Unable to load company roster");
});
return () => { active = false; };
}, []);
return <div className="w-full">
<div className="flex flex-wrap items-end justify-between gap-3">
<div>
<div className="mb-2 flex items-center gap-2 text-xs font-medium uppercase tracking-[0.16em] text-accent"><Building2 className="size-4" />AkurAI company</div>
<h1 className="text-xl font-semibold">Departments and staff</h1>
<p className="mt-1 max-w-3xl text-sm text-ink-dim">Organizational identities recovered from the Midget staff directory. These people form company squads; they do not create additional LLM execution loops.</p>
</div>
{departments ? <span className="rounded-full border border-line bg-panel px-3 py-1.5 text-xs text-ink-muted"><Users className="mr-1.5 inline size-3.5" />{departments.reduce((count, department) => count + department.members.length, 0)} staff · {departments.length} departments</span> : null}
</div>
{error ? <div role="alert" className="mt-6 rounded border border-red-500/30 bg-red-500/10 p-4 text-sm text-red-400">{error}</div> : departments ? <div className="mt-6 grid items-start gap-4 xl:grid-cols-2">
{departments.map((department) => <section key={department.id} className="overflow-hidden rounded border border-line bg-panel">
<header className="flex items-center justify-between border-b border-line bg-panel-2 px-4 py-3">
<h2 className="font-medium">{department.name}</h2>
<span className="text-xs tabular-nums text-ink-dim">{department.members.length}</span>
</header>
<ul className="divide-y divide-line">
{department.members.map((member) => <li key={member.id} className="flex min-w-0 items-center gap-3 px-4 py-3">
<img src={member.avatarUrl} alt="" className="size-12 shrink-0 rounded-full border border-line object-cover bg-bg" />
<div className="min-w-0 flex-1">
<div className="truncate text-sm font-medium text-ink">{member.name}</div>
<div className="truncate text-xs text-ink-muted">{member.title}</div>
</div>
<a href={`mailto:${member.email}`} aria-label={`Email ${member.name}`} className="flex size-10 shrink-0 items-center justify-center rounded text-ink-dim hover:bg-accent-soft hover:text-ink"><Mail className="size-4" /></a>
</li>)}
</ul>
</section>)}
</div> : <div className="mt-6 text-sm text-ink-dim">Loading company roster…</div>}
</div>;
}