summaryrefslogtreecommitdiff
path: root/components/vendor-data-plant/vendor-data-container.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'components/vendor-data-plant/vendor-data-container.tsx')
-rw-r--r--components/vendor-data-plant/vendor-data-container.tsx523
1 files changed, 123 insertions, 400 deletions
diff --git a/components/vendor-data-plant/vendor-data-container.tsx b/components/vendor-data-plant/vendor-data-container.tsx
index 60ec2c94..7ce831df 100644
--- a/components/vendor-data-plant/vendor-data-container.tsx
+++ b/components/vendor-data-plant/vendor-data-container.tsx
@@ -4,28 +4,14 @@ 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 } from "next/navigation"
-import { getFormsByContractItemId, type FormInfo } from "@/lib/forms/services"
+import { usePathname, useRouter } from "next/navigation"
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 { ProjectSwitcher } from "./project-swicher"
interface PackageData {
- itemId: number
- itemName: string
-}
-
-interface ContractData {
- contractId: number
- contractName: string
- packages: PackageData[]
+ packageCode: string
+ packageName: string | null
}
interface ProjectData {
@@ -33,7 +19,7 @@ interface ProjectData {
projectCode: string
projectName: string
projectType: string
- contracts: ContractData[]
+ packages: PackageData[]
}
interface VendorDataContainerProps {
@@ -44,18 +30,39 @@ interface VendorDataContainerProps {
children: React.ReactNode
}
-function getTagIdFromPathname(path: string | null): number | null {
- if (!path) return null;
+function getInfoFromPathname(path: string | null): {
+ projectCode: string | null
+ packageCode: string | null
+ formCode: string | null
+ mode: "master" | "engineering" | "im" | null
+} {
+ if (!path) return { projectCode: null, packageCode: null, formCode: null, mode: null }
+
+ const segments = path.split("/").filter(Boolean)
+ const vendorDataIndex = segments.indexOf("vendor-data-plant")
+
+ if (vendorDataIndex === -1) {
+ return { projectCode: null, packageCode: null, formCode: null, mode: null }
+ }
- // 태그 패턴 검사 (/tag/123)
- const tagMatch = path.match(/\/tag\/(\d+)/)
- if (tagMatch) return parseInt(tagMatch[1], 10)
+ const projectCode = segments[vendorDataIndex + 1] || null
+ const packageCode = segments[vendorDataIndex + 2] || null
- // 폼 패턴 검사 (/form/123/...)
- const formMatch = path.match(/\/form\/(\d+)/)
- if (formMatch) return parseInt(formMatch[1], 10)
+ // /eng/{formCode} 또는 /im/{formCode} 패턴 체크
+ const modeSegment = segments[vendorDataIndex + 3]
+ const formCode = segments[vendorDataIndex + 4] || null
- return null
+ let mode: "master" | "engineering" | "im" | null = null
+
+ if (modeSegment === "eng") {
+ mode = "engineering"
+ } else if (modeSegment === "im") {
+ mode = "im"
+ } else if (projectCode && packageCode && !modeSegment) {
+ mode = "master"
+ }
+
+ return { projectCode, packageCode, formCode, mode }
}
export function VendorDataContainer({
@@ -67,267 +74,106 @@ export function VendorDataContainer({
}: VendorDataContainerProps) {
const pathname = usePathname()
const router = useRouter()
- const searchParams = useSearchParams()
- 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<number | null>(null)
- const [formList, setFormList] = React.useState<FormInfo[]>([])
+ const [selectedPackageCode, setSelectedPackageCode] = React.useState<string | null>(null)
const [selectedFormCode, setSelectedFormCode] = React.useState<string | null>(null)
- const [isLoadingForms, setIsLoadingForms] = React.useState(false)
+ const [currentMode, setCurrentMode] = React.useState<"master" | "engineering" | "im" | null>(null)
- console.log(selectedPackageId,"selectedPackageId")
-
-
- // 현재 선택된 프로젝트/계약/패키지
+ // 현재 선택된 프로젝트
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 ="ENG"
-
- // 모드 초기화 (기존의 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])
- // URL에서 모드가 변경되면 상태도 업데이트 (ship 프로젝트가 아닐 때만)
+ // URL 변경 시 상태 동기화
React.useEffect(() => {
- if (!isShipProject) {
- const modeFromUrl = searchParams?.get('mode')
- if (modeFromUrl === "ENG" || modeFromUrl === "IM") {
- setSelectedMode(modeFromUrl)
+ const { projectCode, packageCode, formCode, mode } = getInfoFromPathname(pathname)
+
+ if (projectCode && packageCode) {
+ // 프로젝트 찾기
+ const project = projects.find(p => p.projectCode === projectCode)
+ if (project) {
+ setSelectedProjectId(project.projectId)
+ setSelectedPackageCode(packageCode)
}
}
- }, [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);
+
+ if (formCode) {
+ setSelectedFormCode(formCode)
+ } else {
+ setSelectedFormCode(null)
}
- }, [isShipProject, router])
-
- // (1) 새로고침 시 URL 파라미터(tagIdNumber) → selectedPackageId 세팅
- React.useEffect(() => {
- if (!currentContract) return
-
- if (tagIdNumber) {
- setSelectedPackageId(tagIdNumber)
+
+ if (mode) {
+ setCurrentMode(mode)
} else {
- // tagIdNumber가 없으면, 현재 계약의 첫 번째 패키지로
- if (currentContract.packages?.length) {
- setSelectedPackageId(currentContract.packages[0].itemId)
- } else {
- setSelectedPackageId(null)
- }
+ setCurrentMode(null)
}
- }, [tagIdNumber, currentContract])
-
- // (2) 프로젝트 변경 시 계약 초기화
- // React.useEffect(() => {
- // if (currentProject?.contracts.length) {
- // setSelectedContractId(currentProject.contracts[0].contractId)
- // } else {
- // setSelectedContractId(0)
- // }
- // }, [currentProject])
+ }, [pathname, projects])
+
+ // 베이스 URL 생성 헬퍼
+ const getBaseUrl = () => {
+ const segments = pathname?.split("/").filter(Boolean) || []
+ const vendorDataIndex = segments.indexOf("vendor-data-plant")
+ if (vendorDataIndex === -1) return ""
+ return "/" + segments.slice(0, vendorDataIndex + 1).join("/")
+ }
- // (3) 패키지 ID와 모드가 변경될 때마다 폼 로딩
- React.useEffect(() => {
- const packageId = getTagIdFromPathname(pathname)
+ // 프로젝트 및 패키지 선택 핸들러
+ const handleSelectPackage = (projectId: number, packageCode: string) => {
+ const project = projects.find(p => p.projectId === projectId)
+ if (!project) return
- 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;
+ setSelectedProjectId(projectId)
+ setSelectedPackageCode(packageCode)
+ setSelectedFormCode(null)
+ setCurrentMode("master")
- setIsLoadingForms(true);
- try {
- const result = await getFormsByContractItemId(packageId, mode);
- setFormList(result.forms || []);
- } catch (error) {
- console.error(`폼 로딩 오류 (${mode} 모드):`, error);
- setFormList([]);
- } finally {
- setIsLoadingForms(false);
- }
- };
-
- // 핸들러들
-// 수정된 handleSelectContract 함수
-async function handleSelectContract(projId: number, cId: number) {
- setSelectedProjectId(projId)
- setSelectedContractId(cId)
-
- // 선택된 계약의 첫 번째 패키지 찾기
- const selectedProject = projects.find(p => p.projectId === projId)
- const selectedContract = selectedProject?.contracts.find(c => c.contractId === cId)
+ const baseUrl = getBaseUrl()
+ router.push(`${baseUrl}/${project.projectCode}/${packageCode}`)
+ }
- if (selectedContract?.packages?.length) {
- const firstPackageId = selectedContract.packages[0].itemId
- setSelectedPackageId(firstPackageId)
+ // Master Tag List 클릭 핸들러
+ const handleMasterTagListClick = () => {
+ if (!selectedPackageCode) return
- // ENG 모드로 폼 목록 로드
- setIsLoadingForms(true)
- try {
- const result = await getFormsByContractItemId(firstPackageId, "ENG")
- setFormList(result.forms || [])
-
- // 첫 번째 폼이 있으면 자동 선택 및 네비게이션
- if (result.forms && result.forms.length > 0) {
- const firstForm = result.forms[0]
- setSelectedFormCode(firstForm.formCode)
-
- // ENG 모드로 설정
- setSelectedMode("ENG")
-
- // 첫 번째 폼으로 네비게이션
- const baseSegments = pathname?.split("/").filter(Boolean).slice(0, pathname.split("/").filter(Boolean).indexOf("vendor-data-plant") + 1).join("/")
- router.push(`/${baseSegments}/form/0/${firstForm.formCode}/${projId}/${cId}?mode=ENG`)
- } else {
- // 폼이 없는 경우에도 ENG 모드로 설정
- setSelectedMode("ENG")
- setSelectedFormCode(null)
-
- const baseSegments = pathname?.split("/").filter(Boolean).slice(0, pathname.split("/").filter(Boolean).indexOf("vendor-data-plant") + 1).join("/")
- router.push(`/${baseSegments}/form/0/0/${projId}/${cId}?mode=ENG`)
- }
- } catch (error) {
- console.error("폼 로딩 오류:", error)
- setFormList([])
- setSelectedFormCode(null)
-
- // 오류 발생 시에도 ENG 모드로 설정
- setSelectedMode("ENG")
- } finally {
- setIsLoadingForms(false)
- }
- } else {
- // 패키지가 없는 경우
- setSelectedPackageId(null)
- setFormList([])
+ const project = projects.find(p => p.projectId === selectedProjectId)
+ if (!project) return
+
+ setCurrentMode("master")
setSelectedFormCode(null)
- setSelectedMode("ENG")
- }
-}
-
- function handleSelectPackage(itemId: number) {
- setSelectedPackageId(itemId)
- }
-
- function handleSelectForm(formName: string) {
- const form = formList.find((f) => f.formName === formName)
- if (form) {
- setSelectedFormCode(form.formCode)
- }
+
+ const baseUrl = getBaseUrl()
+ router.push(`${baseUrl}/${project.projectCode}/${selectedPackageCode}`)
}
-
- // 모드 변경 핸들러
-// 모드 변경 핸들러
-const handleModeChange = async (mode: "IM" | "ENG") => {
- // ship 프로젝트인 경우 모드 변경 금지
- if (isShipProject && mode !== "ENG") return;
- setSelectedMode(mode);
+ // Engineering 폼 클릭 핸들러
+ const handleEngineeringFormClick = (formCode: string) => {
+ if (!selectedPackageCode) return
+
+ const project = projects.find(p => p.projectId === selectedProjectId)
+ if (!project) return
+
+ setCurrentMode("engineering")
+ setSelectedFormCode(formCode)
+
+ const baseUrl = getBaseUrl()
+ router.push(`${baseUrl}/${project.projectCode}/${selectedPackageCode}/eng/${formCode}`)
+ }
- // 모드가 변경될 때 자동 네비게이션
- if (currentContract?.packages?.length) {
- const firstPackageId = currentContract.packages[0].itemId;
+ // IM 폼 클릭 핸들러
+ const handleIMFormClick = (formCode: string) => {
+ if (!selectedPackageCode) return
- if (mode === "IM") {
- // IM 모드: 첫 번째 패키지로 이동
- const baseSegments = pathname?.split("/").filter(Boolean).slice(0, pathname.split("/").filter(Boolean).indexOf("vendor-data-plant") + 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-plant") + 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-plant") + 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);
+ const project = projects.find(p => p.projectId === selectedProjectId)
+ if (!project) return
+
+ setCurrentMode("im")
+ setSelectedFormCode(formCode)
+
+ const baseUrl = getBaseUrl()
+ router.push(`${baseUrl}/${project.projectCode}/${selectedPackageCode}/im/${formCode}`)
}
-};
return (
<TooltipProvider delayDuration={0}>
@@ -351,151 +197,28 @@ const handleModeChange = async (mode: "IM" | "ENG") => {
<ProjectSwitcher
isCollapsed={isCollapsed}
projects={projects}
- selectedContractId={selectedContractId}
- onSelectContract={handleSelectContract}
+ selectedProjectId={selectedProjectId}
+ selectedPackageCode={selectedPackageCode}
+ onSelectPackage={handleSelectPackage}
/>
</div>
<Separator />
- {!isCollapsed ? (
- isShipProject ? (
- // 프로젝트 타입이 ship인 경우: 탭 없이 ENG 모드 사이드바만 바로 표시
- <div className="mt-0">
- <Sidebar
- isCollapsed={isCollapsed}
- packages={currentContract?.packages || []}
- selectedPackageId={selectedPackageId}
- 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"
- />
- </div>
- ) : (
- // 프로젝트 타입이 ship이 아닌 경우: 기존 탭 UI 표시
- <Tabs
- defaultValue={initialMode}
- value={selectedMode}
- onValueChange={(value) => handleModeChange(value as "IM" | "ENG")}
- className="w-full"
- >
- <TabsList className="w-full">
- <TabsTrigger value="ENG" className="flex-1">Engineering</TabsTrigger>
- <TabsTrigger value="IM" className="flex-1">Handover</TabsTrigger>
-
- </TabsList>
-
- <TabsContent value="IM" className="mt-0">
- <Sidebar
- isCollapsed={isCollapsed}
- packages={currentContract?.packages || []}
- selectedPackageId={selectedPackageId}
- 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"
- />
- </TabsContent>
-
- <TabsContent value="ENG" className="mt-0">
- <Sidebar
- isCollapsed={isCollapsed}
- packages={currentContract?.packages || []}
- selectedPackageId={selectedPackageId}
- 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"
- />
- </TabsContent>
- </Tabs>
- )
- ) : (
- // 접혀있을 때 UI
- <>
- {!isShipProject && (
- // ship 프로젝트가 아닐 때만 모드 선택 버튼 표시
- <div className="flex justify-center space-x-1 my-2">
-
- <Button
- variant={selectedMode === "ENG" ? "default" : "ghost"}
- size="sm"
- className="h-8 px-2"
- onClick={() => handleModeChange("ENG")}
- >
- Engineering
- </Button>
- <Button
- variant={selectedMode === "IM" ? "default" : "ghost"}
- size="sm"
- className="h-8 px-2"
- onClick={() => handleModeChange("IM")}
- >
- Handover
- </Button>
- </div>
- )}
-
- <Sidebar
- isCollapsed={isCollapsed}
- packages={currentContract?.packages || []}
- selectedPackageId={selectedPackageId}
- 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"
- />
- </>
- )}
+ <Sidebar
+ isCollapsed={isCollapsed}
+ selectedPackageCode={selectedPackageCode}
+ selectedFormCode={selectedFormCode}
+ currentMode={currentMode}
+ onMasterTagListClick={handleMasterTagListClick}
+ onEngineeringFormClick={handleEngineeringFormClick}
+ onIMFormClick={handleIMFormClick}
+ />
</ResizablePanel>
<ResizableHandle withHandle />
<ResizablePanel defaultSize={defaultLayout[1]} minSize={40}>
<div className="p-4 h-full overflow-auto flex flex-col">
- <div className="flex items-center justify-between mb-4">
- <h2 className="text-lg font-bold">
- {isShipProject || selectedMode === "ENG"
- ? "Engineering Mode"
- : `Package: ${currentPackageName}`}
- </h2>
- </div>
{children}
</div>
</ResizablePanel>