RegistryUI recipes
Employee directory
A searchable list of employees with an org chart of who reports to whom.
It loads its data on the server through the block's client; the employees block must be installed (npx better-supabase add employees). Its page on bettersupabase.com is /recipes/employee-directory.
Web, with shadcn components:
npx shadcn add card empty skeleton/**
* Render inside `<Suspense>`: the employees as an org chart, each manager above
* their reports, with a search. Private details open in a sheet for callers
* with `employees.view_sensitive`.
*/
export async function EmployeeDirectory() {
const [session, t] = await Promise.all([
getSession(),
getExtracted("people"),
]);
if (!can(session, "employees.read")) {
forbidden();
}
const directory = await settle(loadDirectory);
if (directory.kind === "no-organization") {
return null;
}
const canWrite = can(session, "employees.write");
const canViewSensitive = can(session, "employees.view_sensitive");
const managers =
directory.kind === "ok"
? directory.data.map((employee) => ({
value: employee.id,
label: employee.name,
}))
: [];
const addEmployee = canWrite ? (
<AddEmployeeDialog
managers={managers}
canViewSensitive={canViewSensitive}
/>
) : null;
return (
<Card data-recipe="employee-directory">
<CardHeader>
<CardTitle>{t("Employees")}</CardTitle>
<CardDescription>
{t("Everyone in the organization and who they report to.")}
</CardDescription>
{addEmployee && managers.length > 0 ? (
<CardAction>{addEmployee}</CardAction>
) : null}
</CardHeader>
<CardContent>
{directory.kind === "error" ? (
<PeopleLoadError title={t("The directory didn't load")} />
) : directory.data.length === 0 ? (
<Empty className="border">
<EmptyHeader>
<EmptyMedia variant="icon">
<UsersIcon />
</EmptyMedia>
<EmptyTitle>{t("No employees yet")}</EmptyTitle>
<EmptyDescription>
{canWrite
? t("Add the first employee to start the org chart.")
: t("Ask an admin to add employees.")}
</EmptyDescription>
</EmptyHeader>
{addEmployee ? <EmptyContent>{addEmployee}</EmptyContent> : null}
</Empty>
) : (
<EmployeeTable
employees={directory.data}
canViewSensitive={canViewSensitive}
/>
)}
</CardContent>
</Card>
);
}Last updated on