"use client"; import * as React from "react"; import { useMemo } from "react"; import * as Popover from "@radix-ui/react-popover"; import { Check, Search } from "lucide-react"; import { cn } from "@/lib/utils"; import { api } from "@/lib/trpc"; import { Avatar, AvatarFallback, AvatarImage, } from "@/components/ui/avatar"; import { Input } from "@/components/ui/input"; export interface WorkspaceUser { id: string; name: string; avatarUrl?: string | null; } /** Internal default for prop comparison only; list comes from `listMembers` when `workspaceId` is set */ const WORKSPACE_USERS: WorkspaceUser[] = [ { id: "u1", name: "Alice", avatarUrl: null }, { id: "u2", name: "Bob", avatarUrl: null }, { id: "u3", name: "Charlie", avatarUrl: null }, { id: "u4", name: "Diana", avatarUrl: null }, ]; function initials(name: string) { return name .split(/\s+/) .map((p) => p[0]) .join("") .slice(0, 2) .toUpperCase(); } export interface AssigneePickerProps { open: boolean; onOpenChange: (open: boolean) => void; assignedIds: string[]; onToggle: (userId: string) => void; users?: WorkspaceUser[]; workspaceHandle?: string; children: React.ReactNode; side?: "top" | "right" | "bottom" | "left"; align?: "start" | "center" | "end"; } export function AssigneePicker({ open, onOpenChange, assignedIds, onToggle, users = WORKSPACE_USERS, workspaceHandle, children, side = "bottom", align = "start", }: AssigneePickerProps) { const { data: members } = api.workspaces.listMembers.useQuery( { workspace: workspaceHandle! }, { enabled: Boolean(workspaceHandle) }, ); const resolvedUsers = useMemo(() => { if (users && users !== WORKSPACE_USERS) return users; if (!members) return []; return members.map((m) => ({ id: m.id, name: m.name ?? m.email, avatarUrl: m.avatarUrl, })); }, [users, members]); const [q, setQ] = React.useState(""); const filtered = React.useMemo(() => { const s = q.trim().toLowerCase(); if (!s) return resolvedUsers; return resolvedUsers.filter((u) => u.name.toLowerCase().includes(s)); }, [q, resolvedUsers]); React.useEffect(() => { if (!open) setQ(""); }, [open]); return ( {children}
setQ(e.target.value)} placeholder="Search people…" className="h-8 border-0 bg-muted/50 pl-8 text-xs focus-visible:ring-1" />
{filtered.length === 0 ? (

No matches

) : ( filtered.map((user) => { const assigned = assignedIds.includes(user.id); return ( ); }) )}
); }