diff options
| author | joonhoekim <26rote@gmail.com> | 2025-09-22 12:17:48 +0900 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-09-22 12:17:48 +0900 |
| commit | bd3df05b4bdc07cef1bd79cf23c08a757e9ee6eb (patch) | |
| tree | aa726fc9dce49e3d346f0fdde282b6726ad1d815 /lib/avl | |
| parent | 087fc383a662d45a69b5971a6ad821209bcbaf5b (diff) | |
(김준회) AVL 수정요구 처리
- 제목추가
- 프로젝트선택기
Diffstat (limited to 'lib/avl')
| -rw-r--r-- | lib/avl/table/project-avl-table.tsx | 154 |
1 files changed, 53 insertions, 101 deletions
diff --git a/lib/avl/table/project-avl-table.tsx b/lib/avl/table/project-avl-table.tsx index 8664e32b..fc8f0f5e 100644 --- a/lib/avl/table/project-avl-table.tsx +++ b/lib/avl/table/project-avl-table.tsx @@ -1,14 +1,12 @@ "use client" import * as React from "react" -import { useReactTable, getCoreRowModel, getPaginationRowModel, getSortedRowModel, getFilteredRowModel } from "@tanstack/react-table" import { forwardRef, useImperativeHandle, useLayoutEffect, useMemo } from "react" import { DataTable } from "@/components/data-table/data-table" import { Button } from "@/components/ui/button" import { AvlVendorAddAndModifyDialog } from "./avl-vendor-add-and-modify-dialog" import { getProjectAvlVendorInfo, createAvlVendorInfo, updateAvlVendorInfo, deleteAvlVendorInfo, finalizeProjectAvl } from "../service" -import { getProjectInfoByProjectCode as getProjectInfoFromProjects } from "../../projects/service" -import { getProjectInfoByProjectCode as getProjectInfoFromBiddingProjects } from "../../bidding-projects/service" +import { useReactTable, getCoreRowModel, getPaginationRowModel, getSortedRowModel, getFilteredRowModel } from "@tanstack/react-table" import { GetProjectAvlSchema } from "../validations" import { AvlDetailItem, AvlVendorInfoInput } from "../types" import { toast } from "sonner" @@ -19,6 +17,7 @@ import { } from "../components/project-field-components" import { ProjectSearchStatus } from "../components/project-field-utils" import { useSession } from "next-auth/react" +import { UnifiedProjectSelector, UnifiedProject, getProjectInfoByCode } from "@/components/common/project" // 프로젝트 AVL 테이블에서는 AvlDetailItem을 사용 @@ -54,6 +53,9 @@ export const ProjectAvlTable = forwardRef<ProjectAvlTableRef, ProjectAvlTablePro const [pageCount, setPageCount] = React.useState(0) const [originalFile, setOriginalFile] = React.useState<string>("") const [localProjectCode, setLocalProjectCode] = React.useState<string>(projectCode || "") + + // 프로젝트 선택 상태 + const [selectedProject, setSelectedProject] = React.useState<UnifiedProject | undefined>(undefined) // 행 추가/수정 다이얼로그 상태 const [isAddDialogOpen, setIsAddDialogOpen] = React.useState(false) @@ -80,6 +82,7 @@ export const ProjectAvlTable = forwardRef<ProjectAvlTableRef, ProjectAvlTablePro }) + // 데이터 로드 함수 const loadData = React.useCallback(async (searchParams: Partial<GetProjectAvlSchema> = {}) => { try { @@ -163,47 +166,10 @@ export const ProjectAvlTable = forwardRef<ProjectAvlTableRef, ProjectAvlTablePro setProjectSearchStatus('searching') // 검색 시작 상태로 변경 try { - // 1. projects 테이블에서 먼저 검색 - let projectData: { - projectName?: string | null; - shipType?: string; - projectMsrm?: string | null; - projectHtDivision?: string | null; - } | null = null - let searchSource = 'projects' - - try { - projectData = await getProjectInfoFromProjects(projectCode.trim()) - // projects에서 찾았을 때만 즉시 성공 상태로 변경 - setProjectSearchStatus('success-projects') - } catch { - // projects 테이블에 없는 경우 biddingProjects 테이블에서 검색 - try { - projectData = await getProjectInfoFromBiddingProjects(projectCode.trim()) - if (projectData) { - searchSource = 'bidding-projects' - setProjectSearchStatus('success-bidding') // bidding에서 찾았을 때 성공 상태로 변경 - } else { - // 둘 다 실패한 경우에만 에러 상태로 변경 - setProjectInfo(null) - setProjectSearchStatus('error') - setData([]) - setPageCount(0) - toast.error("입력하신 프로젝트 코드를 찾을 수 없습니다.") - return - } - } catch { - // biddingProjects에서도 에러가 발생한 경우 - setProjectInfo(null) - setProjectSearchStatus('error') - setData([]) - setPageCount(0) - toast.error("입력하신 프로젝트 코드를 찾을 수 없습니다.") - return - } - } + const projectData = await getProjectInfoByCode(projectCode.trim(), 'both') if (projectData) { + // 프로젝트 정보 설정 setProjectInfo({ projectName: projectData.projectName || "", constructionSector: "조선", // 기본값으로 조선 설정 (필요시 로직 변경) @@ -211,11 +177,25 @@ export const ProjectAvlTable = forwardRef<ProjectAvlTableRef, ProjectAvlTablePro htDivision: projectData.projectHtDivision || "" }) - const sourceMessage = searchSource === 'projects' ? '프로젝트' : '견적프로젝트' + // 검색 상태 설정 + if (projectData.source === 'projects') { + setProjectSearchStatus('success-projects') + } else { + setProjectSearchStatus('success-bidding') + } + + const sourceMessage = projectData.source === 'projects' ? '프로젝트' : '견적프로젝트' toast.success(`${sourceMessage}에서 프로젝트 정보를 성공적으로 불러왔습니다.`) // 검색 성공 시 AVL 데이터 로드 트리거 setIsSearchClicked(true) + } else { + // 프로젝트를 찾을 수 없는 경우 + setProjectInfo(null) + setProjectSearchStatus('error') + setData([]) + setPageCount(0) + toast.error("입력하신 프로젝트 코드를 찾을 수 없습니다.") } } catch (error) { console.error("프로젝트 정보 조회 실패:", error) @@ -227,31 +207,20 @@ export const ProjectAvlTable = forwardRef<ProjectAvlTableRef, ProjectAvlTablePro } }, [setIsSearchClicked]) - // 프로젝트 코드 변경 핸들러 (입력만 처리) - const handleProjectCodeChange = React.useCallback((value: string) => { - setLocalProjectCode(value) - onProjectCodeChange?.(value) - // 입력이 변경되면 검색 상태를 idle로 초기화하고 검색 클릭 상태를 리셋 - if (!value.trim()) { - setProjectInfo(null) - setProjectSearchStatus('idle') - setIsSearchClicked(false) - setData([]) - setPageCount(0) - } else { - // 새로운 프로젝트 코드가 입력되면 검색 클릭 상태를 리셋 (다시 검색 버튼을 눌러야 함) - setIsSearchClicked(false) - } - }, [onProjectCodeChange]) - - // 프로젝트 검색 버튼 핸들러 - const handleProjectSearch = React.useCallback(async () => { + // 프로젝트 선택 핸들러 + const handleProjectSelect = React.useCallback(async (project: UnifiedProject) => { + setSelectedProject(project) + setLocalProjectCode(project.code) + onProjectCodeChange?.(project.code) + // 검색 시 페이지를 1페이지로 리셋 setPagination(prev => ({ ...prev, pageIndex: 0 })) - // 프로젝트 정보 검색 (성공 시 내부에서 AVL 데이터 로드 트리거) - await searchProject(localProjectCode) - }, [localProjectCode, searchProject]) + + // 선택된 프로젝트로 자동 검색 + await searchProject(project.code) + }, [onProjectCodeChange, searchProject]) + // 행 추가 핸들러 const handleAddRow = React.useCallback(() => { @@ -496,6 +465,7 @@ export const ProjectAvlTable = forwardRef<ProjectAvlTableRef, ProjectAvlTablePro } }, [resetCounter, table]) + return ( <div className="h-full flex flex-col"> <div className="mb-2"> @@ -542,43 +512,25 @@ export const ProjectAvlTable = forwardRef<ProjectAvlTableRef, ProjectAvlTablePro {/* 조회대상 관리영역 */} <div className="mb-4 p-4 border rounded-lg bg-muted/50"> <div className="flex gap-4 overflow-x-auto pb-2"> - {/* 프로젝트 코드 */} - <div className="flex flex-col gap-1 min-w-[200px]"> - <label className="text-sm font-medium">프로젝트 코드</label> - <div className="flex gap-2"> - <div className="flex-1"> - <input - type="text" - value={localProjectCode} - onChange={(e) => handleProjectCodeChange(e.target.value)} - placeholder="프로젝트 코드를 입력하세요" - className={`flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 ${ - projectSearchStatus === 'error' ? 'border-red-500' : - projectSearchStatus === 'success-projects' || projectSearchStatus === 'success-bidding' ? 'border-green-500' : - projectSearchStatus === 'searching' ? 'border-blue-500' : '' - }`} - disabled={projectSearchStatus === 'searching'} - /> - {projectSearchStatus !== 'idle' && ( - <div className="text-xs mt-1 text-muted-foreground"> - {projectSearchStatus === 'success-projects' ? '(프로젝트)' : - projectSearchStatus === 'success-bidding' ? '(견적프로젝트)' : - projectSearchStatus === 'searching' ? '(검색 중...)' : - projectSearchStatus === 'error' ? '(찾을 수 없음)' : - undefined} - </div> - )} + {/* 프로젝트 선택 */} + <div className="flex flex-col gap-1 min-w-[350px]"> + <label className="text-sm font-medium">프로젝트</label> + <UnifiedProjectSelector + selectedProject={selectedProject} + onProjectSelect={handleProjectSelect} + searchOptions={{ searchFrom: 'both' }} + placeholder="프로젝트를 선택하세요" + className="h-9" + /> + {projectSearchStatus !== 'idle' && ( + <div className="text-xs mt-1 text-muted-foreground"> + {projectSearchStatus === 'success-projects' ? '(프로젝트)' : + projectSearchStatus === 'success-bidding' ? '(견적프로젝트)' : + projectSearchStatus === 'searching' ? '(검색 중...)' : + projectSearchStatus === 'error' ? '(찾을 수 없음)' : + undefined} </div> - <Button - variant="outline" - size="sm" - onClick={handleProjectSearch} - disabled={!localProjectCode.trim() || projectSearchStatus === 'searching'} - className="px-3 h-9" - > - {projectSearchStatus === 'searching' ? '검색 중...' : '검색'} - </Button> - </div> + )} </div> {/* 프로젝트명 */} |
