"use client" import * as React from "react" import { cn } from "@/lib/utils" import { Button } from "@/components/ui/button" import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from "@/components/ui/command" import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover" import { Check, ChevronsUpDown, Loader2 } from "lucide-react" interface ContractInfo { contractId: number contractName: string } interface ProjectInfo { projectId: number projectCode: string projectName: string contracts: ContractInfo[] } interface ProjectSwitcherProps { isCollapsed: boolean projects: ProjectInfo[] // 상위가 관리하는 "현재 선택된 contractId" selectedContractId: number | null // 콜백: 사용자가 "어떤 contract"를 골랐는지 // => 우리가 projectId도 찾아서 상위 state를 같이 갱신해야 함 onSelectContract: (projectId: number, contractId: number) => void // 로딩 상태 (선택사항) isLoading?: boolean } export function ProjectSwitcher({ isCollapsed, projects, selectedContractId, onSelectContract, isLoading = false, }: ProjectSwitcherProps) { const [popoverOpen, setPopoverOpen] = React.useState(false) const [searchTerm, setSearchTerm] = React.useState("") // 현재 선택된 contract 객체 찾기 const selectedContract = React.useMemo(() => { if (!selectedContractId) return null for (const proj of projects) { const found = proj.contracts.find((c) => c.contractId === selectedContractId) if (found) { return { ...found, projectId: proj.projectId, projectName: proj.projectName } } } return null }, [projects, selectedContractId]) // Trigger label => 계약 이름 or placeholder const triggerLabel = selectedContract?.contractName ?? "Select a contract" // 검색어에 따른 필터링된 프로젝트/계약 목록 const filteredProjects = React.useMemo(() => { if (!searchTerm) return projects return projects.map(project => ({ ...project, contracts: project.contracts.filter(contract => contract.contractName.toLowerCase().includes(searchTerm.toLowerCase()) || project.projectName.toLowerCase().includes(searchTerm.toLowerCase()) ) })).filter(project => project.contracts.length > 0) }, [projects, searchTerm]) // 계약 선택 핸들러 function handleSelectContract(projectId: number, contractId: number) { onSelectContract(projectId, contractId) setPopoverOpen(false) setSearchTerm("") // 검색어 초기화 } // 총 계약 수 계산 (빈 상태 표시용) const totalContracts = filteredProjects.reduce((sum, project) => sum + project.contracts.length, 0) return ( { e.stopPropagation() // 이벤트 전파 차단 const target = e.currentTarget target.scrollTop += e.deltaY // 직접 스크롤 처리 }} > {totalContracts === 0 ? "No contracts found." : "No search results."} {filteredProjects.map((project) => ( {project.contracts.map((contract) => ( handleSelectContract(project.projectId, contract.contractId)} value={`${project.projectName} ${contract.contractName}`} className="truncate" title={contract.contractName} > {contract.contractName} ))} ))} ) }