Files
silo-server/web/src/components/CrewList.tsx
T

70 lines
2.1 KiB
TypeScript

import ViewTransitionLink from "@/components/ViewTransitionLink";
import type { CrewMember } from "@/api/types";
import { buildPersonCatalogHref } from "@/pages/catalogSearchParams";
interface CrewListProps {
crew: CrewMember[];
}
interface CrewEntry {
name: string;
personId: string;
}
/** Jobs to display, in order. Others are ignored. */
const DISPLAY_JOBS = ["Director", "Writer", "Producer"] as const;
export default function CrewList({ crew }: CrewListProps) {
if (crew.length === 0) return null;
const grouped = new Map<string, CrewEntry[]>();
for (const member of crew) {
const existing = grouped.get(member.job);
const entry: CrewEntry = { name: member.name, personId: member.person_id };
if (existing) {
if (!existing.some((e) => e.name === member.name)) {
existing.push(entry);
}
} else {
grouped.set(member.job, [entry]);
}
}
const entries = DISPLAY_JOBS.filter((job) => grouped.has(job)).map((job) => ({
job: `${job}s`,
people: grouped.get(job)!,
}));
if (entries.length === 0) return null;
return (
<div>
<h2 className="mb-4 text-xl font-semibold">Crew</h2>
<dl className="glass-subtle grid grid-cols-[auto_1fr] gap-x-6 gap-y-3 rounded-xl px-5 py-4 text-sm">
{entries.map(({ job, people }) => (
<div key={job} className="contents">
<dt className="text-muted-foreground text-[13px] font-medium">{job}</dt>
<dd className="text-foreground/85 truncate">
{people.map((p, i) => (
<span key={p.name}>
{i > 0 && ", "}
{p.personId ? (
<ViewTransitionLink
to={buildPersonCatalogHref(p.personId)}
className="hover:text-primary transition-colors"
>
{p.name}
</ViewTransitionLink>
) : (
p.name
)}
</span>
))}
</dd>
</div>
))}
</dl>
</div>
);
}