"use client" import * as React from "react" import { TooltipProvider } from "@/components/ui/tooltip" 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' 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[] defaultLayout?: number[] defaultCollapsed?: boolean 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], defaultCollapsed = false, navCollapsedSize, children }: VendorDataContainerProps) { const pathname = usePathname() const router = useRouter() const searchParams = useSearchParams() 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) const [selectedContractId, setSelectedContractId] = React.useState( 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" const [selectedMode, setSelectedMode] = useAtom(selectedModeAtom) // URL에서 모드 추출 (ship 프로젝트면 무조건 ENG로, 아니면 URL 또는 기본값) const modeFromUrl = searchParams?.get('mode') const initialMode = isShipProject ? "ENG" : (modeFromUrl === "ENG" || modeFromUrl === "IM") ? modeFromUrl : "IM" // 모드 초기화 (기존의 useState 초기값 대신) 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]) const createUrlWithLng = (path: string, queryParams?: Record) => { // 기본 경로에 언어 파라미터 포함 const basePath = `/${currentLng}${path.startsWith('/') ? path : '/' + path}` if (queryParams) { const searchParams = new URLSearchParams(queryParams) return `${basePath}?${searchParams.toString()}` } return basePath } // URL에서 모드가 변경되면 상태도 업데이트 (ship 프로젝트가 아닐 때만) React.useEffect(() => { if (!isShipProject) { const modeFromUrl = searchParams?.get('mode') if (modeFromUrl === "ENG" || modeFromUrl === "IM") { setSelectedMode(modeFromUrl) } } }, [searchParams, isShipProject]) // 프로젝트 타입이 변경될 때 모드 업데이트 React.useEffect(() => { if (isShipProject) { setSelectedMode("ENG") // URL 모드 파라미터도 업데이트 const url = new URL(window.location.href); url.searchParams.set('mode', 'ENG'); router.replace(url.pathname + url.search); } }, [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) 프로젝트 변경 시 계약 초기화 React.useEffect(() => { if (currentProject?.contracts.length) { setSelectedContractId(currentProject.contracts[0].contractId) } else { setSelectedContractId(0) } }, [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) setSelectedContractId(cId) } function handleSelectPackage(itemId: number) { setSelectedPackageId(itemId) } function handleSelectForm(formName: string) { const form = formList.find((f) => f.formName === formName) if (form) { setSelectedFormCode(form.formCode) } } // 모드 변경 핸들러 // 모드 변경 핸들러 const handleModeChange = async (mode: "IM" | "ENG") => { // ship 프로젝트인 경우 모드 변경 금지 if (isShipProject && mode !== "ENG") return; setSelectedMode(mode); // 모드가 변경될 때 자동 네비게이션 if (currentContract?.packages?.length) { const firstPackageId = currentContract.packages[0].itemId; if (mode === "IM") { // IM 모드: 첫 번째 패키지로 이동 const baseSegments = pathname?.split("/").filter(Boolean).slice(0, pathname.split("/").filter(Boolean).indexOf("vendor-data") + 1).join("/"); router.push(`/${baseSegments}/tag/${firstPackageId}?mode=${mode}`); } else { // ENG 모드: 폼 목록을 먼저 로드 setIsLoadingForms(true); try { const result = await getFormsByContractItemId(firstPackageId, mode); setFormList(result.forms || []); // 폼이 있으면 첫 번째 폼으로 이동 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(`/${baseSegments}/form/0/${firstForm.formCode}/${selectedProjectId}/${selectedContractId}?mode=${mode}`); } else { // 폼이 없으면 모드만 변경 const baseSegments = pathname?.split("/").filter(Boolean).slice(0, pathname.split("/").filter(Boolean).indexOf("vendor-data") + 1).join("/"); router.push(`/${baseSegments}/form/0/0/${selectedProjectId}/${selectedContractId}?mode=${mode}`); } } 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); } } } else { // 패키지가 없는 경우, 모드만 변경 const url = new URL(window.location.href); url.searchParams.set('mode', mode); router.replace(url.pathname + url.search); } }; return ( setIsCollapsed(true)} onResize={() => setIsCollapsed(false)} className={cn(isCollapsed && "min-w-[50px] transition-all duration-300 ease-in-out")} >
{!isCollapsed ? ( isShipProject ? ( // 프로젝트 타입이 ship인 경우: 탭 없이 ENG 모드 사이드바만 바로 표시
f.formCode === selectedFormCode)?.formName || null : null } onSelectForm={handleSelectForm} isLoadingForms={isLoadingForms} mode="ENG" className="hidden lg:block" />
) : ( // 프로젝트 타입이 ship이 아닌 경우: 기존 탭 UI 표시 handleModeChange(value as "IM" | "ENG")} className="w-full" > H/O ENG f.formCode === selectedFormCode)?.formName || null : null } onSelectForm={handleSelectForm} isLoadingForms={isLoadingForms} mode="IM" className="hidden lg:block" /> f.formCode === selectedFormCode)?.formName || null : null } onSelectForm={handleSelectForm} isLoadingForms={isLoadingForms} mode="ENG" className="hidden lg:block" /> ) ) : ( // 접혀있을 때 UI <> {!isShipProject && ( // ship 프로젝트가 아닐 때만 모드 선택 버튼 표시
)} f.formCode === selectedFormCode)?.formName || null : null } onSelectForm={handleSelectForm} isLoadingForms={isLoadingForms} mode={isShipProject ? "ENG" : selectedMode} className="hidden lg:block" /> )}

{isShipProject || selectedMode === "ENG" ? "Engineering Mode" : `Package: ${currentPackageName}`}

{children}
) }