RegistryUI recipes
My work
What waits on the caller across the installed blocks, from `loadMyWork`: assigned work, approvals, due reminders, mentions and SLA warnings, each linked to its record.
It loads its data on the server through the block's client; the subjects, work-items, approvals, reminders, comments blocks must be installed (npx better-supabase add subjects work-items approvals reminders comments). Its page on bettersupabase.com is /recipes/my-work.
Web, with shadcn components:
npx shadcn add alert badge button card empty skeleton/**
* Render inside `<Suspense>`: everything that waits on the caller, from
* `loadMyWork`, newest first.
*/
export async function MyWorkList() {
const [work, t, format] = await Promise.all([
getMyWork(),
getExtracted("myWork"),
getFormatter(),
]);
if (work.kind === "no-organization") {
return null;
}
const kindLabel = (kind: MyWorkKind): string => {
switch (kind) {
case "assigned": {
return t("Assigned");
}
case "approval": {
return t("Approval");
}
case "reminder": {
return t("Reminder");
}
case "mention": {
return t("Mention");
}
case "sla": {
return t("SLA warning");
}
default: {
const never: never = kind;
return never;
}
}
};
return (
<Card data-recipe="my-work">
<CardHeader>
<CardTitle>{t("Waiting on you")}</CardTitle>
<CardDescription>
{t(
"Assigned work, approvals, due reminders, mentions and SLA warnings.",
)}
</CardDescription>
</CardHeader>
<CardContent>
{work.kind === "error" ? (
<Alert variant="destructive">
<TriangleAlertIcon />
<AlertTitle>{t("My work didn't load")}</AlertTitle>
<AlertDescription>{t("Try again in a moment.")}</AlertDescription>
<AlertAction>
<form action={retryMyWork}>
<Button size="sm" variant="outline" type="submit">
{t("Retry")}
</Button>
</form>
</AlertAction>
</Alert>
) : work.data.rows.length === 0 ? (
<Empty className="border">
<EmptyHeader>
<EmptyMedia variant="icon">
<InboxIcon />
</EmptyMedia>
<EmptyTitle>{t("Nothing waiting on you")}</EmptyTitle>
<EmptyDescription>
{t("Work assigned to you and requests for you show up here.")}
</EmptyDescription>
</EmptyHeader>
<EmptyContent>
<Link
href="/work"
className={buttonVariants({ variant: "outline", size: "sm" })}
>
{t("Open the work board")}
</Link>
</EmptyContent>
</Empty>
) : (
<ul className="flex flex-col gap-1">
{work.data.rows.map((row) => (
<li key={row.key} className="flex items-center gap-2 text-sm">
<Badge variant={BADGES[row.kind]}>{kindLabel(row.kind)}</Badge>
{row.url === null ? (
<span className="truncate">{row.title}</span>
) : (
<Link
href={row.url}
className="truncate font-medium underline-offset-4 transition-colors hover:underline"
>
{row.title}
</Link>
)}
{row.at === null ? null : (
<time
dateTime={new Date(row.at).toISOString()}
className="ml-auto shrink-0 text-xs text-muted-foreground tabular-nums"
>
{format.relativeTime(row.at)}
</time>
)}
</li>
))}
</ul>
)}
</CardContent>
</Card>
);
}Last updated on