import { Ellipsis } from "lucide-react"; import { useState } from "react"; import { Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger } from "~/components/menu"; import Delete from "../dialogs/delete-user"; import LinkUser from "../dialogs/link-user"; import Reassign from "../dialogs/reassign-user"; import TransferOwnership from "../dialogs/transfer-ownership"; import type { HeadplaneUserData } from "../overview"; interface MenuProps { user: HeadplaneUserData; headscaleUsers: { id: string; name: string; claimed: boolean }[]; currentLink?: string; isSelf?: boolean; isOwner?: boolean; } type Modal = "delete" | "reassign" | "link" | "transfer" | null; export default function UserMenu({ user, headscaleUsers, currentLink, isSelf, isOwner, }: MenuProps) { const [modal, setModal] = useState(null); const isLinked = currentLink !== undefined; const disabledKeys: string[] = []; if (!isLinked) { disabledKeys.push("reassign"); } // Filter linkable users: unclaimed, or the one currently linked to this user const linkableUsers = headscaleUsers.filter((u) => !u.claimed || u.id === currentLink); const displayName = user.linkedHeadscaleUser?.displayName || user.name || user.email || user.sub; return ( <> {modal === "delete" && user.linkedHeadscaleUser && ( { if (!isOpen) setModal(null); }} user={user.linkedHeadscaleUser} /> )} {modal === "reassign" && ( { if (!isOpen) setModal(null); }} userId={user.linkedHeadscaleUser?.id ?? user.id} /> )} {modal === "link" && ( { if (!isOpen) setModal(null); }} userId={user.linkedHeadscaleUser?.id ?? user.id} /> )} {modal === "transfer" && ( { if (!isOpen) setModal(null); }} targetDisplayName={displayName} targetUserId={user.linkedHeadscaleUser?.id ?? user.id} /> )} setModal("reassign")} > Change role setModal("link")}> {isLinked ? "Change linked user" : "Link Headscale user"} {isOwner && !isSelf && ( <> setModal("transfer")}> Transfer ownership )} {user.linkedHeadscaleUser && !isSelf && ( <> setModal("delete")}> Delete )} ); }