st: fix: 하수도보급률 저장, 일반 검증 결과 체크

This commit is contained in:
2026-02-19 10:45:56 +09:00
parent 2873d1b0b9
commit 4a74cd0394
7 changed files with 131 additions and 40 deletions
+77 -26
View File
@@ -1,9 +1,9 @@
import { useRef, useEffect } from "react";
import { useRef, useEffect, useLayoutEffect } from "react";
import { ValueType } from "realgrid";
import RealGrid, { GridFitStyle, type DisplayOptions } from "realgrid";
import { RealGridReact, RGDataColumn } from "realgrid-react";
import type { DataGridProps, RealGridColumnInfo, GridViewWithSetColumns, FooterItemWithCallback, ColumnLayoutItem } from "../type/DataGrid.type";
import type { DataGridProps, RealGridColumnInfo, GridViewWithSetColumns, FooterItemWithCallback, ColumnLayoutItem, CellStyleCallback } from "../type/DataGrid.type";
import { getComputedValueCallback } from "@/components/util/grid/computedFieldCallbacks";
import JSZip from "jszip";
import * as XLSX from "xlsx";
@@ -289,12 +289,33 @@ function buildFieldsFromColumns(columns: { fieldName: string; valueType?: ValueT
});
}
const DataGrid = ({ columnInfo, rowStartNum, isExcelImport = true, isExcelExport = true, fixedColumns, showHeaderCheckbox = false, rowData, setRowData, getGridDataRef }: DataGridProps) => {
const DataGrid = ({
columnInfo,
rowStartNum,
isExcelImport = true,
isExcelExport = true,
fixedColumns,
showHeaderCheckbox = false,
rowData,
setRowData,
getGridDataRef,
cellStyleCallback,
}: DataGridProps) => {
const { columns, columnLayout } = columnInfo;
const gridRef = useRef<RealGridReact>(null);
const fileInputRef = useRef<HTMLInputElement>(null);
const sortDirRef = useRef<Record<string, "asc" | "desc" | "none">>({});
const originalRowsRef = useRef<Record<string, Record<string, string | number>[]>>({});
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]);
const { setMessage: alert } = useAlertStore((state) => state);
const activeTabId = useTabStore((state) => state.activeTabId);
const menuList = useTabStore((state) => state.menuList);
@@ -801,6 +822,7 @@ const DataGrid = ({ columnInfo, rowStartNum, isExcelImport = true, isExcelExport
layout={columnLayout}
rows={rowData}
onInitialized={(grid) => {
if (!grid) return;
(grid as { onSorting?: (g: unknown, f: unknown[], d: unknown[]) => boolean }).onSorting = createOnSortingHandler(columns, setRowData, sortDirRef, originalRowsRef);
const dataProvider = gridRef.current?.dataProvider as unknown as
| { setFields?(f: unknown[]): void; setRows?(r: Record<string, string | number>[]): void; getJsonRow?(r: number): Record<string, unknown> }
@@ -811,32 +833,61 @@ const DataGrid = ({ columnInfo, rowStartNum, isExcelImport = true, isExcelExport
if (dataProvider?.setRows && rowData?.length) {
dataProvider.setRows(rowData);
}
if (!cellStyleCallbackRef.current) return;
const gridView = gridRef.current?.gridView ?? grid;
if (!gridView?.columnByName) return;
setTimeout(() => {
const gv = gridRef.current?.gridView;
if (!gv?.columnByName) return;
columns.forEach((column) => {
const baseStyleName = column.styleName ?? (column.editable === false ? 'rg-cell-readonly' : undefined);
const gridCol = gv.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;
};
}
});
gv.refresh();
}, 0);
}}
>
{columns.map((column) => (
<RGDataColumn
key={column.name}
name={column.name}
fieldName={column.fieldName}
valueType={column.valueType ? column.valueType : ValueType.TEXT}
{...(column.valueType === ValueType.NUMBER && { numberFormat: column.dataFormat ? column.dataFormat : '#,##0.000' })}
header={column.header}
editable={column.editable}
{...(column.styleName != null
? { styleName: column.styleName }
{columns.map((column) => {
const baseStyleName =
column.styleName != null
? column.styleName
: column.editable === false
? { styleName: 'rg-cell-readonly' as const }
: {})}
{...(column.visible === false && { visible: false })}
footer={column.footer && !Array.isArray(column.footer) ? {
text: column.footer.text,
expression: column.footer.expression,
numberFormat: column.footer.numberFormat,
} : undefined}
mergeRule={column.mergeCells ? { criteria: 'value' } : undefined}
sortable={!column.sortdisable}
/>
))}
? ('rg-cell-readonly' as const)
: undefined;
return (
<RGDataColumn
key={column.name}
name={column.name}
fieldName={column.fieldName}
valueType={column.valueType ? column.valueType : ValueType.TEXT}
{...(column.valueType === ValueType.NUMBER && { numberFormat: column.dataFormat ? column.dataFormat : '#,##0.000' })}
header={column.header}
editable={column.editable}
{...(baseStyleName != null && { styleName: baseStyleName })}
{...(column.visible === false && { visible: false })}
footer={column.footer && !Array.isArray(column.footer) ? {
text: column.footer.text,
expression: column.footer.expression,
numberFormat: column.footer.numberFormat,
} : undefined}
mergeRule={column.mergeCells ? { criteria: 'value' } : undefined}
sortable={!column.sortdisable}
/>
);
})}
</RealGridReact>
</div>
</div>