1import type { EnvironmentId, EnvironmentMachineKind } from "@t3tools/contracts";
2
3import type { SidebarProjectSnapshot } from "~/sidebarProjectGrouping";
4import { EnvironmentMachineIcon } from "./EnvironmentMachineIcon";
5import { Tooltip, TooltipPopup, TooltipTrigger } from "./ui/tooltip";
6
7export function ProjectEnvironmentBadge(props: {
8 readonly group: Pick<SidebarProjectSnapshot, "memberProjects">;
9 readonly primaryEnvironmentId: EnvironmentId | null;
10 readonly machineByEnvironmentId: ReadonlyMap<EnvironmentId, EnvironmentMachineKind>;
11}) {
12 const remoteMembers = props.group.memberProjects
13 .filter((member) => member.environmentId !== props.primaryEnvironmentId)
14 .map((member) => ({ ...member, environmentLabel: member.environmentLabel ?? "Remote" }))
15 .sort((a, b) => a.environmentLabel.localeCompare(b.environmentLabel));
16 const first = remoteMembers[0];
17 if (!first) return null;
18 const labels = remoteMembers
19 .map((member) => member.environmentLabel)
20 .filter((label, index, all) => all.indexOf(label) === index)
21 .join(", ");
22 const alsoHere = remoteMembers.length < props.group.memberProjects.length;
23 const description = `${alsoHere ? "Also on" : "On"} ${labels}`;
24 return (
25 <Tooltip>
26 <TooltipTrigger
27 render={
28 <span
29 role="img"
30 aria-label={description}
31 className="inline-flex shrink-0 items-center text-muted-foreground"
32 />
33 }
34 >
35 <EnvironmentMachineIcon
36 aria-hidden
37 kind={props.machineByEnvironmentId.get(first.environmentId) ?? "server"}
38 className="size-3.5"
39 />
40 </TooltipTrigger>
41 <TooltipPopup side="top">{description}</TooltipPopup>
42 </Tooltip>
43 );
44}