feat(housekeeping): deliver people account workflows

This commit is contained in:
Simo committed 2026-08-29 11:45:50 +02:00
1 parent 7920d4f46c
commit e1b31ff773
45 files changed
+4290 -1243

No files matched your search

@@ -0,0 +1,83 @@
import { PERMS } from "@/lib/permission-slugs";
import {
createCorrelationId,
fail,
type HousekeepingCapabilityContext,
type HousekeepingResult,
} from "../../../foundation/contracts";
import type { HousekeepingPageInput } from "../../../route-handlers";
import { type PeopleStaffQueryData, peopleStaffQuery } from "../queries/staff";
import { PeoplePageFrame } from "./page-state";
interface PeopleStaffPageProps {
readonly context: HousekeepingCapabilityContext;
readonly result?: HousekeepingResult<PeopleStaffQueryData>;
readonly partialDependencies?: readonly string[];
}
export function PeopleStaffPage({
context,
result,
partialDependencies,
}: PeopleStaffPageProps) {
return (
<PeoplePageFrame
title="Staff"
description="Review staff applications and team definitions."
result={result}
partialDependencies={partialDependencies}
isEmpty={(data) => data.page.items.length === 0}
>
{(data) =>
data.kind === "applications" ? (
<ul className="space-y-2">
{data.page.items.map((application) => (
<li
key={application.id}
className="rounded-lg border border-[var(--admin-border)] bg-[var(--admin-surface)] p-4"
>
<h2>{application.username ?? `User #${application.userId}`}</h2>
<p>{application.content}</p>
{context.has(PERMS.USERS_EDIT) ? (
<span data-housekeeping-command="people.application.decide">
Dismiss application
</span>
) : null}
</li>
))}
</ul>
) : data.kind === "teams" ? (
<ul className="space-y-2">
{data.page.items.map((team) => (
<li
key={team.id}
className="rounded-lg border border-[var(--admin-border)] bg-[var(--admin-surface)] p-4"
>
<h2>{team.name}</h2>
<p>{team.jobDescription ?? "No job description"}</p>
{context.has(PERMS.USERS_EDIT) ? (
<span data-housekeeping-command="people.team.change">
Team controls
</span>
) : null}
</li>
))}
</ul>
) : null
}
</PeoplePageFrame>
);
}
export async function renderPeopleStaffPage(input: HousekeepingPageInput) {
const routeId = input.match.routeId;
const result =
routeId === "people.staff.applications" || routeId === "people.staff.teams"
? await peopleStaffQuery.run(input.context, { routeId, list: {} })
: fail(
"NOT_FOUND",
"errors.housekeeping.notFound",
createCorrelationId(),
);
return <PeopleStaffPage context={input.context} result={result} />;
}