"use client" import * as React from "react" import { Button } from "@/components/ui/button" import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from "lucide-react" import { useAtom } from "jotai" import { ProjectAvlTable, ProjectAvlTableRef } from "./project-avl-table" import { StandardAvlTable, StandardAvlTableRef } from "./standard-avl-table" import { VendorPoolTable, VendorPoolTableRef } from "./vendor-pool-table" import { selectedAvlRecordAtom } from "../avl-atoms" import { copyToProjectAvl, copyToStandardAvl, copyToVendorPool, copyFromVendorPoolToProjectAvl, copyFromVendorPoolToStandardAvl, copyFromStandardAvlToVendorPool } from "../service" import { useSession } from "next-auth/react" import { toast } from "sonner" // 선택된 테이블 타입 type SelectedTable = 'project' | 'standard' | 'vendor' | null // 선택 상태 액션 타입 type SelectionAction = | { type: 'SELECT_PROJECT'; count: number } | { type: 'SELECT_STANDARD'; count: number } | { type: 'SELECT_VENDOR'; count: number } | { type: 'CLEAR_SELECTION' } // 선택 상태 interface SelectionState { selectedTable: SelectedTable selectedRowCount: number resetCounters: { project: number standard: number vendor: number } } // 선택 상태 리듀서 const selectionReducer = (state: SelectionState, action: SelectionAction): SelectionState => { switch (action.type) { case 'SELECT_PROJECT': if (action.count > 0) { return { selectedTable: 'project', selectedRowCount: action.count, resetCounters: { ...state.resetCounters, standard: state.selectedTable !== 'project' ? state.resetCounters.standard + 1 : state.resetCounters.standard, vendor: state.selectedTable !== 'project' ? state.resetCounters.vendor + 1 : state.resetCounters.vendor, } } } else if (state.selectedTable === 'project') { return { ...state, selectedTable: null, selectedRowCount: 0, } } return state case 'SELECT_STANDARD': if (action.count > 0) { return { selectedTable: 'standard', selectedRowCount: action.count, resetCounters: { ...state.resetCounters, project: state.selectedTable !== 'standard' ? state.resetCounters.project + 1 : state.resetCounters.project, vendor: state.selectedTable !== 'standard' ? state.resetCounters.vendor + 1 : state.resetCounters.vendor, } } } else if (state.selectedTable === 'standard') { return { ...state, selectedTable: null, selectedRowCount: 0, } } return state case 'SELECT_VENDOR': if (action.count > 0) { return { selectedTable: 'vendor', selectedRowCount: action.count, resetCounters: { ...state.resetCounters, project: state.selectedTable !== 'vendor' ? state.resetCounters.project + 1 : state.resetCounters.project, standard: state.selectedTable !== 'vendor' ? state.resetCounters.standard + 1 : state.resetCounters.standard, } } } else if (state.selectedTable === 'vendor') { return { ...state, selectedTable: null, selectedRowCount: 0, } } return state default: return state } } interface AvlRegistrationAreaProps { disabled?: boolean // 비활성화 상태 } export function AvlRegistrationArea({ disabled = false }: AvlRegistrationAreaProps) { // 선택된 AVL 레코드 구독 const [selectedAvlRecord] = useAtom(selectedAvlRecordAtom) // 세션 정보 const { data: session } = useSession() // 단일 선택 상태 관리 (useReducer 사용) const [selectionState, dispatch] = React.useReducer(selectionReducer, { selectedTable: null, selectedRowCount: 0, resetCounters: { project: 0, standard: 0, vendor: 0, }, }) // 선택 핸들러들 const handleProjectSelection = React.useCallback((count: number) => { console.log('handleProjectSelection called with count:', count) dispatch({ type: 'SELECT_PROJECT', count }) }, []) const handleStandardSelection = React.useCallback((count: number) => { console.log('handleStandardSelection called with count:', count) dispatch({ type: 'SELECT_STANDARD', count }) }, []) const handleVendorSelection = React.useCallback((count: number) => { dispatch({ type: 'SELECT_VENDOR', count }) }, []) const { selectedTable, selectedRowCount, resetCounters } = selectionState console.log('selectedTable', selectedTable); // 선택된 AVL에 따른 필터 값들 const [currentProjectCode, setCurrentProjectCode] = React.useState("") const constructionSector = selectedAvlRecord?.constructionSector || "" const shipType = selectedAvlRecord?.shipType || "" const avlKind = selectedAvlRecord?.avlKind || "" const htDivision = selectedAvlRecord?.htDivision || "" const avlListId = selectedAvlRecord?.id ? String(selectedAvlRecord.id) : "" // 선종별 표준 AVL 검색 조건 상태 (복사 버튼 활성화용) const [standardSearchConditions, setStandardSearchConditions] = React.useState({ constructionSector: "", shipType: "", avlKind: "", htDivision: "" }) // 검색 조건이 모두 입력되었는지 확인 const isStandardSearchConditionsComplete = React.useMemo(() => { return ( standardSearchConditions.constructionSector.trim() !== "" && standardSearchConditions.shipType.trim() !== "" && standardSearchConditions.avlKind.trim() !== "" && standardSearchConditions.htDivision.trim() !== "" ) }, [standardSearchConditions]) // 벤더 풀 리로드 트리거 const [vendorPoolReloadTrigger, setVendorPoolReloadTrigger] = React.useState(0) // 선종별 표준 AVL 리로드 트리거 const [standardAvlReloadTrigger, setStandardAvlReloadTrigger] = React.useState(0) // 프로젝트 AVL 리로드 트리거 const [projectAvlReloadTrigger, setProjectAvlReloadTrigger] = React.useState(0) // 테이블 ref들 (선택된 행 정보 가져오기용) const projectTableRef = React.useRef(null) const standardTableRef = React.useRef(null) const vendorTableRef = React.useRef(null) // 선택된 AVL 레코드가 변경될 때 프로젝트 코드 초기화 React.useEffect(() => { setCurrentProjectCode(selectedAvlRecord?.projectCode || "") }, [selectedAvlRecord?.projectCode]) // 프로젝트 코드 변경 핸들러 const handleProjectCodeChange = React.useCallback((projectCode: string) => { setCurrentProjectCode(projectCode) }, []) // 선택된 ID들을 가져오는 헬퍼 함수들 const getSelectedIds = React.useCallback((tableType: 'project' | 'standard' | 'vendor') => { // 각 테이블 컴포넌트에서 선택된 행들의 ID를 가져오는 로직 switch (tableType) { case 'project': return projectTableRef.current?.getSelectedIds?.() || [] case 'standard': return standardTableRef.current?.getSelectedIds?.() || [] case 'vendor': return vendorTableRef.current?.getSelectedIds?.() || [] default: return [] } }, []) // 복사 버튼 핸들러들 const handleCopyToProject = React.useCallback(async () => { if (selectedTable !== 'standard' || selectedRowCount === 0) return const selectedIds = getSelectedIds('standard') if (!selectedIds.length) { toast.error("복사할 항목을 선택해주세요.") return } if (!currentProjectCode) { toast.error("프로젝트 코드가 설정되지 않았습니다.") return } try { const result = await copyToProjectAvl( selectedIds, currentProjectCode, parseInt(avlListId) || 1, session?.user?.name || "unknown" ) if (result.success) { toast.success(result.message) // 선택 해제 dispatch({ type: 'CLEAR_SELECTION' }) } else { toast.error(result.message) } } catch (error) { console.error('프로젝트AVL로 복사 실패:', error) toast.error("복사 중 오류가 발생했습니다.") } }, [selectedTable, selectedRowCount, getSelectedIds, currentProjectCode, avlListId, session]) const handleCopyToStandard = React.useCallback(async () => { if (selectedTable !== 'project' || selectedRowCount === 0) return const selectedIds = getSelectedIds('project') if (!selectedIds.length) { toast.error("복사할 항목을 선택해주세요.") return } const targetStandardInfo = { constructionSector: standardSearchConditions.constructionSector || "조선", shipType: standardSearchConditions.shipType || "", avlKind: standardSearchConditions.avlKind || "", htDivision: standardSearchConditions.htDivision || "H" } try { const result = await copyToStandardAvl( selectedIds, targetStandardInfo, session?.user?.name || "unknown" ) if (result.success) { toast.success(result.message) // 선종별 표준 AVL 데이터 리로드 setStandardAvlReloadTrigger(prev => prev + 1) // 선택 해제 dispatch({ type: 'CLEAR_SELECTION' }) } else { toast.error(result.message) } } catch (error) { console.error('선종별표준AVL로 복사 실패:', error) toast.error("복사 중 오류가 발생했습니다.") } }, [selectedTable, selectedRowCount, getSelectedIds, standardSearchConditions, session]) const handleCopyToVendorPool = React.useCallback(async () => { if (selectedTable !== 'project' || selectedRowCount === 0) return const selectedIds = getSelectedIds('project') if (!selectedIds.length) { toast.error("복사할 항목을 선택해주세요.") return } try { const result = await copyToVendorPool( selectedIds, session?.user?.name || "unknown" ) if (result.success) { toast.success(result.message) // 벤더 풀 데이터 리로드 setVendorPoolReloadTrigger(prev => prev + 1) // 선택 해제 dispatch({ type: 'CLEAR_SELECTION' }) } else { toast.error(result.message) } } catch (error) { console.error('벤더풀로 복사 실패:', error) toast.error("복사 중 오류가 발생했습니다.") } }, [selectedTable, selectedRowCount, getSelectedIds, session]) // 추가 복사 버튼 핸들러들 const handleCopyFromVendorToProject = React.useCallback(async () => { if (selectedTable !== 'vendor' || selectedRowCount === 0) return const selectedIds = getSelectedIds('vendor') if (!selectedIds.length) { toast.error("복사할 항목을 선택해주세요.") return } if (!currentProjectCode) { toast.error("프로젝트 코드가 설정되지 않았습니다.") return } try { const result = await copyFromVendorPoolToProjectAvl( selectedIds, currentProjectCode, parseInt(avlListId) || 1, session?.user?.name || "unknown" ) if (result.success) { toast.success(result.message) // 프로젝트 AVL 리로드 setProjectAvlReloadTrigger(prev => prev + 1) // 선택 해제 dispatch({ type: 'CLEAR_SELECTION' }) } else { toast.error(result.message) } } catch (error) { console.error('벤더풀 → 프로젝트AVL 복사 실패:', error) toast.error("복사 중 오류가 발생했습니다.") } }, [selectedTable, selectedRowCount, getSelectedIds, currentProjectCode, avlListId, session]) const handleCopyFromVendorToStandard = React.useCallback(async () => { if (selectedTable !== 'vendor' || selectedRowCount === 0) return const selectedIds = getSelectedIds('vendor') if (!selectedIds.length) { toast.error("복사할 항목을 선택해주세요.") return } const targetStandardInfo = { constructionSector: standardSearchConditions.constructionSector || "조선", shipType: standardSearchConditions.shipType || "", avlKind: standardSearchConditions.avlKind || "", htDivision: standardSearchConditions.htDivision || "H" } try { const result = await copyFromVendorPoolToStandardAvl( selectedIds, targetStandardInfo, session?.user?.name || "unknown" ) if (result.success) { toast.success(result.message) // 선종별 표준 AVL 리로드 setStandardAvlReloadTrigger(prev => prev + 1) // 선택 해제 dispatch({ type: 'CLEAR_SELECTION' }) } else { toast.error(result.message) } } catch (error) { console.error('벤더풀 → 선종별표준AVL 복사 실패:', error) toast.error("복사 중 오류가 발생했습니다.") } }, [selectedTable, selectedRowCount, getSelectedIds, standardSearchConditions, session]) const handleCopyFromStandardToVendor = React.useCallback(async () => { if (selectedTable !== 'standard' || selectedRowCount === 0) return const selectedIds = getSelectedIds('standard') if (!selectedIds.length) { toast.error("복사할 항목을 선택해주세요.") return } try { const result = await copyFromStandardAvlToVendorPool( selectedIds, session?.user?.name || "unknown" ) if (result.success) { toast.success(result.message) // 벤더 풀 리로드 setVendorPoolReloadTrigger(prev => prev + 1) // 선택 해제 dispatch({ type: 'CLEAR_SELECTION' }) } else { toast.error(result.message) } } catch (error) { console.error('선종별표준AVL → 벤더풀 복사 실패:', error) toast.error("복사 중 오류가 발생했습니다.") } }, [selectedTable, selectedRowCount, getSelectedIds, session]) return (
{/* 고정 헤더 영역 */}

AVL 등록 {disabled ? "(비활성화)" : ""}

{/* */}
{/* 스크롤되는 콘텐츠 영역 */}
{/* 프로젝트 AVL 테이블 - 9개 컬럼 */}
{/* 이동 버튼들 - 첫 번째 border 위에 오버레이 */}
{/* 선종별 표준 AVL 테이블 - 8개 컬럼 */}
{/* 이동 버튼들 - 두 번째 border 위에 오버레이 */}
{/* Vendor Pool 테이블 - 10개 컬럼 */}
) }