diff options
Diffstat (limited to 'lib/procurement-rfqs/table/rfq-table.tsx')
| -rw-r--r-- | lib/procurement-rfqs/table/rfq-table.tsx | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/lib/procurement-rfqs/table/rfq-table.tsx b/lib/procurement-rfqs/table/rfq-table.tsx new file mode 100644 index 00000000..510f474d --- /dev/null +++ b/lib/procurement-rfqs/table/rfq-table.tsx @@ -0,0 +1,209 @@ +"use client" + +import * as React from "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 { getColumns, EditingCellState } from "./rfq-table-column" +import { useEffect } from "react" +import { DataTableAdvancedToolbar } from "@/components/data-table/data-table-advanced-toolbar" +import { RFQTableToolbarActions } from "./rfq-table-toolbar-actions" +import { ProcurementRfqsView } from "@/db/schema" +import { getPORfqs } from "../services" +import { toast } from "sonner" +import { updateRfqRemark } from "@/lib/procurement-rfqs/services" // 구현 필요 + +interface RFQListTableProps { + data?: Awaited<ReturnType<typeof getPORfqs>>; + onSelectRFQ?: (rfq: ProcurementRfqsView | null) => void; + // 데이터 새로고침을 위한 콜백 추가 + onDataRefresh?: () => void; + maxHeight?: string | number; // Add this prop +} + +// 보다 유연한 타입 정의 +type LocalDataType = Awaited<ReturnType<typeof getPORfqs>>; + +export function RFQListTable({ + data, + onSelectRFQ, + onDataRefresh, + maxHeight +}: RFQListTableProps) { + const [rowAction, setRowAction] = React.useState<DataTableRowAction<ProcurementRfqsView> | null>(null) + // 인라인 에디팅을 위한 상태 추가 + const [editingCell, setEditingCell] = React.useState<EditingCellState | null>(null) + // 로컬 데이터를 관리하기 위한 상태 추가 + const [localData, setLocalData] = React.useState<LocalDataType>(data || { data: [], pageCount: 0, total: 0 }); + + // 데이터가 변경될 때 로컬 데이터도 업데이트 + useEffect(() => { + setLocalData(data || { data: [], pageCount: 0, total: 0 }) + }, [data]) + + + // 비고 업데이트 함수 + const updateRemark = async (rfqId: number, remark: string) => { + try { + // 낙관적 UI 업데이트 (로컬 데이터 먼저 갱신) + if (localData && localData.data) { + // 로컬 데이터에서 해당 행 찾기 + const rowIndex = localData.data.findIndex(row => row.id === rfqId); + if (rowIndex >= 0) { + // 불변성을 유지하면서 로컬 데이터 업데이트 + const newData = [...localData.data]; + newData[rowIndex] = { ...newData[rowIndex], remark }; + + // 전체 데이터 구조 복사하여 업데이트 + setLocalData({ ...localData, data: newData } as typeof localData); + } + } + + const result = await updateRfqRemark(rfqId, remark); + + if (result.success) { + toast.success("비고가 업데이트되었습니다"); + + // 서버 데이터 리프레시 호출 + if (onDataRefresh) { + onDataRefresh(); + } + } else { + toast.error(result.message || "업데이트 중 오류가 발생했습니다"); + } + } catch (error) { + console.error("비고 업데이트 오류:", error); + toast.error("업데이트 중 오류가 발생했습니다"); + } + } + + // 행 액션 처리 + useEffect(() => { + if (rowAction) { + // 액션 유형에 따라 처리 + switch (rowAction.type) { + case "select": + // 선택된 문서 처리 + if (onSelectRFQ) { + onSelectRFQ(rowAction.row.original) + } + break; + case "update": + // 업데이트 처리 로직 + console.log("Update rfq:", rowAction.row.original) + break; + case "delete": + // 삭제 처리 로직 + console.log("Delete rfq:", rowAction.row.original) + break; + } + + // 액션 처리 후 rowAction 초기화 + setRowAction(null) + } + }, [rowAction, onSelectRFQ]) + + const columns = React.useMemo( + () => getColumns({ + setRowAction, + editingCell, + setEditingCell, + updateRemark + }), + [setRowAction, editingCell, setEditingCell, updateRemark] + ) + + + // Filter fields + const filterFields: DataTableFilterField<ProcurementRfqsView>[] = [] + + const advancedFilterFields: DataTableAdvancedFilterField<ProcurementRfqsView>[] = [ + { + id: "rfqCode", + label: "RFQ No.", + type: "text", + }, + { + id: "projectCode", + label: "프로젝트", + type: "text", + }, + { + id: "itemCode", + label: "자재그룹", + type: "text", + }, + { + id: "itemName", + label: "자재명", + type: "text", + }, + + { + id: "rfqSealedYn", + label: "RFQ 밀봉여부", + type: "text", + }, + { + id: "majorItemMaterialCode", + label: "자재코드", + type: "text", + }, + { + id: "rfqSendDate", + label: "RFQ 전송일", + type: "date", + }, + { + id: "dueDate", + label: "RFQ 마감일", + type: "date", + }, + { + id: "createdByUserName", + label: "요청자", + type: "text", + }, + ] + + // useDataTable 훅으로 react-table 구성 - 로컬 데이터 사용하도록 수정 + const { table } = useDataTable({ + data: localData?.data || [], + columns, + pageCount: localData?.pageCount || 0, + rowCount: localData?.total || 0, // 총 레코드 수 추가 + filterFields, + enablePinning: true, + enableAdvancedFilter: true, + initialState: { + sorting: [{ id: "updatedAt", desc: true }], + }, + getRowId: (originalRow) => String(originalRow.id), + shallow: false, + clearOnDefault: true, + columnResizeMode: "onEnd", + }) + + return ( + <div className="w-full overflow-auto"> + <DataTable table={table} maxHeight={maxHeight}> + <DataTableAdvancedToolbar + table={table} + filterFields={advancedFilterFields} + shallow={false} + > + <RFQTableToolbarActions + table={table} + localData={localData} + setLocalData={setLocalData} + onSuccess={onDataRefresh} + /> + </DataTableAdvancedToolbar> + </DataTable> + </div> + ) +}
\ No newline at end of file |
