# Employee directory

> A searchable list of employees with an org chart of who reports to whom.

Source: https://bettersupabase.com/docs/registry/ui-recipes/employee-directory

{/* Generated by scripts/build-recipes.ts from the example apps. Edit the examples or the script, then run `pnpm recipes`. */}

It loads its data on the server through the block's client; the [employees block](https://bettersupabase.com/blocks/employees) must be installed (`npx better-supabase add employees`). Its page on bettersupabase.com is [/recipes/employee-directory](https://bettersupabase.com/recipes/employee-directory).

Web, with shadcn components:

```bash
npx shadcn add card empty skeleton
```

```tsx title="apps/examples/nextjs/src/features/people/components/employee-directory.tsx"
/**
 * 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>
  );
}
```