st: feat: 일반검증 컴포넌트 구현중
This commit is contained in:
@@ -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<RealGridReact>(null);
|
||||
const rowDataRef = useRef<Record<string, string | number>[]>(rowData);
|
||||
const cellStyleCallbackRef = useRef<CellStyleCallback | undefined>(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<string, string | number>;
|
||||
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<string, string | number>[] = [];
|
||||
for (let i = 0; i < cnt; i++) {
|
||||
const r: Record<string, string | number> = {};
|
||||
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<string, string | number>);
|
||||
} catch (error) {
|
||||
console.error("행 데이터 가져오기 오류:", error);
|
||||
}
|
||||
};
|
||||
|
||||
return () => {
|
||||
gridView.onCellClicked = undefined;
|
||||
};
|
||||
}, [onRowClick]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-[0.6rem] mx-[0.6rem] w-1/2">
|
||||
@@ -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<string, string | number>[]): void }
|
||||
| undefined;
|
||||
if (dp?.setFields) {
|
||||
dp.setFields(buildFieldsFromColumns(columns));
|
||||
}
|
||||
if (dp?.setRows && rowData?.length) {
|
||||
dp.setRows(rowData);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{columns.map((column) => (
|
||||
|
||||
Reference in New Issue
Block a user