From 5adc1df95f80fbec7a0b5bbee15448b10d5aec3a Mon Sep 17 00:00:00 2001 From: 0-Zz-ang Date: Sun, 17 Aug 2025 23:05:19 +0900 Subject: (박서영)evcp/document-list-only, evcp/vendor-data 생성 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/vendor-data/vendor-data-container.tsx | 270 +++++++---------------- 1 file changed, 74 insertions(+), 196 deletions(-) (limited to 'components/vendor-data/vendor-data-container.tsx') diff --git a/components/vendor-data/vendor-data-container.tsx b/components/vendor-data/vendor-data-container.tsx index a549594c..3974b791 100644 --- a/components/vendor-data/vendor-data-container.tsx +++ b/components/vendor-data/vendor-data-container.tsx @@ -1,63 +1,42 @@ "use client" import * as React from "react" -import { TooltipProvider } from "@/components/ui/tooltip" +import { usePathname, useRouter, useSearchParams, useParams } from "next/navigation" +import { useAtom } from "jotai" +import { selectedModeAtom } from "@/atoms" +import { Sidebar } from "./sidebar" +import { ProjectSwitcher } from "./project-swicher" import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "@/components/ui/resizable" import { cn } from "@/lib/utils" -import { ProjectSwitcher } from "./project-swicher" -import { Sidebar } from "./sidebar" -import { usePathname, useRouter, useSearchParams, useParams } from "next/navigation" -import { getFormsByContractItemId, type FormInfo } from "@/lib/forms/services" import { Separator } from "@/components/ui/separator" import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs" -import { ScrollArea } from "@/components/ui/scroll-area" import { Button } from "@/components/ui/button" -import { FormInput } from "lucide-react" -import { Skeleton } from "@/components/ui/skeleton" -import { selectedModeAtom } from '@/atoms' -import { useAtom } from 'jotai' +import { TooltipProvider } from "@/components/ui/tooltip" interface PackageData { itemId: number itemName: string } -interface ContractData { - contractId: number - contractName: string - packages: PackageData[] -} - -interface ProjectData { - projectId: number - projectCode: string - projectName: string - projectType: string - contracts: ContractData[] -} - interface VendorDataContainerProps { - projects: ProjectData[] + projects: { + projectId: number + projectCode: string + projectName: string + projectType: string + contracts: { + contractId: number + contractNo: string + contractName: string + packages: PackageData[] + }[] + }[] defaultLayout?: number[] defaultCollapsed?: boolean - navCollapsedSize: number + navCollapsedSize?: number children: React.ReactNode } -function getTagIdFromPathname(path: string | null): number | null { - if (!path) return null; - - // 태그 패턴 검사 (/tag/123) - const tagMatch = path.match(/\/tag\/(\d+)/) - if (tagMatch) return parseInt(tagMatch[1], 10) - - // 폼 패턴 검사 (/form/123/...) - const formMatch = path.match(/\/form\/(\d+)/) - if (formMatch) return parseInt(formMatch[1], 10) - - return null -} - export function VendorDataContainer({ projects, defaultLayout = [20, 80], @@ -71,8 +50,6 @@ export function VendorDataContainer({ const params = useParams() const currentLng = params?.lng as string || 'en' - const tagIdNumber = getTagIdFromPathname(pathname) - // 기본 상태 const [selectedProjectId, setSelectedProjectId] = React.useState(projects[0]?.projectId || 0) const [isCollapsed, setIsCollapsed] = React.useState(defaultCollapsed) @@ -80,15 +57,12 @@ export function VendorDataContainer({ projects[0]?.contracts[0]?.contractId || 0 ) const [selectedPackageId, setSelectedPackageId] = React.useState(null) - const [formList, setFormList] = React.useState([]) - const [selectedFormCode, setSelectedFormCode] = React.useState(null) - const [isLoadingForms, setIsLoadingForms] = React.useState(false) // 현재 선택된 프로젝트/계약/패키지 const currentProject = projects.find((p) => p.projectId === selectedProjectId) ?? projects[0] const currentContract = currentProject?.contracts.find((c) => c.contractId === selectedContractId) ?? currentProject?.contracts[0] - + // 프로젝트 타입 확인 - ship인 경우 항상 ENG 모드 const isShipProject = currentProject?.projectType === "ship" @@ -104,31 +78,6 @@ export function VendorDataContainer({ React.useEffect(() => { setSelectedMode(initialMode as "IM" | "ENG") }, [initialMode, setSelectedMode]) - - const isTagOrFormRoute = pathname ? (pathname.includes("/tag/") || pathname.includes("/form/")) : false - const currentPackageName = isTagOrFormRoute - ? currentContract?.packages.find((pkg) => pkg.itemId === selectedPackageId)?.itemName || "None" - : "None" - - // 폼 목록에서 고유한 폼 이름만 추출 - const formNames = React.useMemo(() => { - return [...new Set(formList.map((form) => form.formName))] - }, [formList]) - - // URL에서 현재 폼 코드 추출 - const getCurrentFormCode = (path: string): string | null => { - const segments = path.split("/").filter(Boolean) - const formIndex = segments.indexOf("form") - if (formIndex !== -1 && segments[formIndex + 2]) { - return segments[formIndex + 2] - } - return null - } - - const currentFormCode = React.useMemo(() => { - return pathname ? getCurrentFormCode(pathname) : null - }, [pathname]) - // URL에서 모드가 변경되면 상태도 업데이트 (ship 프로젝트가 아닐 때만) React.useEffect(() => { @@ -152,23 +101,7 @@ export function VendorDataContainer({ } }, [isShipProject, router]) - // (1) 새로고침 시 URL 파라미터(tagIdNumber) → selectedPackageId 세팅 - React.useEffect(() => { - if (!currentContract) return - - if (tagIdNumber) { - setSelectedPackageId(tagIdNumber) - } else { - // tagIdNumber가 없으면, 현재 계약의 첫 번째 패키지로 - if (currentContract.packages?.length) { - setSelectedPackageId(currentContract.packages[0].itemId) - } else { - setSelectedPackageId(null) - } - } - }, [tagIdNumber, currentContract]) - - // (2) 프로젝트 변경 시 계약 초기화 + // (1) 프로젝트 변경 시 계약 초기화 React.useEffect(() => { if (currentProject?.contracts.length) { setSelectedContractId(currentProject.contracts[0].contractId) @@ -177,38 +110,6 @@ export function VendorDataContainer({ } }, [currentProject]) - // (3) 패키지 ID와 모드가 변경될 때마다 폼 로딩 - React.useEffect(() => { - const packageId = getTagIdFromPathname(pathname) - - if (packageId) { - setSelectedPackageId(packageId) - - // URL에서 패키지 ID를 얻었을 때 즉시 폼 로드 - loadFormsList(packageId, selectedMode); - } else if (currentContract?.packages?.length) { - const firstPackageId = currentContract.packages[0].itemId; - setSelectedPackageId(firstPackageId); - loadFormsList(firstPackageId, selectedMode); - } - }, [pathname, currentContract, selectedMode]) - - // 모드에 따른 폼 로드 함수 - const loadFormsList = async (packageId: number, mode: "IM" | "ENG") => { - if (!packageId) return; - - setIsLoadingForms(true); - try { - const result = await getFormsByContractItemId(packageId, mode); - setFormList(result.forms || []); - } catch (error) { - console.error(`폼 로딩 오류 (${mode} 모드):`, error); - setFormList([]); - } finally { - setIsLoadingForms(false); - } - }; - // 핸들러들 function handleSelectContract(projId: number, cId: number) { setSelectedProjectId(projId) @@ -217,67 +118,72 @@ export function VendorDataContainer({ function handleSelectPackage(itemId: number) { setSelectedPackageId(itemId) + + // partners와 동일하게: 패키지 선택 시 해당 페이지로 이동 + if (itemId && pathname) { + // 더 안전한 URL 생성 로직 + let baseSegments: string; + const vendorDataIndex = pathname.split("/").filter(Boolean).indexOf("vendor-data"); + + if (vendorDataIndex !== -1) { + baseSegments = pathname.split("/").filter(Boolean).slice(0, vendorDataIndex + 1).join("/"); + } else { + // vendor-data가 없으면 기본 경로 사용 + baseSegments = `${currentLng}/evcp/vendor-data`; + } + + const targetUrl = `/${baseSegments}/tag/${itemId}?mode=${selectedMode}`; + router.push(targetUrl); + } } function handleSelectForm(formName: string) { - const form = formList.find((f) => f.formName === formName) - if (form) { - setSelectedFormCode(form.formCode) + // partners와 동일하게: 폼 선택 시 해당 페이지로 이동 + if (selectedPackageId && pathname) { + // 더 안전한 URL 생성 로직 + let baseSegments: string; + const vendorDataIndex = pathname.split("/").filter(Boolean).indexOf("vendor-data"); + + if (vendorDataIndex !== -1) { + baseSegments = pathname.split("/").filter(Boolean).slice(0, vendorDataIndex + 1).join("/"); + } else { + // vendor-data가 없으면 기본 경로 사용 + baseSegments = `${currentLng}/evcp/vendor-data`; + } + + const targetUrl = `/${baseSegments}/form/${selectedPackageId}/${formName}/${selectedProjectId}/${selectedContractId}?mode=${selectedMode}`; + router.push(targetUrl); } } // 모드 변경 핸들러 -// 모드 변경 핸들러 -const handleModeChange = async (mode: "IM" | "ENG") => { - // ship 프로젝트인 경우 모드 변경 금지 - if (isShipProject && mode !== "ENG") return; - - setSelectedMode(mode); - - // 모드가 변경될 때 자동 네비게이션 - if (currentContract?.packages?.length) { - const firstPackageId = currentContract.packages[0].itemId; + const handleModeChange = async (mode: "IM" | "ENG") => { + // ship 프로젝트인 경우 모드 변경 금지 + if (isShipProject && mode !== "ENG") return; - if (mode === "IM") { - // IM 모드: 첫 번째 패키지로 이동 - const baseSegments = pathname?.split("/").filter(Boolean).slice(0, pathname.split("/").filter(Boolean).indexOf("vendor-data") + 1).join("/"); - router.push(`/${currentLng}/${baseSegments}/tag/${firstPackageId}?mode=${mode}`); - } else { - // ENG 모드: 폼 목록을 먼저 로드 - setIsLoadingForms(true); - try { - const result = await getFormsByContractItemId(firstPackageId, mode); - setFormList(result.forms || []); + setSelectedMode(mode); + + // 모드가 변경될 때 자동 네비게이션 + if (currentContract?.packages?.length) { + const firstPackageId = currentContract.packages[0].itemId; + + if (pathname) { + // 더 안전한 URL 생성 로직 + let baseSegments: string; + const vendorDataIndex = pathname.split("/").filter(Boolean).indexOf("vendor-data"); - // 폼이 있으면 첫 번째 폼으로 이동 - if (result.forms && result.forms.length > 0) { - const firstForm = result.forms[0]; - setSelectedFormCode(firstForm.formCode); - - const baseSegments = pathname?.split("/").filter(Boolean).slice(0, pathname.split("/").filter(Boolean).indexOf("vendor-data") + 1).join("/"); - router.push(`/${currentLng}/${baseSegments}/form/0/${firstForm.formCode}/${selectedProjectId}/${selectedContractId}?mode=${mode}`); + if (vendorDataIndex !== -1) { + baseSegments = pathname.split("/").filter(Boolean).slice(0, vendorDataIndex + 1).join("/"); } else { - // 폼이 없으면 모드만 변경 - const baseSegments = pathname?.split("/").filter(Boolean).slice(0, pathname.split("/").filter(Boolean).indexOf("vendor-data") + 1).join("/"); - router.push(`/${currentLng}/${baseSegments}/form/0/0/${selectedProjectId}/${selectedContractId}?mode=${mode}`); + // vendor-data가 없으면 기본 경로 사용 + baseSegments = `${currentLng}/evcp/vendor-data`; } - } catch (error) { - console.error(`폼 로딩 오류 (${mode} 모드):`, error); - // 오류 발생 시 모드만 변경 - const url = new URL(window.location.href); - url.searchParams.set('mode', mode); - router.replace(url.pathname + url.search); - } finally { - setIsLoadingForms(false); + + const targetUrl = `/${baseSegments}/tag/${firstPackageId}?mode=${mode}`; + router.push(targetUrl); } } - } else { - // 패키지가 없는 경우, 모드만 변경 - const url = new URL(window.location.href); - url.searchParams.set('mode', mode); - router.replace(url.pathname + url.search); } -}; return ( @@ -318,14 +224,7 @@ const handleModeChange = async (mode: "IM" | "ENG") => { selectedProjectId={selectedProjectId} selectedContractId={selectedContractId} onSelectPackage={handleSelectPackage} - forms={formList} - selectedForm={ - selectedFormCode - ? formList.find((f) => f.formCode === selectedFormCode)?.formName || null - : null - } onSelectForm={handleSelectForm} - isLoadingForms={isLoadingForms} mode="ENG" className="hidden lg:block" /> @@ -351,14 +250,7 @@ const handleModeChange = async (mode: "IM" | "ENG") => { selectedContractId={selectedContractId} selectedProjectId={selectedProjectId} onSelectPackage={handleSelectPackage} - forms={formList} - selectedForm={ - selectedFormCode - ? formList.find((f) => f.formCode === selectedFormCode)?.formName || null - : null - } onSelectForm={handleSelectForm} - isLoadingForms={isLoadingForms} mode="IM" className="hidden lg:block" /> @@ -372,14 +264,7 @@ const handleModeChange = async (mode: "IM" | "ENG") => { selectedContractId={selectedContractId} selectedProjectId={selectedProjectId} onSelectPackage={handleSelectPackage} - forms={formList} - selectedForm={ - selectedFormCode - ? formList.find((f) => f.formCode === selectedFormCode)?.formName || null - : null - } onSelectForm={handleSelectForm} - isLoadingForms={isLoadingForms} mode="ENG" className="hidden lg:block" /> @@ -418,14 +303,7 @@ const handleModeChange = async (mode: "IM" | "ENG") => { selectedProjectId={selectedProjectId} selectedContractId={selectedContractId} onSelectPackage={handleSelectPackage} - forms={formList} - selectedForm={ - selectedFormCode - ? formList.find((f) => f.formCode === selectedFormCode)?.formName || null - : null - } onSelectForm={handleSelectForm} - isLoadingForms={isLoadingForms} mode={isShipProject ? "ENG" : selectedMode} className="hidden lg:block" /> @@ -441,7 +319,7 @@ const handleModeChange = async (mode: "IM" | "ENG") => {

{isShipProject || selectedMode === "ENG" ? "Engineering Mode" - : `Package: ${currentPackageName}`} + : `Package: ${currentContract?.packages.find((pkg) => pkg.itemId === selectedPackageId)?.itemName || "None"}`}

{children} -- cgit v1.2.3