summaryrefslogtreecommitdiff
path: root/components/vendor-data/vendor-data-container.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'components/vendor-data/vendor-data-container.tsx')
-rw-r--r--components/vendor-data/vendor-data-container.tsx333
1 files changed, 252 insertions, 81 deletions
diff --git a/components/vendor-data/vendor-data-container.tsx b/components/vendor-data/vendor-data-container.tsx
index 3974b791..207abcf1 100644
--- a/components/vendor-data/vendor-data-container.tsx
+++ b/components/vendor-data/vendor-data-container.tsx
@@ -1,42 +1,63 @@
"use client"
import * as React from "react"
-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 { 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 { 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 { TooltipProvider } from "@/components/ui/tooltip"
+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: {
- projectId: number
- projectCode: string
- projectName: string
- projectType: string
- contracts: {
- contractId: number
- contractNo: string
- contractName: string
- packages: PackageData[]
- }[]
- }[]
+ projects: ProjectData[]
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],
@@ -47,8 +68,8 @@ export function VendorDataContainer({
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)
@@ -57,12 +78,15 @@ export function VendorDataContainer({
projects[0]?.contracts[0]?.contractId || 0
)
const [selectedPackageId, setSelectedPackageId] = React.useState<number | null>(null)
+ const [formList, setFormList] = React.useState<FormInfo[]>([])
+ const [selectedFormCode, setSelectedFormCode] = React.useState<string | null>(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"
@@ -78,6 +102,30 @@ 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(() => {
@@ -101,89 +149,184 @@ export function VendorDataContainer({
}
}, [isShipProject, router])
- // (1) 프로젝트 변경 시 계약 초기화
+ // (1) 새로고침 시 URL 파라미터(tagIdNumber) → selectedPackageId 세팅
React.useEffect(() => {
- if (currentProject?.contracts.length) {
- setSelectedContractId(currentProject.contracts[0].contractId)
+ if (!currentContract) return
+
+ if (tagIdNumber) {
+ setSelectedPackageId(tagIdNumber)
} else {
- setSelectedContractId(0)
+ // tagIdNumber가 없으면, 현재 계약의 첫 번째 패키지로
+ if (currentContract.packages?.length) {
+ setSelectedPackageId(currentContract.packages[0].itemId)
+ } else {
+ setSelectedPackageId(null)
+ }
}
- }, [currentProject])
+ }, [tagIdNumber, currentContract])
- // 핸들러들
- function handleSelectContract(projId: number, cId: number) {
- setSelectedProjectId(projId)
- setSelectedContractId(cId)
- }
+ // (2) 프로젝트 변경 시 계약 초기화
+ // React.useEffect(() => {
+ // if (currentProject?.contracts.length) {
+ // setSelectedContractId(currentProject.contracts[0].contractId)
+ // } else {
+ // setSelectedContractId(0)
+ // }
+ // }, [currentProject])
- function handleSelectPackage(itemId: number) {
- setSelectedPackageId(itemId)
+ // (3) 패키지 ID와 모드가 변경될 때마다 폼 로딩
+ React.useEffect(() => {
+ const packageId = getTagIdFromPathname(pathname)
- // partners와 동일하게: 패키지 선택 시 해당 페이지로 이동
- if (itemId && pathname) {
- // 더 안전한 URL 생성 로직
- let baseSegments: string;
- const vendorDataIndex = pathname.split("/").filter(Boolean).indexOf("vendor-data");
+ if (packageId) {
+ setSelectedPackageId(packageId)
- if (vendorDataIndex !== -1) {
- baseSegments = pathname.split("/").filter(Boolean).slice(0, vendorDataIndex + 1).join("/");
+ // 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);
+ }
+ };
+
+ // 핸들러들
+// 수정된 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)
+
+ if (selectedContract?.packages?.length) {
+ const firstPackageId = selectedContract.packages[0].itemId
+ setSelectedPackageId(firstPackageId)
+
+ // 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") + 1).join("/")
+ router.push(`/${baseSegments}/form/0/${firstForm.formCode}/${projId}/${cId}?mode=ENG`)
} else {
- // vendor-data가 없으면 기본 경로 사용
- baseSegments = `${currentLng}/evcp/vendor-data`;
+ // 폼이 없는 경우에도 ENG 모드로 설정
+ setSelectedMode("ENG")
+ setSelectedFormCode(null)
+
+ const baseSegments = pathname?.split("/").filter(Boolean).slice(0, pathname.split("/").filter(Boolean).indexOf("vendor-data") + 1).join("/")
+ router.push(`/${baseSegments}/form/0/0/${projId}/${cId}?mode=ENG`)
}
+ } catch (error) {
+ console.error("폼 로딩 오류:", error)
+ setFormList([])
+ setSelectedFormCode(null)
- const targetUrl = `/${baseSegments}/tag/${itemId}?mode=${selectedMode}`;
- router.push(targetUrl);
+ // 오류 발생 시에도 ENG 모드로 설정
+ setSelectedMode("ENG")
+ } finally {
+ setIsLoadingForms(false)
}
+ } else {
+ // 패키지가 없는 경우
+ setSelectedPackageId(null)
+ setFormList([])
+ setSelectedFormCode(null)
+ setSelectedMode("ENG")
+ }
+}
+
+ function handleSelectPackage(itemId: number) {
+ setSelectedPackageId(itemId)
}
function handleSelectForm(formName: string) {
- // 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 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);
+// 모드 변경 핸들러
+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 (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 (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 (vendorDataIndex !== -1) {
- baseSegments = pathname.split("/").filter(Boolean).slice(0, vendorDataIndex + 1).join("/");
+ // 폼이 있으면 첫 번째 폼으로 이동
+ 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 {
- // vendor-data가 없으면 기본 경로 사용
- baseSegments = `${currentLng}/evcp/vendor-data`;
+ // 폼이 없으면 모드만 변경
+ 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}`);
}
-
- const targetUrl = `/${baseSegments}/tag/${firstPackageId}?mode=${mode}`;
- router.push(targetUrl);
+ } 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 (
<TooltipProvider delayDuration={0}>
@@ -224,7 +367,14 @@ export function VendorDataContainer({
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"
/>
@@ -250,7 +400,14 @@ export function VendorDataContainer({
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"
/>
@@ -264,7 +421,14 @@ export function VendorDataContainer({
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"
/>
@@ -303,7 +467,14 @@ export function VendorDataContainer({
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"
/>
@@ -319,7 +490,7 @@ export function VendorDataContainer({
<h2 className="text-lg font-bold">
{isShipProject || selectedMode === "ENG"
? "Engineering Mode"
- : `Package: ${currentContract?.packages.find((pkg) => pkg.itemId === selectedPackageId)?.itemName || "None"}`}
+ : `Package: ${currentPackageName}`}
</h2>
</div>
{children}