summaryrefslogtreecommitdiff
path: root/components/vendor-data
diff options
context:
space:
mode:
Diffstat (limited to 'components/vendor-data')
-rw-r--r--components/vendor-data/sidebar.tsx15
-rw-r--r--components/vendor-data/vendor-data-container.tsx270
2 files changed, 79 insertions, 206 deletions
diff --git a/components/vendor-data/sidebar.tsx b/components/vendor-data/sidebar.tsx
index 3805d216..a6b35a9d 100644
--- a/components/vendor-data/sidebar.tsx
+++ b/components/vendor-data/sidebar.tsx
@@ -27,8 +27,7 @@ interface SidebarProps extends React.HTMLAttributes<HTMLDivElement> {
selectedProjectId: number | null
selectedContractId: number | null
onSelectPackage: (itemId: number) => void
- forms: FormInfo[]
- selectedForm: string | null
+ forms?: FormInfo[] // 선택적 속성으로 변경
onSelectForm: (formName: string) => void
isLoadingForms?: boolean
mode: "IM" | "ENG" // 새로 추가: 현재 선택된 모드
@@ -43,7 +42,7 @@ export function Sidebar({
selectedContractId,
onSelectPackage,
forms,
- selectedForm,
+ // selectedForm, // 사용되지 않음
onSelectForm,
isLoadingForms = false,
mode = "IM", // 기본값 설정
@@ -90,13 +89,9 @@ export function Sidebar({
* ---------------------------
*/
const handlePackageClick = (itemId: number) => {
- // 상위 컴포넌트 상태 업데이트
+ // 상위 컴포넌트 상태 업데이트만 수행
+ // 라우팅은 하지 않음 (프로젝트 선택 상태 유지)
onSelectPackage(itemId)
-
- // 해당 태그 페이지로 라우팅
- // 예: /vendor-data/tag/123
- const baseSegments = segments.slice(0, segments.indexOf("vendor-data") + 1).join("/")
- router.push(`/${baseSegments}/tag/${itemId}`)
}
/**
@@ -204,7 +199,7 @@ export function Sidebar({
<Skeleton className="h-8 w-full" />
</div>
))
- ) : forms.length === 0 ? (
+ ) : !forms || forms.length === 0 ? (
<p className="text-sm text-muted-foreground px-2">
(No forms loaded)
</p>
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}