summaryrefslogtreecommitdiff
path: root/components/documents/project-swicher.tsx
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-03-25 15:55:45 +0900
committerjoonhoekim <26rote@gmail.com>2025-03-25 15:55:45 +0900
commit1a2241c40e10193c5ff7008a7b7b36cc1d855d96 (patch)
tree8a5587f10ca55b162d7e3254cb088b323a34c41b /components/documents/project-swicher.tsx
initial commit
Diffstat (limited to 'components/documents/project-swicher.tsx')
-rw-r--r--components/documents/project-swicher.tsx138
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