[st] feat: DataGrid 컴포넌트에 행 클릭 이벤트 설정

This commit is contained in:
2026-02-11 15:45:38 +09:00
parent c439d3e58a
commit fbe355f6cf
3 changed files with 738 additions and 294 deletions
File diff suppressed because it is too large Load Diff
@@ -70,17 +70,38 @@ const VerificationArticleManagement = () => {
console.log("등록");
};
// 행 클릭 이벤트 핸들러
const handleRowClick = (rowData: Record<string, string | number>) => {
console.log("클릭한 행 데이터:", rowData);
// 여기에 필요한 로직 추가 (예: 상세 정보 표시, 수정 모달 열기 등)
};
return (
<Tabs variant="underline" defaultValue="HB">
<Tabs defaultValue="HB">
{/* 탭 리스트 */}
<TabsList>
<TabsTrigger value="HB">H-B</TabsTrigger>
<TabsTrigger value="IMR">I-MR</TabsTrigger>
<TabsTrigger value="VALIDATION">Validation</TabsTrigger>
<TabsTrigger
value="HB"
className="!px-[2rem] !py-[0.8rem] !text-[1.2rem]"
>
H-B
</TabsTrigger>
<TabsTrigger
value="IMR"
className="!px-[2rem] !py-[0.8rem] !text-[1.2rem]"
>
I-MR
</TabsTrigger>
<TabsTrigger
value="VALIDATION"
className="!px-[2rem] !py-[0.8rem] !text-[1.2rem]"
>
Validation
</TabsTrigger>
</TabsList>
<div className="card card-border !mx-0">
<div className="flex items-end gap-4">
<div className="flex items-center gap-4">
<div className="flex items-center gap-4">
<Label className="whitespace-nowrap px-4 text-label">
통계항목
@@ -130,40 +151,31 @@ const VerificationArticleManagement = () => {
{/* H-B 탭 콘텐츠 */}
<TabsContent value="HB">
{/* 데이터 그리드 */}
<DataGrid
columnInfo={hbArticleColumnInfo}
rowData={hbRowData}
setRowData={setHbRowData}
isExcelImport={false}
isExcelExport={false}
showHeaderCheckbox={false}
onRowClick={handleRowClick}
/>
</TabsContent>
{/* I-MR 탭 콘텐츠 */}
<TabsContent value="IMR">
{/* 데이터 그리드 */}
<DataGrid
columnInfo={imrArticleColumnInfo}
rowData={imrRowData}
setRowData={setImrRowData}
isExcelImport={false}
isExcelExport={false}
showHeaderCheckbox={false}
onRowClick={handleRowClick}
/>
</TabsContent>
{/* Validation 탭 콘텐츠 */}
<TabsContent value="VALIDATION">
{/* 데이터 그리드 */}
<DataGrid
columnInfo={validationArticleColumnInfo}
rowData={validationRowData}
setRowData={setValidationRowData}
isExcelImport={false}
isExcelExport={false}
showHeaderCheckbox={false}
onRowClick={handleRowClick}
/>
</TabsContent>
</Tabs>
+119 -48
View File
@@ -11,28 +11,55 @@ export type RealGridColumnInfo = {
valueType?: import("realgrid").ValueType;
dataFormat?: string;
styleName?: string;
mergeRule?: { criteria: 'value' };
footer?: {
text?: string;
expression?: 'sum' | 'avg' | 'count' | 'max' | 'min';
numberFormat?: string;
valueCallback?: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => number | string;
} | Array<{
text?: string;
expression?: 'sum' | 'avg' | 'count' | 'max' | 'min';
numberFormat?: string;
valueCallback?: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => number | string;
}>;
mergeRule?: { criteria: "value" };
footer?:
| {
text?: string;
expression?: "sum" | "avg" | "count" | "max" | "min";
numberFormat?: string;
valueCallback?: (
grid: GridView,
column: DataColumn,
footerIndex: number,
columnFooter: ColumnFooter,
value: number | string | undefined,
) => number | string;
}
| Array<{
text?: string;
expression?: "sum" | "avg" | "count" | "max" | "min";
numberFormat?: string;
valueCallback?: (
grid: GridView,
column: DataColumn,
footerIndex: number,
columnFooter: ColumnFooter,
value: number | string | undefined,
) => number | string;
}>;
};
/** setColumns 메서드가 있는 GridView */
export type GridViewWithSetColumns = GridView & { setColumns?: (columns: RealGridColumnInfo[]) => void };
export type GridViewWithSetColumns = GridView & {
setColumns?: (columns: RealGridColumnInfo[]) => void;
};
/** footer 배열 요소에 valueCallback 할당용 */
export type FooterItemWithCallback = { valueCallback?: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => number | string };
export type FooterItemWithCallback = {
valueCallback?: (
grid: GridView,
column: DataColumn,
footerIndex: number,
columnFooter: ColumnFooter,
value: number | string | undefined,
) => number | string;
};
export type GridView = {
getSummary(field: string, summary: 'sum' | 'avg' | 'count' | 'max' | 'min'): number | undefined;
getSummary(
field: string,
summary: "sum" | "avg" | "count" | "max" | "min",
): number | undefined;
getDataSource(): {
getRowCount(): number;
getValue(rowIndex: number, field: string): number | string;
@@ -41,7 +68,12 @@ export type GridView = {
getDataRow(itemIndex: number): number;
};
export type MergeCallback = (grid: GridView, column: DataColumn, itemIndex: number, value: number | string | null | undefined) => number | null;
export type MergeCallback = (
grid: GridView,
column: DataColumn,
itemIndex: number,
value: number | string | null | undefined,
) => number | null;
export type DataColumn = {
name: string;
@@ -66,15 +98,28 @@ export type DataFieldValueCallback = (
dataRow: number,
fieldName: string,
fieldNames: string[],
values: unknown[]
values: unknown[],
) => number | string | undefined;
/** 계산 필드 설정 (computedFieldCallbacks.ts 참고) */
export type ComputedFieldConfig =
| { fields: string[]; type: "sum" | "avg" }
| { numeratorFields: string[]; denominatorFields: string[]; type: "pblswrgPopltnSuprtRate" }
| { numeratorFields: string[]; denominatorFields: string[]; type: "adtrtPopltnSuprtRate" }
| { numeratorFields: string[]; denominatorFields: string[]; thirdFields: string[], type: "swrgInstlrtRate" };
| {
numeratorFields: string[];
denominatorFields: string[];
type: "pblswrgPopltnSuprtRate";
}
| {
numeratorFields: string[];
denominatorFields: string[];
type: "adtrtPopltnSuprtRate";
}
| {
numeratorFields: string[];
denominatorFields: string[];
thirdFields: string[];
type: "swrgInstlrtRate";
};
export type ColumnConfig = {
name: string;
@@ -92,18 +137,32 @@ export type ColumnConfig = {
sortPreserveGroupOrder?: SortPreserveGroupOrder;
valueType?: ValueType;
dataFormat?: string;
footer?: {
text?: string;
expression?: 'sum' | 'avg' | 'count' | 'max' | 'min';
numberFormat?: string;
valueCallback?: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => number | string;
multiRow?: boolean; // 여러 행 footer 사용 여부
} | Array<{
text?: string;
expression?: 'sum' | 'avg' | 'count' | 'max' | 'min';
numberFormat?: string;
valueCallback?: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => number | string;
}>, // RealGrid에서 footer를 배열로 설정할 수 있음
footer?:
| {
text?: string;
expression?: "sum" | "avg" | "count" | "max" | "min";
numberFormat?: string;
valueCallback?: (
grid: GridView,
column: DataColumn,
footerIndex: number,
columnFooter: ColumnFooter,
value: number | string | undefined,
) => number | string;
multiRow?: boolean; // 여러 행 footer 사용 여부
}
| Array<{
text?: string;
expression?: "sum" | "avg" | "count" | "max" | "min";
numberFormat?: string;
valueCallback?: (
grid: GridView,
column: DataColumn,
footerIndex: number,
columnFooter: ColumnFooter,
value: number | string | undefined,
) => number | string;
}>; // RealGrid에서 footer를 배열로 설정할 수 있음
};
export type FooterUserSpan = {
@@ -112,16 +171,19 @@ export type FooterUserSpan = {
text?: string; // 표시할 텍스트
};
export type ColumnLayoutItem = string | {
name: string;
hideChildHeaders?: boolean;
header: { text: string };
items: (string | ColumnLayoutItem)[];
footerUserSpans?: FooterUserSpan[]; // footer 병합 설정
} | {
column: string; // 컬럼 이름 (footerUserSpans 사용 시)
footerUserSpans?: FooterUserSpan[]; // footer 병합 설정
};
export type ColumnLayoutItem =
| string
| {
name: string;
hideChildHeaders?: boolean;
header: { text: string };
items: (string | ColumnLayoutItem)[];
footerUserSpans?: FooterUserSpan[]; // footer 병합 설정
}
| {
column: string; // 컬럼 이름 (footerUserSpans 사용 시)
footerUserSpans?: FooterUserSpan[]; // footer 병합 설정
};
export type ColumnInfo = {
columns: ColumnConfig[];
@@ -138,7 +200,7 @@ export type ColumnInfoList = {
isSplitGrid?: boolean; // 5:5 분리형 그리드 유무
left?: ColumnInfoList; // SplitDataGrid용 왼쪽 그리드 정보
right?: ColumnInfoList; // SplitDataGrid용 오른쪽 그리드 정보
}
};
export type DataGridProps = {
columnInfo: ColumnInfo;
@@ -149,7 +211,10 @@ export type DataGridProps = {
fixedColumns?: number; // 고정할 컬럼 개수 (좌측부터)
showHeaderCheckbox?: boolean; // 헤더 체크박스 표시 여부 (기본값: true)
rowData: Record<string, string | number>[];
setRowData: React.Dispatch<React.SetStateAction<Record<string, string | number>[]>>;
setRowData: React.Dispatch<
React.SetStateAction<Record<string, string | number>[]>
>;
onRowClick?: (rowData: Record<string, string | number>) => void; // 행 클릭 이벤트
};
export type TabDataGridProps = {
@@ -160,7 +225,9 @@ export type TabDataGridProps = {
onRowsChange?: (rows: Record<string, string | number>[]) => void;
showHeaderCheckbox?: boolean; // 헤더 체크박스 표시 여부 (기본값: true)
rowDataMap: Map<string, Record<string, string | number>[]>;
setRowDataMap: React.Dispatch<React.SetStateAction<Map<string, Record<string, string | number>[]>>>;
setRowDataMap: React.Dispatch<
React.SetStateAction<Map<string, Record<string, string | number>[]>>
>;
isSplitGrid?: boolean; // 5:5 분리형 그리드 유무
};
@@ -172,6 +239,10 @@ export type SplitDataGridProps = {
showHeaderCheckbox?: boolean;
leftRowData: Record<string, string | number>[];
rightRowData: Record<string, string | number>[];
setLeftRowData: React.Dispatch<React.SetStateAction<Record<string, string | number>[]>>;
setRightRowData: React.Dispatch<React.SetStateAction<Record<string, string | number>[]>>;
};
setLeftRowData: React.Dispatch<
React.SetStateAction<Record<string, string | number>[]>
>;
setRightRowData: React.Dispatch<
React.SetStateAction<Record<string, string | number>[]>
>;
};