summaryrefslogtreecommitdiff
path: root/components/vendor-data/vendor-data-container.tsx
diff options
context:
space:
mode:
author0-Zz-ang <s1998319@gmail.com>2025-08-17 23:05:19 +0900
committer0-Zz-ang <s1998319@gmail.com>2025-08-17 23:05:19 +0900
commit5adc1df95f80fbec7a0b5bbee15448b10d5aec3a (patch)
treec748910aacb05f13e335f9afa39eb9d763f88d7c /components/vendor-data/vendor-data-container.tsx
parent6013fe51293ea067400e6b3b26691705608eba22 (diff)
(박서영)evcp/document-list-only, evcp/vendor-data 생성
Diffstat (limited to 'components/vendor-data/vendor-data-container.tsx')
-rw-r--r--components/vendor-data/vendor-data-container.tsx270
1 files changed, 74 insertions, 196 deletions
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<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"
@@ -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 (
<TooltipProvider delayDuration={0}>
@@ -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") => {
<h2 className="text-lg font-bold">
{isShipProject || selectedMode === "ENG"
? "Engineering Mode"
- : `Package: ${currentPackageName}`}
+ : `Package: ${currentContract?.packages.find((pkg) => pkg.itemId === selectedPackageId)?.itemName || "None"}`}
</h2>
</div>
{children}