summaryrefslogtreecommitdiff
path: root/components/form-data/form-data-table-columns.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'components/form-data/form-data-table-columns.tsx')
-rw-r--r--components/form-data/form-data-table-columns.tsx218
1 files changed, 148 insertions, 70 deletions
diff --git a/components/form-data/form-data-table-columns.tsx b/components/form-data/form-data-table-columns.tsx
index 3749fe02..930e113b 100644
--- a/components/form-data/form-data-table-columns.tsx
+++ b/components/form-data/form-data-table-columns.tsx
@@ -42,6 +42,11 @@ export interface DataTableColumnJSON {
uom?: string;
uomId?: string;
shi?: boolean;
+
+ /** 템플릿에서 가져온 추가 정보 */
+ hidden?: boolean; // true이면 컬럼 숨김
+ seq?: number; // 정렬 순서
+ head?: string; // 헤더 텍스트 (우선순위 가장 높음)
}
/**
@@ -87,79 +92,70 @@ function getStatusBadgeVariant(status: string): "default" | "secondary" | "destr
}
/**
- * getColumns 함수
- * 1) columnsJSON 배열을 순회하면서 accessorKey / header / cell 등을 설정
- * 2) 체크박스 컬럼 추가 (showBatchSelection이 true일 때)
- * 3) 마지막에 "Action" 칼럼(예: update 버튼) 추가
+ * 헤더 텍스트를 결정하는 헬퍼 함수
+ * displayLabel이 있으면 사용, 없으면 label 사용
*/
-export function getColumns<TData extends object>({
- columnsJSON,
- setRowAction,
- setReportData,
- tempCount,
- selectedRows = {},
- onRowSelectionChange,
- // editableFieldsMap 매개변수 제거됨
-}: GetColumnsProps<TData>): ColumnDef<TData>[] {
- const columns: ColumnDef<TData>[] = [];
+function getHeaderText(col: DataTableColumnJSON): string {
+ if (col.displayLabel && col.displayLabel.trim()) {
+ return col.displayLabel;
+ }
+ return col.label;
+}
- // (1) 체크박스 컬럼 (항상 표시)
- const selectColumn: ColumnDef<TData> = {
- id: "select",
- header: ({ table }) => (
- <Checkbox
- checked={
- table.getIsAllPageRowsSelected() ||
- (table.getIsSomePageRowsSelected() && "indeterminate")
- }
- onCheckedChange={(value) => {
- table.toggleAllPageRowsSelected(!!value);
-
- // 모든 행 선택/해제
- if (onRowSelectionChange) {
- const allRowsSelection: Record<string, boolean> = {};
- table.getRowModel().rows.forEach((row) => {
- allRowsSelection[row.id] = !!value;
- });
- onRowSelectionChange(allRowsSelection);
- }
- }}
- aria-label="Select all"
- className="translate-y-[2px]"
- />
- ),
- cell: ({ row }) => (
- <Checkbox
- checked={row.getIsSelected()}
- onCheckedChange={(value) => {
- row.toggleSelected(!!value);
-
- // 개별 행 선택 상태 업데이트
- if (onRowSelectionChange) {
- onRowSelectionChange(prev => ({
- ...prev,
- [row.id]: !!value
- }));
- }
- }}
- aria-label="Select row"
- className="translate-y-[2px]"
- />
- ),
- enableSorting: false,
- enableHiding: false,
- enablePinning: true,
- size: 40,
- };
- columns.push(selectColumn);
+/**
+ * 컬럼들을 head 값에 따라 그룹핑하는 헬퍼 함수
+ */
+function groupColumnsByHead(columns: DataTableColumnJSON[]): ColumnDef<any>[] {
+ const groupedColumns: ColumnDef<any>[] = [];
+ const groupMap = new Map<string, DataTableColumnJSON[]>();
+ const ungroupedColumns: DataTableColumnJSON[] = [];
+
+ // head 값에 따라 컬럼들을 그룹핑
+ columns.forEach(col => {
+ if (col.head && col.head.trim()) {
+ const groupKey = col.head.trim();
+ if (!groupMap.has(groupKey)) {
+ groupMap.set(groupKey, []);
+ }
+ groupMap.get(groupKey)!.push(col);
+ } else {
+ ungroupedColumns.push(col);
+ }
+ });
+
+ // 그룹핑된 컬럼들 처리
+ groupMap.forEach((groupColumns, groupHeader) => {
+ if (groupColumns.length === 1) {
+ // 그룹에 컬럼이 하나만 있으면 일반 컬럼으로 처리
+ ungroupedColumns.push(groupColumns[0]);
+ } else {
+ // 그룹 컬럼 생성
+ const groupColumn: ColumnDef<any> = {
+ header: groupHeader,
+ columns: groupColumns.map(col => createColumnDef(col))
+ };
+ groupedColumns.push(groupColumn);
+ }
+ });
+
+ // 그룹핑되지 않은 컬럼들 처리
+ ungroupedColumns.forEach(col => {
+ groupedColumns.push(createColumnDef(col));
+ });
+
+ return groupedColumns;
+}
- // (2) 기본 컬럼들
- const baseColumns: ColumnDef<TData>[] = columnsJSON.map((col) => ({
+/**
+ * 개별 컬럼 정의를 생성하는 헬퍼 함수
+ */
+function createColumnDef(col: DataTableColumnJSON): ColumnDef<any> {
+ return {
accessorKey: col.key,
header: ({ column }) => (
<ClientDataTableColumnHeaderSimple
column={column}
- title={col.displayLabel || col.label}
+ title={getHeaderText(col)}
/>
),
@@ -240,11 +236,93 @@ export function getColumns<TData extends object>({
);
}
},
- }));
+ };
+}
+
+/**
+ * getColumns 함수
+ * 1) columnsJSON 배열을 필터링 (hidden이 true가 아닌 것들만)
+ * 2) seq에 따라 정렬
+ * 3) head 값에 따라 컬럼 그룹핑
+ * 4) 체크박스 컬럼 추가
+ * 5) 마지막에 "Action" 칼럼 추가
+ */
+export function getColumns<TData extends object>({
+ columnsJSON,
+ setRowAction,
+ setReportData,
+ tempCount,
+ selectedRows = {},
+ onRowSelectionChange,
+ // editableFieldsMap 매개변수 제거됨
+}: GetColumnsProps<TData>): ColumnDef<TData>[] {
+ const columns: ColumnDef<TData>[] = [];
+
+ // (0) 컬럼 필터링 및 정렬
+ const visibleColumns = columnsJSON
+ .filter(col => col.hidden !== true) // hidden이 true가 아닌 것들만
+ .sort((a, b) => {
+ // seq가 없는 경우 999999로 처리하여 맨 뒤로 보냄
+ const seqA = a.seq !== undefined ? a.seq : 999999;
+ const seqB = b.seq !== undefined ? b.seq : 999999;
+ return seqA - seqB;
+ });
+
+ // (1) 체크박스 컬럼 (항상 표시)
+ const selectColumn: ColumnDef<TData> = {
+ id: "select",
+ header: ({ table }) => (
+ <Checkbox
+ checked={
+ table.getIsAllPageRowsSelected() ||
+ (table.getIsSomePageRowsSelected() && "indeterminate")
+ }
+ onCheckedChange={(value) => {
+ table.toggleAllPageRowsSelected(!!value);
+
+ // 모든 행 선택/해제
+ if (onRowSelectionChange) {
+ const allRowsSelection: Record<string, boolean> = {};
+ table.getRowModel().rows.forEach((row) => {
+ allRowsSelection[row.id] = !!value;
+ });
+ onRowSelectionChange(allRowsSelection);
+ }
+ }}
+ aria-label="Select all"
+ className="translate-y-[2px]"
+ />
+ ),
+ cell: ({ row }) => (
+ <Checkbox
+ checked={row.getIsSelected()}
+ onCheckedChange={(value) => {
+ row.toggleSelected(!!value);
+
+ // 개별 행 선택 상태 업데이트
+ if (onRowSelectionChange) {
+ onRowSelectionChange(prev => ({
+ ...prev,
+ [row.id]: !!value
+ }));
+ }
+ }}
+ aria-label="Select row"
+ className="translate-y-[2px]"
+ />
+ ),
+ enableSorting: false,
+ enableHiding: false,
+ enablePinning: true,
+ size: 40,
+ };
+ columns.push(selectColumn);
- columns.push(...baseColumns);
+ // (2) 기본 컬럼들 (head에 따라 그룹핑 처리)
+ const groupedColumns = groupColumnsByHead(visibleColumns);
+ columns.push(...groupedColumns);
- // (4) 액션 칼럼 - update 버튼 예시
+ // (3) 액션 칼럼 - update 버튼 예시
const actionColumn: ColumnDef<TData> = {
id: "update",
header: "",
@@ -297,6 +375,6 @@ export function getColumns<TData extends object>({
columns.push(actionColumn);
- // (5) 최종 반환
+ // (4) 최종 반환
return columns;
} \ No newline at end of file