diff options
Diffstat (limited to 'components/bidding-projects/bid-projects-container.tsx')
| -rw-r--r-- | components/bidding-projects/bid-projects-container.tsx | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/components/bidding-projects/bid-projects-container.tsx b/components/bidding-projects/bid-projects-container.tsx new file mode 100644 index 00000000..cae01b04 --- /dev/null +++ b/components/bidding-projects/bid-projects-container.tsx @@ -0,0 +1,107 @@ +"use client" + +import * as React from "react" +import { useRouter, usePathname, useSearchParams } from "next/navigation" +import { ChevronDown } from "lucide-react" + +import { Button } from "@/components/ui/button" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" +import { InformationButton } from "@/components/information/information-button" + +interface ProjectType { + id: string + name: string +} + +interface BidProjectsContainerProps { + projectTypes: ProjectType[] + children: React.ReactNode +} + +export function BidProjectsContainer({ + projectTypes, + children, +}: BidProjectsContainerProps) { + const router = useRouter() + const pathname = usePathname() + const searchParamsObj = useSearchParams() + + // useSearchParams를 메모이제이션하여 안정적인 참조 생성 + const searchParams = React.useMemo( + () => searchParamsObj || new URLSearchParams(), + [searchParamsObj] + ) + + // URL에서 현재 선택된 프로젝트 타입 가져오기 + const projectType = searchParams.get("type") || "all" + + // 선택한 프로젝트 타입에 해당하는 이름 찾기 + const selectedProject = projectTypes.find((project) => project.id === projectType)?.name || "전체" + + // 프로젝트 타입 변경 핸들러 + const handleProjectTypeChange = React.useCallback((value: string) => { + const params = new URLSearchParams(searchParams.toString()) + + if (value === "all") { + params.delete("type") + } else { + params.set("type", value) + } + + // 기존 필터를 제거하여 새로운 타입에 맞는 깨끗한 상태로 시작 + params.delete("filters") + + router.push(`${pathname}?${params.toString()}`) + }, [router, pathname, searchParams]) + + return ( + <> + {/* 상단 영역: 제목 왼쪽 / 프로젝트 타입 선택기 오른쪽 */} + <div className="flex items-center justify-between"> + {/* 왼쪽: 타이틀 & 설명 */} + <div> + <div className="flex items-center gap-2"> + <h2 className="text-2xl font-bold tracking-tight">견적 프로젝트 리스트</h2> + <InformationButton pagePath="evcp/bid-projects" /> + </div> + <p className="text-muted-foreground"> + 데이터 출처 - SHIP/HULL: From ECC(S-ERP), TOP: From NONSAP + </p> + </div> + + {/* 오른쪽: 프로젝트 타입 드롭다운 */} + <DropdownMenu> + <DropdownMenuTrigger asChild> + <Button variant="outline" className="min-w-[150px]"> + {selectedProject} + <ChevronDown className="ml-2 h-4 w-4" /> + </Button> + </DropdownMenuTrigger> + <DropdownMenuContent align="end" className="w-[200px]"> + {projectTypes.map((project) => ( + <DropdownMenuItem + key={project.id} + onClick={() => handleProjectTypeChange(project.id)} + className={project.id === projectType ? "bg-muted" : ""} + > + {project.name} + </DropdownMenuItem> + ))} + </DropdownMenuContent> + </DropdownMenu> + </div> + + {/* 컨텐츠 영역 */} + <section className="overflow-hidden"> + <div> + {children} + </div> + </section> + </> + ) +}
\ No newline at end of file |
