diff --git a/apps/st/src/components/module/CompactDataGrid.tsx b/apps/st/src/components/module/CompactDataGrid.tsx index 4e193c532..36a17b225 100644 --- a/apps/st/src/components/module/CompactDataGrid.tsx +++ b/apps/st/src/components/module/CompactDataGrid.tsx @@ -1,9 +1,9 @@ -import { useRef, useEffect } from "react" +import { useRef, useEffect, useLayoutEffect } from "react" import { ValueType } from "realgrid" import RealGrid, { GridFitStyle } from "realgrid" import { RealGridReact, RGDataColumn } from "realgrid-react" -import type { DataGridProps, RealGridColumnInfo, GridViewWithSetColumns, FooterItemWithCallback } from "../type/DataGrid.type" +import type { DataGridProps, RealGridColumnInfo, GridViewWithSetColumns, FooterItemWithCallback, CellStyleCallback } from "../type/DataGrid.type" import { getComputedValueCallback } from "@/components/util/grid/computedFieldCallbacks" // RealGrid 타입 확장 @@ -62,15 +62,36 @@ function createNumberComparer(dp: RealGridDataProviderComparer): (field: string }; } -const CompactDataGrid = ({ columnInfo, fixedColumns, showHeaderCheckbox = false, rowData }: DataGridProps) => { +const CompactDataGrid = ({ + columnInfo, + fixedColumns, + showHeaderCheckbox = false, + rowData, + setRowData, + getGridDataRef, + cellStyleCallback, + onRowClick, +}: DataGridProps) => { const { columns, columnLayout } = columnInfo; const gridRef = useRef(null); + const rowDataRef = useRef[]>(rowData); + const cellStyleCallbackRef = useRef(cellStyleCallback); + rowDataRef.current = rowData; + cellStyleCallbackRef.current = cellStyleCallback; + + useLayoutEffect(() => { + if (!cellStyleCallback || !gridRef.current?.gridView) return; + gridRef.current.gridView.refresh(); + }, [cellStyleCallback, rowData]); useEffect(() => { if (!gridRef.current?.gridView || !gridRef.current?.dataProvider) return; const gridView = gridRef.current.gridView; const dataProvider = gridRef.current.dataProvider; + if ((dataProvider as { setRows?: (r: unknown[]) => void })?.setRows && rowData) { + (dataProvider as { setRows: (r: unknown[]) => void }).setRows(rowData); + } // setDataComparer로 숫자 정렬 (setFields 미사용 → 데이터 유실·필드 중복 오류 없음) const dp = dataProvider as RealGridDataProviderComparer; @@ -231,11 +252,11 @@ const CompactDataGrid = ({ columnInfo, fixedColumns, showHeaderCheckbox = false, // footer가 단일 객체이고 valueCallback이 있는 경우 columns.forEach(col => { if (!col.footer || Array.isArray(col.footer)) return; - + try { const column = currentGridView.columnByName(col.name); if (!column || !column.footer) return; - + if (col.footer.valueCallback) { (column.footer as { valueCallback?: typeof col.footer.valueCallback }).valueCallback = col.footer.valueCallback; } @@ -243,9 +264,75 @@ const CompactDataGrid = ({ columnInfo, fixedColumns, showHeaderCheckbox = false, console.warn(`Error setting footer valueCallback for column ${col.name}:`, e); } }); + + // cellStyleCallback이 있으면 컬럼별 styleCallback 설정 + if (cellStyleCallbackRef.current) { + columns.forEach((column) => { + const baseStyleName = column.styleName; + const gridCol = currentGridView.columnByName(column.name) as { + styleCallback?: (g: unknown, dataCell: { itemIndex?: number; index?: { itemIndex?: number }; dataField?: string; fieldName?: string }) => string; + } | null; + if (gridCol) { + gridCol.styleCallback = (_g, dataCell) => { + const itemIndex = dataCell?.index?.itemIndex ?? dataCell?.itemIndex ?? -1; + const fieldName = (dataCell?.dataField ?? dataCell?.fieldName ?? column.fieldName) ?? ''; + const data = rowDataRef.current; + if (itemIndex < 0 || itemIndex >= data.length) return baseStyleName ?? ''; + const row = data[itemIndex] as Record; + const extra = cellStyleCallbackRef.current?.({ rowIndex: itemIndex, fieldName, row }); + if (!extra) return baseStyleName ?? ''; + return baseStyleName ? `${extra} ${baseStyleName}` : extra; + }; + } + }); + } + currentGridView.refresh?.(); }, 200); - }, [columns, columnLayout, fixedColumns, rowData, showHeaderCheckbox]); + if (getGridDataRef) { + const fieldNames = columns.map((c) => c.fieldName).filter(Boolean) as string[]; + getGridDataRef.current = () => { + const gv = gridRef.current?.gridView as { + getDataSource?: () => { getRowCount(): number; getValue(r: number, f: string): unknown }; + } | undefined; + if (!gv?.getDataSource) return []; + const ds = gv.getDataSource(); + if (!ds) return []; + const cnt = ds.getRowCount(); + const rows: Record[] = []; + for (let i = 0; i < cnt; i++) { + const r: Record = {}; + for (const f of fieldNames) r[f] = ds.getValue(i, f) as string | number; + rows.push(r); + } + return rows; + }; + } + + return () => { + if (getGridDataRef) getGridDataRef.current = null; + }; + }, [columns, columnLayout, fixedColumns, rowData, showHeaderCheckbox, getGridDataRef]); + + // 행 클릭 이벤트 + useEffect(() => { + const gridView = gridRef.current?.gridView; + if (!gridView || !onRowClick) return; + + gridView.onCellClicked = (grid, clickData) => { + if (clickData.cellType !== "data" || clickData.itemIndex === undefined) return; + try { + const row = rowDataRef.current[clickData.itemIndex]; + onRowClick((row ?? {}) as Record); + } catch (error) { + console.error("행 데이터 가져오기 오류:", error); + } + }; + + return () => { + gridView.onCellClicked = undefined; + }; + }, [onRowClick]); return (
@@ -256,10 +343,15 @@ const CompactDataGrid = ({ columnInfo, fixedColumns, showHeaderCheckbox = false, layout={columnLayout} rows={rowData} onInitialized={() => { - const dp = gridRef.current?.dataProvider as { setFields?: (fields: unknown[]) => void } | undefined; + const dp = gridRef.current?.dataProvider as + | { setFields?(f: unknown[]): void; setRows?(r: Record[]): void } + | undefined; if (dp?.setFields) { dp.setFields(buildFieldsFromColumns(columns)); } + if (dp?.setRows && rowData?.length) { + dp.setRows(rowData); + } }} > {columns.map((column) => ( diff --git a/apps/st/src/components/statistics/management/LogHistory.tsx b/apps/st/src/components/statistics/management/LogHistory.tsx index 9cecf9ed5..0b45ce9fd 100644 --- a/apps/st/src/components/statistics/management/LogHistory.tsx +++ b/apps/st/src/components/statistics/management/LogHistory.tsx @@ -1,61 +1,60 @@ "use client"; import { useState } from 'react'; -import useSWR from 'swr'; +// import useSWR from 'swr'; import { Button, - Input, + // Input, Label, - Select, - SelectTrigger, - SelectContent, - SelectItem, - SelectValue + // Select, + // SelectTrigger, + // SelectContent, + // SelectItem, + // SelectValue } from "@common/components"; import DataGrid from '@/components/module/DataGrid'; +import { CodeSelect } from '@/entities/code'; import { LogHistoryColumn } from '@/components/util/column/management/LogHistoryColumn'; import { useAlertStore } from "@/shared/lib"; -import { - LwpoCodeApi, -} from "@/entities/code"; +// import { LwpoCodeApi } from "@/entities/code"; -const getStateCdListFetcher = async () => { - return LwpoCodeApi.getLwpoCodeList({ - sort: 'regDt,desc', - upCd: 'STITEM', - page: 0, - size: 100, - }); -} +// const getStateCdListFetcher = async () => { +// return LwpoCodeApi.getLwpoCodeList({ +// sort: 'regDt,desc', +// upCd: 'STITEM', +// page: 0, +// size: 100, +// }); +// } const LogHistory = () => { - const { setMessage: alert } = useAlertStore((state) => state); - const [lwpoCd, setLwpoCd] = useState(''); + // const { setMessage: alert } = useAlertStore((state) => state); + const [statsCd, setStatsCd] = useState(''); - const { data: lwpoCdList } = useSWR( - "lwpo-code-list", - getStateCdListFetcher, - { - revalidateOnFocus: false, - revalidateOnReconnect: false, - revalidateIfStale: false, - dedupingInterval: 2000, - shouldRetryOnError: false, - onSuccess: (data) => { - if (!data.content || data.content.length == 0) { - alert(`시도 목록을 불러오는데 실패했습니다. - 새로고침 후 다시 시도해주세요.`); - } - }, - onError: () => { - alert(`시도 목록을 불러오는데 실패했습니다. - 새로고침 후 다시 시도해주세요.`); - }, - } - ); + // const { data: lwpoCdList } = useSWR( + // "lwpo-code-list", + // getStateCdListFetcher, + // { + // revalidateOnFocus: false, + // revalidateOnReconnect: false, + // revalidateIfStale: false, + // dedupingInterval: 2000, + // shouldRetryOnError: false, + // onSuccess: (data) => { + // if (!data.content || data.content.length == 0) { + // alert(`시도 목록을 불러오는데 실패했습니다. + // 새로고침 후 다시 시도해주세요.`); + // } + // }, + // onError: () => { + // alert(`시도 목록을 불러오는데 실패했습니다. + // 새로고침 후 다시 시도해주세요.`); + // }, + // } + // ); return (
@@ -64,9 +63,9 @@ const LogHistory = () => {
- @@ -78,7 +77,14 @@ const LogHistory = () => { ))} - + */} +
+ +
+
+ +
+
+
+ + + No + 검증항목 + 등록자 + 등록일 + 사용여부 + + + + + 1 + + + 인구수검증 + + + 관리자 + + + 2026-02-09 + + + Y + + + +
+
+
+ +
+
+
+ ); +}; + +export default GeneralVerificationManagement; \ No newline at end of file