feat(card): distinguish anonymous submissions on the card page

Phase 8a Task 13. CardSubmittedBy renders nothing for 'owner',
'Requested' for 'client', and 'Submitted via public link' for
'anonymous'. Renders nothing once the card is accepted. Replaces the
inline client-only check on the card detail page.
This commit is contained in:
Dave 2026-09-21 02:27:13 +02:00
parent 07ece87de5
commit bb78c9b56f
2 changed files with 51 additions and 4 deletions

View file

@ -13,6 +13,7 @@ import { SubtaskList } from "@/components/card/subtask-list";
import { CommentThread } from "@/components/card/comment-thread";
import { ActivityTimeline } from "@/components/card/activity-timeline";
import { Pill } from "@/components/ui/pill";
import { CardSubmittedBy } from "@/components/card/card-submitted-by";
import { getSession } from "@/lib/auth/session";
import { loadCardDetail } from "@/lib/data/card";
@ -54,9 +55,11 @@ export default async function CardPage({
Back to board
</Link>
<Pill tone="neutral">{detail.column.name}</Pill>
{!detail.card.accepted &&
detail.card.created_by_role === "client" && (
<Pill tone="brand">Requested</Pill>
{!detail.card.accepted && (
<CardSubmittedBy
role={detail.card.created_by_role}
accepted={detail.card.accepted}
/>
)}
</div>

View file

@ -0,0 +1,44 @@
import { Inbox } from "lucide-react";
import { Pill } from "@/components/ui/pill";
import type { CreatedByRole } from "@/lib/pb/types";
/**
* How a card arrived.
*
* Renders nothing for `owner` (the developer made it themselves; no badge
* needed). Renders a "Requested" pill for `client` and a "Public link"
* pill for `anonymous`, distinguishing the two in the developer's view
* without exposing any submitter identity (which the public route does not
* collect anyway).
*
* The pill is part of the existing header strip on the card detail page
* rather than a new section, because the card is otherwise identical
* regardless of how it arrived.
*/
export function CardSubmittedBy({
role,
accepted,
}: {
role: CreatedByRole;
accepted: boolean;
}) {
if (accepted) return null;
if (role === "owner") return null;
if (role === "anonymous") {
return (
<Pill tone="brand">
<Inbox size={11} strokeWidth={2} />
Submitted via public link
</Pill>
);
}
return (
<Pill tone="brand">
<Inbox size={11} strokeWidth={2} />
Requested
</Pill>
);
}