"use client" import * as React from "react" import { useRouter, useSearchParams } from "next/navigation" import { Button } from "@/components/ui/button" import { PanelLeftClose, PanelLeftOpen } from "lucide-react" import type { DataTableAdvancedFilterField, DataTableFilterField, DataTableRowAction, } from "@/types/table" import { useDataTable } from "@/hooks/use-data-table" import { DataTable } from "@/components/data-table/data-table" import { DataTableAdvancedToolbar } from "@/components/data-table/data-table-advanced-toolbar" import { getPQSubmissions } from "../service" import { getColumns, PQSubmission } from "./vendors-table-columns" import { VendorsTableToolbarActions } from "./vendors-table-toolbar-actions" import { PQFilterSheet } from "./pq-filter-sheet" import { cn } from "@/lib/utils" // TablePresetManager 관련 import 추가 import { useTablePresets } from "@/components/data-table/use-table-presets" import { TablePresetManager } from "@/components/data-table/data-table-preset" import { useMemo } from "react" interface PQSubmissionsTableProps { promises: Promise<[Awaited>]> className?: string } export function PQSubmissionsTable({ promises, className }: PQSubmissionsTableProps) { const [rowAction, setRowAction] = React.useState | null>(null) const [isFilterPanelOpen, setIsFilterPanelOpen] = React.useState(false) const router = useRouter() const searchParams = useSearchParams() // Container wrapper의 위치를 측정하기 위한 ref const containerRef = React.useRef(null) const [containerTop, setContainerTop] = React.useState(0) // Container 위치 측정 함수 - top만 측정 const updateContainerBounds = React.useCallback(() => { if (containerRef.current) { const rect = containerRef.current.getBoundingClientRect() setContainerTop(rect.top) } }, []) // 컴포넌트 마운트 시와 윈도우 리사이즈 시 위치 업데이트 React.useEffect(() => { updateContainerBounds() const handleResize = () => { updateContainerBounds() } window.addEventListener('resize', handleResize) window.addEventListener('scroll', updateContainerBounds) return () => { window.removeEventListener('resize', handleResize) window.removeEventListener('scroll', updateContainerBounds) } }, [updateContainerBounds]) // Suspense 방식으로 데이터 처리 const [promiseData] = React.use(promises) const tableData = promiseData // 디버깅용 로그 console.log("PQ Table Data:", { dataLength: tableData.data?.length, pageCount: tableData.pageCount, sampleData: tableData.data?.[0] }) // 초기 설정 정의 (RFQ와 동일한 패턴) 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: "updatedAt", desc: true }], filters: searchParams.get('filters') ? JSON.parse(searchParams.get('filters')!) : [], joinOperator: (searchParams.get('joinOperator') as "and" | "or") || "and", basicFilters: searchParams.get('basicFilters') || searchParams.get('pqBasicFilters') ? JSON.parse(searchParams.get('basicFilters') || searchParams.get('pqBasicFilters')!) : [], basicJoinOperator: (searchParams.get('basicJoinOperator') as "and" | "or") || "and", search: searchParams.get('search') || '', from: searchParams.get('from') || undefined, to: searchParams.get('to') || undefined, columnVisibility: {}, columnOrder: [], pinnedColumns: { left: [], right: ["actions"] }, // PQ는 actions를 오른쪽에 고정 groupBy: [], expandedRows: [] }), [searchParams]) // DB 기반 프리셋 훅 사용 const { presets, activePresetId, hasUnsavedChanges, isLoading: presetsLoading, createPreset, applyPreset, updatePreset, deletePreset, setDefaultPreset, renamePreset, updateClientState, getCurrentSettings, } = useTablePresets('pq-submissions-table', initialSettings) const columns = React.useMemo( () => getColumns({ setRowAction, router }), [setRowAction, router] ) // PQ 제출 필터링을 위한 필드 정의 const filterFields: DataTableFilterField[] = [ { id: "vendorName", label: "협력업체" }, { id: "projectName", label: "프로젝트" }, { id: "status", label: "상태" }, ] // 고급 필터 필드 정의 const advancedFilterFields: DataTableAdvancedFilterField[] = [ { id: "requesterName", label: "요청자명", type: "text" }, { id: "pqNumber", label: "PQ 번호", type: "text" }, { id: "vendorName", label: "협력업체명", type: "text" }, { id: "vendorCode", label: "협력업체 코드", type: "text" }, { id: "type", label: "PQ 유형", type: "select", options: [ { label: "일반 PQ", value: "GENERAL" }, { label: "프로젝트 PQ", value: "PROJECT" }, ]}, { id: "projectName", label: "프로젝트명", type: "text" }, { id: "status", label: "PQ 상태", type: "select", options: [ { label: "요청됨", value: "REQUESTED" }, { label: "진행 중", value: "IN_PROGRESS" }, { label: "제출됨", value: "SUBMITTED" }, { label: "승인됨", value: "APPROVED" }, { label: "거부됨", value: "REJECTED" }, ]}, { id: "evaluationResult", label: "평가 결과", type: "select", options: [ { label: "승인", value: "APPROVED" }, { label: "보완", value: "SUPPLEMENT" }, { label: "불가", value: "REJECTED" }, ]}, { id: "createdAt", label: "생성일", type: "date" }, { id: "submittedAt", label: "제출일", type: "date" }, { id: "approvedAt", label: "승인일", type: "date" }, { id: "rejectedAt", label: "거부일", type: "date" }, ] // 현재 설정 가져오기 const currentSettings = useMemo(() => { return getCurrentSettings() }, [getCurrentSettings]) // useDataTable 초기 상태 설정 (RFQ와 동일한 패턴) const initialState = useMemo(() => { return { sorting: initialSettings.sort.filter(sortItem => { const columnExists = columns.some(col => col.accessorKey === sortItem.id) return columnExists }) as any, columnVisibility: currentSettings.columnVisibility, columnPinning: currentSettings.pinnedColumns, } }, [currentSettings, initialSettings.sort, columns]) const { table } = useDataTable({ data: tableData.data, columns, pageCount: tableData.pageCount, rowCount: tableData.total || tableData.data.length, // total 추가 filterFields, // RFQ와 달리 빈 배열이 아닌 실제 필터 필드 사용 enablePinning: true, enableAdvancedFilter: true, initialState, getRowId: (originalRow) => String(originalRow.id), shallow: false, clearOnDefault: true, }) // 조회 버튼 클릭 핸들러 - PQFilterSheet에 전달 const handleSearch = () => { // Close the panel after search setIsFilterPanelOpen(false) } // Get active basic filter count const getActiveBasicFilterCount = () => { try { const basicFilters = searchParams.get('basicFilters') || searchParams.get('pqBasicFilters') return basicFilters ? JSON.parse(basicFilters).length : 0 } catch (e) { return 0 } } // Filter panel width const FILTER_PANEL_WIDTH = 400; return ( <> {/* Filter Panel - fixed positioning으로 화면 최대 좌측에서 시작 */}
{/* Filter Content */}
setIsFilterPanelOpen(false)} onSearch={handleSearch} isLoading={false} />
{/* Main Content Container */}
{/* Main Content - 너비 조정으로 필터 패널 공간 확보 */}
{/* Header Bar */}
{/* Right side info */}
{tableData && ( 총 {tableData.total || tableData.data.length}건 )}
{/* Table Content Area */}
{/* DB 기반 테이블 프리셋 매니저 추가 */} presets={presets} activePresetId={activePresetId} currentSettings={currentSettings} hasUnsavedChanges={hasUnsavedChanges} isLoading={presetsLoading} onCreatePreset={createPreset} onUpdatePreset={updatePreset} onDeletePreset={deletePreset} onApplyPreset={applyPreset} onSetDefaultPreset={setDefaultPreset} onRenamePreset={renamePreset} /> {/* 기존 툴바 액션들 */}
) }