diff options
Diffstat (limited to 'lib/avl/table/vendor-pool-table.tsx')
| -rw-r--r-- | lib/avl/table/vendor-pool-table.tsx | 241 |
1 files changed, 126 insertions, 115 deletions
diff --git a/lib/avl/table/vendor-pool-table.tsx b/lib/avl/table/vendor-pool-table.tsx index 1a0a5fca..7ad9eb56 100644 --- a/lib/avl/table/vendor-pool-table.tsx +++ b/lib/avl/table/vendor-pool-table.tsx @@ -1,7 +1,8 @@ "use client" import * as React from "react" -import { useReactTable, getCoreRowModel, getPaginationRowModel, getSortedRowModel, getFilteredRowModel, type ColumnDef } from "@tanstack/react-table" +import { useReactTable, getCoreRowModel, getPaginationRowModel, getSortedRowModel, getFilteredRowModel } from "@tanstack/react-table" +import { forwardRef, useImperativeHandle } from "react" import { DataTable } from "@/components/data-table/data-table" import { Button } from "@/components/ui/button" import { Checkbox } from "@/components/ui/checkbox" @@ -10,114 +11,29 @@ import { Search } from "lucide-react" import { getVendorPools } from "../../vendor-pool/service" import { GetVendorPoolSchema } from "../../vendor-pool/validations" import { VendorPool } from "../../vendor-pool/types" +import { vendorPoolColumns } from "./vendor-pool-table-columns" // Vendor Pool 데이터 타입 (실제 VendorPool 타입 사용) export type VendorPoolItem = VendorPool +// ref를 통해 외부에서 접근할 수 있는 메소드들 +export interface VendorPoolTableRef { + getSelectedIds: () => number[] +} + interface VendorPoolTableProps { onSelectionChange?: (count: number) => void resetCounter?: number + reloadTrigger?: number } -// Vendor Pool 테이블 컬럼 -const vendorPoolColumns: ColumnDef<VendorPoolItem>[] = [ - { - id: "select", - header: ({ table }) => ( - <Checkbox - checked={ - table.getIsAllPageRowsSelected() || - (table.getIsSomePageRowsSelected() && "indeterminate") - } - onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)} - aria-label="Select all" - /> - ), - cell: ({ row, table }) => { - // Vendor Pool 테이블의 단일 선택 핸들러 - const handleRowSelection = (checked: boolean) => { - if (checked) { - // 다른 모든 행의 선택 해제 - table.getRowModel().rows.forEach(r => { - if (r !== row && r.getIsSelected()) { - r.toggleSelected(false) - } - }) - } - // 현재 행 선택/해제 - row.toggleSelected(checked) - } - - return ( - <Checkbox - checked={row.getIsSelected()} - onCheckedChange={handleRowSelection} - aria-label="Select row" - /> - ) - }, - enableSorting: false, - enableHiding: false, - size: 50, - }, - { - accessorKey: "no", - header: "No.", - size: 60, - }, - { - accessorKey: "designCategory", - header: "설계공종", - size: 120, - }, - { - accessorKey: "avlVendorName", - header: "AVL 등재업체명", - size: 140, - }, - { - accessorKey: "materialGroupCode", - header: "자재그룹코드", - size: 130, - }, - { - accessorKey: "materialGroupName", - header: "자재그룹명", - size: 130, - }, - { - accessorKey: "vendorName", - header: "협력업체 정보", - size: 130, - }, - { - accessorKey: "tier", - header: "업체분류", - size: 100, - }, - { - accessorKey: "faStatus", - header: "FA현황", - size: 100, - }, - { - accessorKey: "recentQuoteNumber", - header: "최근견적번호", - size: 130, - }, - { - accessorKey: "recentOrderNumber", - header: "최근발주번호", - size: 130, - }, -] - // 실제 데이터는 API에서 가져옴 -export function VendorPoolTable({ +export const VendorPoolTable = forwardRef<VendorPoolTableRef, VendorPoolTableProps>(({ onSelectionChange, - resetCounter -}: VendorPoolTableProps) { + resetCounter, + reloadTrigger +}, ref) => { const [data, setData] = React.useState<VendorPoolItem[]>([]) const [loading, setLoading] = React.useState(false) const [pageCount, setPageCount] = React.useState(0) @@ -126,18 +42,78 @@ export function VendorPoolTable({ const [searchText, setSearchText] = React.useState("") const [showAll, setShowAll] = React.useState(false) + // 페이지네이션 상태 + const [pagination, setPagination] = React.useState({ + pageIndex: 0, + pageSize: 10, + }) + // 데이터 로드 함수 - const loadData = React.useCallback(async (searchParams: Partial<GetVendorPoolSchema>) => { + const loadData = React.useCallback(async (searchParams: Partial<GetVendorPoolSchema> = {}) => { try { setLoading(true) - const params: GetVendorPoolSchema = { + + const params = { page: searchParams.page ?? 1, perPage: searchParams.perPage ?? 10, sort: searchParams.sort ?? [{ id: "registrationDate", desc: true }], + flags: [], search: searchText || "", + constructionSector: undefined, + shipType: undefined, + htDivision: undefined, + designCategoryCode: undefined, + designCategory: undefined, + equipBulkDivision: undefined, + packageCode: undefined, + packageName: undefined, + materialGroupCode: undefined, + materialGroupName: undefined, + vendorCode: undefined, + vendorName: undefined, + faTarget: undefined, + faStatus: undefined, + tier: undefined, + isAgent: undefined, + isBlacklist: undefined, + isBcc: undefined, + purchaseOpinion: undefined, + shipTypeCommon: undefined, + shipTypeAmax: undefined, + shipTypeSmax: undefined, + shipTypeVlcc: undefined, + shipTypeLngc: undefined, + shipTypeCont: undefined, + offshoreTypeCommon: undefined, + offshoreTypeFpso: undefined, + offshoreTypeFlng: undefined, + offshoreTypeFpu: undefined, + offshoreTypePlatform: undefined, + offshoreTypeWtiv: undefined, + offshoreTypeGom: undefined, + picName: undefined, + picEmail: undefined, + picPhone: undefined, + agentName: undefined, + agentEmail: undefined, + agentPhone: undefined, + recentQuoteDate: undefined, + recentQuoteNumber: undefined, + recentOrderDate: undefined, + recentOrderNumber: undefined, + registrationDate: undefined, + registrant: undefined, + lastModifiedDate: undefined, + lastModifier: undefined, ...searchParams, } - const result = await getVendorPools(params) + console.log('VendorPoolTable - API call params:', params) + const result = await getVendorPools(params as GetVendorPoolSchema) + console.log('VendorPoolTable - API result:', { + dataCount: result.data.length, + pageCount: result.pageCount, + requestedPage: params.page + }) setData(result.data) setPageCount(result.pageCount) } catch (error) { @@ -155,9 +131,11 @@ export function VendorPoolTable({ // 전체보기 모드에서는 페이징 없이 전체 데이터 로드 loadData({ perPage: 1000 }) // 충분히 큰 숫자로 전체 데이터 가져오기 } else { - loadData({}) + // 검색 시 페이지를 1페이지로 리셋 + setPagination(prev => ({ ...prev, pageIndex: 0 })) + loadData({ page: 1, perPage: pagination.pageSize }) } - }, [loadData, showAll]) + }, [loadData, showAll, pagination.pageSize]) // 전체보기 토글 핸들러 const handleShowAllToggle = React.useCallback((checked: boolean) => { @@ -174,8 +152,18 @@ export function VendorPoolTable({ // 초기 데이터 로드 React.useEffect(() => { - loadData({}) - }, [loadData]) + // 초기 로드 시 페이지를 1페이지로 설정 + setPagination(prev => ({ ...prev, pageIndex: 0 })) + loadData({ page: 1, perPage: pagination.pageSize }) + }, [pagination.pageSize]) + + // reloadTrigger가 변경될 때마다 데이터 리로드 + React.useEffect(() => { + if (reloadTrigger && reloadTrigger > 0) { + console.log('VendorPoolTable - reloadTrigger changed, reloading data') + loadData({}) + } + }, [reloadTrigger, loadData]) const table = useReactTable({ data, @@ -186,27 +174,48 @@ export function VendorPoolTable({ getFilteredRowModel: getFilteredRowModel(), manualPagination: !showAll, // 전체보기 시에는 수동 페이징 비활성화 pageCount: showAll ? 1 : pageCount, // 전체보기 시 1페이지, 일반 모드에서는 API에서 받은 pageCount 사용 - initialState: { - pagination: { - pageSize: showAll ? data.length : 10, // 전체보기 시 모든 데이터 표시 - }, + state: { + pagination: showAll ? { pageIndex: 0, pageSize: data.length } : pagination, }, onPaginationChange: (updater) => { if (!showAll) { // 전체보기가 아닐 때만 페이징 변경 처리 - const newState = typeof updater === 'function' ? updater(table.getState().pagination) : updater - loadData({ - page: newState.pageIndex + 1, - perPage: newState.pageSize, + const newPaginationState = typeof updater === 'function' ? updater(pagination) : updater + + console.log('VendorPoolTable - Pagination changed:', { + currentState: pagination, + newPaginationState, + showAll, + willLoadData: !showAll }) + + setPagination(newPaginationState) + + const apiParams = { + page: newPaginationState.pageIndex + 1, + perPage: newPaginationState.pageSize, + } + console.log('VendorPoolTable - Loading data with params:', apiParams) + loadData(apiParams) } }, }) + // 외부에서 선택된 ID들을 가져올 수 있도록 ref에 메소드 노출 + useImperativeHandle(ref, () => ({ + getSelectedIds: () => { + const selectedRows = table.getFilteredSelectedRowModel().rows + return selectedRows.map(row => row.original.id) + } + })) + + // 선택된 행 개수 + const selectedRowCount = table.getFilteredSelectedRowModel().rows.length + // 선택 상태 변경 시 콜백 호출 React.useEffect(() => { - onSelectionChange?.(table.getFilteredSelectedRowModel().rows.length) - }, [table.getFilteredSelectedRowModel().rows.length, onSelectionChange]) + onSelectionChange?.(selectedRowCount) + }, [selectedRowCount, onSelectionChange]) // 선택 해제 요청이 오면 모든 선택 해제 React.useEffect(() => { @@ -287,4 +296,6 @@ export function VendorPoolTable({ </div> </div> ) -} +}) + +VendorPoolTable.displayName = "VendorPoolTable" |
