From 40250c61031263606dd073ce7056a3e8e27f18d0 Mon Sep 17 00:00:00 2001 From: joonhoekim <26rote@gmail.com> Date: Tue, 14 Oct 2025 14:25:28 +0900 Subject: (김준회) AVL 구매요구사항 수정 - AVL 상세 엑셀 익스포트 추가 - 레코드 이동 멀티선택 추가 - 최종확정처리 오류 수정 - 프로젝트 AVL에 H/T 구분 추가 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/avl/table/project-avl-table.tsx | 173 +++++++++++++++++++++--------------- 1 file changed, 100 insertions(+), 73 deletions(-) (limited to 'lib/avl/table/project-avl-table.tsx') diff --git a/lib/avl/table/project-avl-table.tsx b/lib/avl/table/project-avl-table.tsx index ad72b221..d15dbb06 100644 --- a/lib/avl/table/project-avl-table.tsx +++ b/lib/avl/table/project-avl-table.tsx @@ -12,16 +12,22 @@ import { DialogHeader, DialogTitle, } from "@/components/ui/dialog" +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select" import { AvlVendorAddAndModifyDialog } from "./avl-vendor-add-and-modify-dialog" -import { getProjectAvlVendorInfo, createAvlVendorInfo, updateAvlVendorInfo, deleteAvlVendorInfo, finalizeProjectAvl } from "../service" +import { getProjectAvlVendorInfo, createAvlVendorInfo, updateAvlVendorInfo, deleteAvlVendorInfo, finalizeProjectAvl, getProjectAvlVendorInfoCount } from "../service" import { useReactTable, getCoreRowModel, getPaginationRowModel, getSortedRowModel, getFilteredRowModel } from "@tanstack/react-table" import { GetProjectAvlSchema } from "../validations" import { AvlDetailItem, AvlVendorInfoInput } from "../types" import { toast } from "sonner" import { getProjectAvlColumns } from "./project-avl-table-columns" import { - ProjectDisplayField, - ProjectFileField + ProjectDisplayField } from "../components/project-field-components" import { ProjectSearchStatus } from "../components/project-field-utils" import { useSession } from "next-auth/react" @@ -31,6 +37,12 @@ import { UnifiedProjectSelector, UnifiedProject, getProjectInfoByCode } from "@/ // 프로젝트 AVL 테이블에서는 AvlDetailItem을 사용 export type ProjectAvlItem = AvlDetailItem +// H/T 구분 옵션 (공통 없음) +const htDivisionOptions = [ + { value: "H", label: "Hull (H)" }, + { value: "T", label: "Top (T)" }, +] + // ref를 통해 외부에서 접근할 수 있는 메소드들 export interface ProjectAvlTableRef { getSelectedIds: () => number[] @@ -42,6 +54,7 @@ interface ProjectAvlTableProps { projectCode?: string // 프로젝트 코드 필터 avlListId?: number // AVL 리스트 ID (관리 영역 표시용) onProjectCodeChange?: (projectCode: string) => void // 프로젝트 코드 변경 콜백 + onHtDivisionChange?: (htDivision: string) => void // H/T 구분 변경 콜백 reloadTrigger?: number } @@ -52,6 +65,7 @@ export const ProjectAvlTable = forwardRef { @@ -59,7 +73,6 @@ export const ProjectAvlTable = forwardRef([]) const [pageCount, setPageCount] = React.useState(0) - const [originalFile, setOriginalFile] = React.useState("") const [localProjectCode, setLocalProjectCode] = React.useState(projectCode || "") // 프로젝트 선택 상태 @@ -74,9 +87,11 @@ export const ProjectAvlTable = forwardRef(null) + // H/T 구분 상태 (사용자가 직접 선택) + const [searchHtDivision, setSearchHtDivision] = React.useState("") + // 프로젝트 검색 상태 const [projectSearchStatus, setProjectSearchStatus] = React.useState('idle') @@ -100,7 +115,8 @@ export const ProjectAvlTable = forwardRef { + return ( + localProjectCode.trim() !== "" && + searchHtDivision.trim() !== "" && + isSearchClicked + ) + }, [localProjectCode, searchHtDivision, isSearchClicked]) + + // 초기 데이터 로드 (모든 조건이 충족되었을 때만) React.useEffect(() => { - if (localProjectCode && isSearchClicked) { + if (isAllConditionsSelected) { loadData({}) + } else { + // 조건이 충족되지 않으면 빈 데이터로 설정 + setData([]) + setPageCount(0) } - }, [loadData, localProjectCode, isSearchClicked]) - - // 파일 업로드 핸들러 - const handleFileUpload = React.useCallback((event: React.ChangeEvent) => { - const file = event.target.files?.[0] - if (file) { - setOriginalFile(file.name) - // TODO: 실제 파일 업로드 로직 구현 - console.log("파일 업로드:", file.name) - } - }, []) + }, [loadData, isAllConditionsSelected]) // 프로젝트 검색 함수 (공통 로직) const searchProject = React.useCallback(async (projectCode: string) => { @@ -187,30 +206,11 @@ export const ProjectAvlTable = forwardRef) => { @@ -353,7 +358,7 @@ export const ProjectAvlTable = forwardRef(0) // 최종 확정 핸들러 const handleFinalizeAvl = React.useCallback(async () => { @@ -437,36 +443,45 @@ export const ProjectAvlTable = forwardRef { try { - // 3. 현재 데이터의 모든 ID 수집 (전체 레코드 기준) - const avlVendorInfoIds = data.map(item => item.id) - - // 4. 최종 확정 실행 + // 최종 확정 실행 (서버에서 DB의 모든 레코드를 조회하여 확정) const result = await finalizeProjectAvl( localProjectCode, - projectInfo!, - avlVendorInfoIds, + { + ...projectInfo!, + htDivision: searchHtDivision // 사용자가 선택한 H/T 구분 사용 + }, sessionData?.user?.name || "" ) if (result.success) { toast.success(result.message) - // 5. 데이터 새로고침 + // 데이터 새로고침 loadData({}) - // 6. 선택 해제 + // 선택 해제 table.toggleAllPageRowsSelected(false) } else { toast.error(result.message) @@ -477,7 +492,7 @@ export const ProjectAvlTable = forwardRef { + onHtDivisionChange?.(searchHtDivision) + }, [searchHtDivision, onHtDivisionChange]) + return (
@@ -536,7 +556,7 @@ export const ProjectAvlTable = forwardRef 최종 확정 @@ -568,11 +588,11 @@ export const ProjectAvlTable = forwardRef {/* 원본파일 */} - + /> */} {/* 공사부문 */} {/* H/T 구분 */} - - value === 'H' ? 'Hull (H)' : - value === 'T' ? 'Topside (T)' : '-' - } - /> +
+ + +
@@ -636,8 +661,10 @@ export const ProjectAvlTable = forwardRef• 프로젝트명: {projectInfo?.projectName || ""}
• 공사부문: {projectInfo?.constructionSector || ""}
• 선종: {projectInfo?.shipType || ""}
-
• H/T 구분: {projectInfo?.htDivision || ""}
-
• 벤더 정보: {data.length}개 (전체 레코드)
+
• H/T 구분: {searchHtDivision === 'H' ? 'Hull (H)' : searchHtDivision === 'T' ? 'Top (T)' : searchHtDivision}
+
+ • 확정될 벤더 정보: {totalVendorInfoCount}개 +
{/*
⚠️ 확정 후 내용 수정을 필요로 하는 경우 동일 건을 다시 최종확정해 revision 처리로 수정해야 합니다.
*/} -- cgit v1.2.3