/** * Renders the "invitees" tab of a profile, which shows whom the user invited, * and whom they invited in turn. * * @module */ import { useMemo } from "react"; import { Link } from "react-router"; import { Trans } from "@lingui/react/macro"; import type { Invitee } from "../../../shared/user.ts"; import type { FetchState } from "../../hooks/shared/useFetchState.ts"; import { Avatar } from "../shared/Avatar.tsx"; import { ListState } from "../shared/ListState.tsx"; import { ProfileSection } from "./ProfileSection.tsx"; type InviteTreeNode = Invitee & { children: InviteTreeNode[] }; /** * Returns the invitees of `parentId` among `entries`, each with theirs. The * server answers the whole tree as a flat list. */ function buildInviteTree( entries: Invitee[], parentId: string, ): InviteTreeNode[] { return entries .filter((e) => e.invitedById === parentId) .map((e) => ({ ...e, children: buildInviteTree(entries, e.id) })); } /** Renders the invite tree, each invitee nested under who invited them. */ function InviteTreeList({ nodes }: { nodes: InviteTreeNode[] }) { return ( ); } /** Passed to {@link ProfileInviteesTab} by `UserPublicProfile`. */ export interface ProfileInviteesTabProps { userId: string; /** * Loaded when the tab is first opened, from * `GET /api/users/:username/invitees`. */ state: FetchState; } /** Renders the invitees of `userId` as a tree. */ export function ProfileInviteesTab( { userId, state }: ProfileInviteesTabProps, ): React.JSX.Element { const nodes = useMemo( () => state.status === "loaded" ? buildInviteTree(state.data, userId) : [], [state, userId], ); return ( Invitees}> data.length === 0} empty={

No invitees yet.

} > {() => }
); }