diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-05-28 00:32:31 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-05-28 00:32:31 +0000 |
| commit | 20800b214145ee6056f94ca18fa1054f145eb977 (patch) | |
| tree | b5c8b27febe5b126e6d9ece115ea05eace33a020 /lib/pq/pq-review-table-new/user-combobox.tsx | |
| parent | e1344a5da1aeef8fbf0f33e1dfd553078c064ccc (diff) | |
(대표님) lib 파트 커밋
Diffstat (limited to 'lib/pq/pq-review-table-new/user-combobox.tsx')
| -rw-r--r-- | lib/pq/pq-review-table-new/user-combobox.tsx | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/lib/pq/pq-review-table-new/user-combobox.tsx b/lib/pq/pq-review-table-new/user-combobox.tsx new file mode 100644 index 00000000..0fb0e4c8 --- /dev/null +++ b/lib/pq/pq-review-table-new/user-combobox.tsx @@ -0,0 +1,122 @@ +"use client" + +import * as React from "react" +import { Check, ChevronsUpDown } from "lucide-react" + +import { cn } from "@/lib/utils" +import { Button } from "@/components/ui/button" +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, +} from "@/components/ui/command" +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover" + +interface User { + id: number + name: string + email: string + department?: string +} + +interface UserComboboxProps { + users: User[] + value: number | null + onChange: (value: number) => void + placeholder?: string + disabled?: boolean +} + +export function UserCombobox({ + users, + value, + onChange, + placeholder = "담당자 선택...", + disabled = false +}: UserComboboxProps) { + const [open, setOpen] = React.useState(false) + const [inputValue, setInputValue] = React.useState("") + + const selectedUser = React.useMemo(() => { + return users.find(user => user.id === value) + }, [users, value]) + + return ( + <Popover open={open} onOpenChange={setOpen}> + <PopoverTrigger asChild> + <Button + variant="outline" + role="combobox" + aria-expanded={open} + className={cn( + "w-full justify-between", + !value && "text-muted-foreground" + )} + disabled={disabled} + > + {selectedUser ? ( + <span className="flex items-center"> + <span className="font-medium">{selectedUser.name}</span> + {selectedUser.department && ( + <span className="ml-2 text-xs text-muted-foreground"> + ({selectedUser.department}) + </span> + )} + </span> + ) : ( + placeholder + )} + <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" /> + </Button> + </PopoverTrigger> + <PopoverContent className="w-[300px] p-0"> + <Command> + <CommandInput + placeholder="담당자 검색..." + value={inputValue} + onValueChange={setInputValue} + /> + <CommandEmpty>검색 결과가 없습니다.</CommandEmpty> + <CommandGroup className="max-h-[200px] overflow-y-auto"> + {users.map((user) => ( + <CommandItem + key={user.id} + value={user.email} // 이메일을 value로 사용 + onSelect={() => { + onChange(user.id) + setOpen(false) + }} + > + <Check + className={cn( + "mr-2 h-4 w-4", + value === user.id ? "opacity-100" : "opacity-0" + )} + /> + <div className="flex flex-col truncate"> + <div className="flex items-center"> + <span className="font-medium">{user.name}</span> + {user.department && ( + <span className="ml-2 text-xs text-muted-foreground"> + ({user.department}) + </span> + )} + </div> + <span className="text-xs text-muted-foreground truncate"> + {user.email} + </span> + </div> + </CommandItem> + ))} + </CommandGroup> + </Command> + </PopoverContent> + </Popover> + ) +}
\ No newline at end of file |
