diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-03-26 00:37:41 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-03-26 00:37:41 +0000 |
| commit | e0dfb55c5457aec489fc084c4567e791b4c65eb1 (patch) | |
| tree | 68543a65d88f5afb3a0202925804103daa91bc6f /components/documents/project-swicher.tsx | |
3/25 까지의 대표님 작업사항
Diffstat (limited to 'components/documents/project-swicher.tsx')
| -rw-r--r-- | components/documents/project-swicher.tsx | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/components/documents/project-swicher.tsx b/components/documents/project-swicher.tsx new file mode 100644 index 00000000..5c70ea88 --- /dev/null +++ b/components/documents/project-swicher.tsx @@ -0,0 +1,138 @@ +"use client" + +import * as React from "react" +import { cn } from "@/lib/utils" +import { + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectLabel, + SelectTrigger, + SelectValue, +} from "@/components/ui/select" + +interface PackageItem { + itemId: number + itemName: string +} + +interface ContractInfo { + contractId: number + contractNo: string + contractName: string + packages: PackageItem[] +} + +export interface ProjectInfo { + projectId: number + projectCode: string + projectName: string + projectType: string + contracts: ContractInfo[] +} + +interface ProjectSwitcherProps { + isCollapsed: boolean + projects: ProjectInfo[] + + // 상위가 관리하는 "현재 선택된 contractId" + selectedContractId: number | null + + // 콜백: 사용자가 "어떤 contract"를 골랐는지 + onSelectContract: (projectId: number, contractId: number) => void +} + +/** + * ProjectSwitcher: + * - 프로젝트들(contracts 포함)을 그룹화하여 Select 표시 + * - 너무 긴 계약명 등을 ellipsis로 축약 + */ +export function ProjectSwitcher({ + isCollapsed, + projects, + selectedContractId, + onSelectContract, +}: ProjectSwitcherProps) { + // Select value = stringified contractId + const selectValue = selectedContractId ? String(selectedContractId) : "" + + // 현재 선택된 계약 정보를 찾기 + 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 } + } + } + return null + }, [projects, selectedContractId]) + + // Trigger Label => 계약 이름 or "Select a contract" + const triggerLabel = selectedContract?.contractName ?? "Select a contract" + + function handleValueChange(val: string) { + const contractId = Number(val) + let foundProjectId = 0 + + for (const proj of projects) { + const found = proj.contracts.find((c) => c.contractId === contractId) + if (found) { + foundProjectId = proj.projectId + break + } + } + onSelectContract(foundProjectId, contractId) + } + + return ( + <Select value={selectValue} onValueChange={handleValueChange}> + {/* + 아래 SelectTrigger에 max-w, whitespace-nowrap, overflow-hidden, text-ellipsis 적용 + 가로폭이 200px 넘어가면 "…" 으로 표시 + */} + <SelectTrigger + className={cn( + "flex items-center gap-2", + isCollapsed && "flex h-9 w-9 shrink-0 items-center justify-center p-0", + "max-w-[300px] whitespace-nowrap overflow-hidden text-ellipsis" + )} + aria-label="Select Contract" + > + <SelectValue placeholder="Select a contract"> + {/* 실제 표시부분에도 ellipsis 처리. */} + <span + className={cn( + "ml-2 block max-w-[250px] truncate", + isCollapsed && "hidden" + )} + > + {triggerLabel} + </span> + </SelectValue> + </SelectTrigger> + + <SelectContent> + {projects.map((project) => ( + <SelectGroup key={project.projectCode}> + {/* 프로젝트명 표시 */} + <SelectLabel> + {/* 필요하다면 projectCode만 보이도록 하는 등 조정 가능 */} + {project.projectName} + </SelectLabel> + {project.contracts.map((contract) => ( + <SelectItem + key={contract.contractId} + value={String(contract.contractId)} + > + {/* 계약명 + 계약번호 등 원하는 형식 */} + {contract.contractName} ({contract.contractNo}) + </SelectItem> + ))} + </SelectGroup> + ))} + </SelectContent> + </Select> + ) +}
\ No newline at end of file |
