"use client" import * as React from "react" import { useSearchParams } from "next/navigation" import type { DataTableRowAction, } from "@/types/table" import { ResizablePanelGroup, ResizablePanel, ResizableHandle, } from "@/components/ui/resizable" import { useDataTable } from "@/hooks/use-data-table" import { DataTable } from "@/components/data-table/data-table" import { getColumns } from "./pcr-table-column" import { useEffect, useMemo } from "react" import { DataTableAdvancedToolbar } from "@/components/data-table/data-table-advanced-toolbar" import { PcrTableToolbarActions } from "./pcr-table-toolbar-actions" import { getPcrPoList } from "@/lib/pcr/service" import { useTablePresets } from "@/components/data-table/use-table-presets" import { PcrDetailTables } from "./detail-table/pcr-detail-table" import { EditPcrSheet } from "./edit-pcr-sheet" import { cn } from "@/lib/utils" import { PcrPoData } from "@/lib/pcr/types" import type { DataTableAdvancedFilterField, DataTableFilterField, } from "@/types/table" interface PcrTableProps { tableData: Awaited> className?: string; calculatedHeight?: string; isEvcpPage?: boolean; // EvcP 페이지인지 여부 isPartnersPage?: boolean; // Partners 페이지인지 여부 currentVendorId?: number; // Partners 페이지에서 현재 사용자의 vendorId } export function PcrTable({ tableData, className, calculatedHeight, isEvcpPage = false, isPartnersPage = false, currentVendorId, }: PcrTableProps) { const searchParams = useSearchParams() // 선택된 PCR_PO 상태 const [selectedPcrPo, setSelectedPcrPo] = React.useState(null) // Edit sheet 상태 const [editSheetOpen, setEditSheetOpen] = React.useState(false) const [editingPcr, setEditingPcr] = React.useState(null) // 패널 collapse 상태 const [panelHeight, setPanelHeight] = React.useState(55) // RFQListTable 컴포넌트 내부의 rowAction 처리 부분 수정 const [rowAction, setRowAction] = React.useState | null>(null) // 고정 높이 설정을 위한 상수 (실제 측정값으로 조정 필요) const LAYOUT_HEADER_HEIGHT = 64 // Layout Header 높이 const LAYOUT_FOOTER_HEIGHT = 60 // Layout Footer 높이 (있다면 실제 값) const LOCAL_HEADER_HEIGHT = 72 // 로컬 헤더 바 높이 (p-4 + border) console.log(calculatedHeight) // 테이블 컨텐츠 높이 - 전달받은 높이에서 로컬 헤더 제외 const FIXED_TABLE_HEIGHT = calculatedHeight ? `calc(${calculatedHeight} - ${LOCAL_HEADER_HEIGHT}px)` : `calc(100vh - ${LAYOUT_HEADER_HEIGHT + LAYOUT_FOOTER_HEIGHT + LOCAL_HEADER_HEIGHT+76}px)` // fallback // 데이터는 props로 직접 전달받음 // 초기 설정 정의 const initialSettings = React.useMemo(() => ({ page: parseInt(searchParams?.get('page') || '1'), perPage: parseInt(searchParams?.get('perPage') || '10'), sort: searchParams?.get('sort') ? JSON.parse(searchParams.get('sort')!) : [{ id: "createdAt", desc: true }], columnVisibility: {}, columnOrder: [], pinnedColumns: { left: [], right: [] }, filters: [], joinOperator: "and" as const, basicFilters: [], basicJoinOperator: "and" as const, search: "", }), [searchParams]) // DB 기반 프리셋 훅 사용 const { getCurrentSettings, } = useTablePresets('pcr-po-table', initialSettings) // 행 액션 처리 useEffect(() => { if (rowAction) { switch (rowAction.type) { case "select": // 객체 참조 안정화를 위해 필요한 필드만 추출 const pcrPoData = rowAction.row.original; console.log("Row action select - PCR_PO 데이터:", pcrPoData) setSelectedPcrPo({ id: pcrPoData.id, no: pcrPoData.no, pcrApprovalStatus: pcrPoData.pcrApprovalStatus, changeType: pcrPoData.changeType, details: pcrPoData.details || undefined, project: pcrPoData.project || undefined, pcrRequestDate: pcrPoData.pcrRequestDate, poContractNumber: pcrPoData.poContractNumber, revItemNumber: pcrPoData.revItemNumber || undefined, purchaseContractManager: pcrPoData.purchaseContractManager || undefined, pcrCreator: pcrPoData.pcrCreator || undefined, poContractAmountBefore: pcrPoData.poContractAmountBefore ? Number(pcrPoData.poContractAmountBefore) : undefined as number | undefined, poContractAmountAfter: pcrPoData.poContractAmountAfter ? Number(pcrPoData.poContractAmountAfter) : undefined as number | undefined, contractCurrency: pcrPoData.contractCurrency || "KRW", pcrReason: pcrPoData.pcrReason || undefined, detailsReason: pcrPoData.detailsReason || undefined, rejectionReason: pcrPoData.rejectionReason || undefined, pcrResponseDate: pcrPoData.pcrResponseDate || undefined, vendorId: pcrPoData.vendorId || undefined, vendorName: pcrPoData.vendorName || undefined, createdBy: pcrPoData.createdBy, updatedBy: pcrPoData.updatedBy, createdAt: pcrPoData.createdAt, updatedAt: pcrPoData.updatedAt, }); break; case "update": // PCR_PO 수정 시트 열기 setEditingPcr(rowAction.row.original) setEditSheetOpen(true) break; case "delete": console.log("Delete PCR_PO:", rowAction.row.original) break; } setRowAction(null) } }, [rowAction]) const columns = React.useMemo( () => getColumns({ setRowAction, isEvcpPage, }), [setRowAction, isEvcpPage] ) // 필터 필드 정의 const filterFields: DataTableFilterField[] = [] const advancedFilterFields: DataTableAdvancedFilterField[] = [ { id: "pcrApprovalStatus", label: "PCR 승인상태", type: "multi-select", options: [ { label: "승인대기", value: "승인대기" }, { label: "승인완료", value: "승인완료" }, { label: "거절", value: "거절" }, { label: "취소", value: "취소" }, ], }, { id: "changeType", label: "변경구분", type: "multi-select", options: [ { label: "수량변경", value: "QUANTITY" }, { label: "금액변경", value: "AMOUNT" }, { label: "기간변경", value: "PERIOD" }, { label: "품목변경", value: "ITEM" }, { label: "기타", value: "OTHER" }, ], }, { id: "poContractNumber", label: "PO/계약번호", type: "text", }, { id: "project", label: "프로젝트", type: "text", }, ...(isEvcpPage ? [{ id: "vendorName" as const, label: "협력업체", type: "text" as const, }] : []), { id: "pcrRequestDate", label: "PCR 요청일자", type: "date", }, { id: "createdAt", label: "생성일", type: "date", }, ] // 현재 설정 가져오기 const currentSettings = useMemo(() => { return getCurrentSettings() }, [getCurrentSettings]) // useDataTable 초기 상태 설정 const initialState = useMemo(() => { return { sorting: initialSettings.sort.filter((sortItem: any) => { const columnExists = columns.some((col: any) => col.accessorKey === sortItem.id) return columnExists }) as any, columnVisibility: currentSettings.columnVisibility, columnPinning: currentSettings.pinnedColumns, } }, [currentSettings, initialSettings.sort, columns]) // useDataTable 훅 설정 const { table } = useDataTable({ data: tableData?.data || [], columns: columns as any, pageCount: tableData?.pageCount || 0, filterFields, enablePinning: true, enableAdvancedFilter: true, initialState, getRowId: (originalRow) => String(originalRow.id), shallow: false, clearOnDefault: true, columnResizeMode: "onEnd", }) // 선택된 행들 감시하여 selectedPcrPo 설정 (checkbox selection) React.useEffect(() => { if (table) { const selectedRows = table.getSelectedRowModel().rows if (selectedRows.length === 1) { const pcrPoData = selectedRows[0].original const selectedData = { id: pcrPoData.id, no: (pcrPoData as any).no, pcrApprovalStatus: pcrPoData.pcrApprovalStatus || "", changeType: pcrPoData.changeType || "", details: pcrPoData.details || undefined, project: pcrPoData.project || undefined, pcrRequestDate: pcrPoData.pcrRequestDate, poContractNumber: pcrPoData.poContractNumber, revItemNumber: pcrPoData.revItemNumber || undefined, purchaseContractManager: pcrPoData.purchaseContractManager || undefined, pcrCreator: pcrPoData.pcrCreator || undefined, poContractAmountBefore: pcrPoData.poContractAmountBefore ? Number(pcrPoData.poContractAmountBefore) : undefined as number | undefined, poContractAmountAfter: pcrPoData.poContractAmountAfter ? Number(pcrPoData.poContractAmountAfter) : undefined as number | undefined, contractCurrency: pcrPoData.contractCurrency || "KRW", pcrReason: pcrPoData.pcrReason || undefined, detailsReason: pcrPoData.detailsReason || undefined, rejectionReason: pcrPoData.rejectionReason || undefined, pcrResponseDate: pcrPoData.pcrResponseDate || undefined, vendorId: pcrPoData.vendorId || undefined, vendorName: pcrPoData.vendorName || undefined, createdBy: pcrPoData.createdBy, updatedBy: pcrPoData.updatedBy, createdAt: pcrPoData.createdAt, updatedAt: pcrPoData.updatedAt, } setSelectedPcrPo(selectedData) } else if (selectedRows.length === 0) { // 선택이 해제되었을 때는 selectedPcrPo를 null로 설정하지 않음 // row action select가 우선권을 가짐 } } }, [table?.getSelectedRowModel().rows]) return (
{/* Main Content */}
{/* Header Bar - 고정 높이 */}
{/* Right side info */}
{tableData && ( 총 {tableData.totalCount || 0}건 )}
{/* Table Content Area - 계산된 높이 사용 */}
{ setPanelHeight(size) }} className="flex flex-col overflow-hidden" > {/* 상단 테이블 영역 */}
{}} isEvcpPage={isEvcpPage} isPartnersPage={isPartnersPage} currentVendorId={currentVendorId} />
{/* 하단 상세 테이블 영역 */}
{/* PCR 수정 시트 */} { // 데이터 새로고침 window.location.reload() }} />
) }