From 92eda21e45d902663052575aaa4c4f80bfa2faea Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Mon, 4 Aug 2025 09:36:14 +0000
Subject: (대표님) 벤더 문서 변경사항, data-table 변경, sync 변경
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 components/form-data/form-data-table-columns.tsx | 95 ++++++++++++++----------
 1 file changed, 56 insertions(+), 39 deletions(-)

(limited to 'components/form-data/form-data-table-columns.tsx')

diff --git a/components/form-data/form-data-table-columns.tsx b/components/form-data/form-data-table-columns.tsx
index 930e113b..2a065d1b 100644
--- a/components/form-data/form-data-table-columns.tsx
+++ b/components/form-data/form-data-table-columns.tsx
@@ -103,53 +103,59 @@ function getHeaderText(col: DataTableColumnJSON): string {
 }
 
 /**
- * 컬럼들을 head 값에 따라 그룹핑하는 헬퍼 함수
+ * 컬럼들을 seq 순서대로 배치하면서 연속된 같은 head를 가진 컬럼들을 그룹으로 묶는 함수
  */
 function groupColumnsByHead(columns: DataTableColumnJSON[]): ColumnDef<any>[] {
-  const groupedColumns: ColumnDef<any>[] = [];
-  const groupMap = new Map<string, DataTableColumnJSON[]>();
-  const ungroupedColumns: DataTableColumnJSON[] = [];
+  const result: ColumnDef<any>[] = [];
+  let i = 0;
 
-  // 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);
+  while (i < columns.length) {
+    const currentCol = columns[i];
+    
+    // head가 없거나 빈 문자열인 경우 일반 컬럼으로 처리
+    if (!currentCol.head || !currentCol.head.trim()) {
+      result.push(createColumnDef(currentCol, false));
+      i++;
+      continue;
+    }
+
+    // 같은 head를 가진 연속된 컬럼들을 찾기
+    const groupHead = currentCol.head.trim();
+    const groupColumns: DataTableColumnJSON[] = [currentCol];
+    let j = i + 1;
+
+    while (j < columns.length && columns[j].head && columns[j].head.trim() === groupHead) {
+      groupColumns.push(columns[j]);
+      j++;
     }
-  });
 
-  // 그룹핑된 컬럼들 처리
-  groupMap.forEach((groupColumns, groupHeader) => {
+    // 그룹에 컬럼이 하나만 있으면 일반 컬럼으로 처리
     if (groupColumns.length === 1) {
-      // 그룹에 컬럼이 하나만 있으면 일반 컬럼으로 처리
-      ungroupedColumns.push(groupColumns[0]);
+      result.push(createColumnDef(currentCol, false));
     } else {
-      // 그룹 컬럼 생성
+      // 그룹 컬럼 생성 (구분선 스타일 적용)
       const groupColumn: ColumnDef<any> = {
-        header: groupHeader,
-        columns: groupColumns.map(col => createColumnDef(col))
+        id: `group-${groupHead.replace(/\s+/g, '-')}`,
+        header: groupHead,
+        columns: groupColumns.map(col => createColumnDef(col, true)),
+        meta: {
+          isGroupColumn: true,
+          groupBorders: true, // 그룹 구분선 표시 플래그
+        }
       };
-      groupedColumns.push(groupColumn);
+      result.push(groupColumn);
     }
-  });
 
-  // 그룹핑되지 않은 컬럼들 처리
-  ungroupedColumns.forEach(col => {
-    groupedColumns.push(createColumnDef(col));
-  });
+    i = j; // 다음 그룹으로 이동
+  }
 
-  return groupedColumns;
+  return result;
 }
 
 /**
  * 개별 컬럼 정의를 생성하는 헬퍼 함수
  */
-function createColumnDef(col: DataTableColumnJSON): ColumnDef<any> {
+function createColumnDef(col: DataTableColumnJSON, isInGroup: boolean = false): ColumnDef<any> {
   return {
     accessorKey: col.key,
     header: ({ column }) => (
@@ -165,6 +171,8 @@ function createColumnDef(col: DataTableColumnJSON): ColumnDef<any> {
       paddingFactor: 1.2,
       maxWidth: col.key === "TAG_NO" ? 120 : 150,
       isReadOnly: col.shi === true,
+      isInGroup, // 그룹 내 컬럼인지 표시
+      groupBorders: isInGroup, // 그룹 구분선 표시 플래그
     },
     
     cell: ({ row }) => {
@@ -173,10 +181,19 @@ function createColumnDef(col: DataTableColumnJSON): ColumnDef<any> {
       // SHI 필드만 읽기 전용으로 처리
       const isReadOnly = col.shi === true;
       
+      // 그룹 구분선 스타일 클래스 추가
+      const groupBorderClass = isInGroup ? "group-column-border" : "";
       const readOnlyClass = isReadOnly ? "read-only-cell" : "";
-      const cellStyle = isReadOnly 
-        ? { backgroundColor: '#f5f5f5', color: '#666', cursor: 'not-allowed' } 
-        : {};
+      const combinedClass = [groupBorderClass, readOnlyClass].filter(Boolean).join(" ");
+      
+      const cellStyle = {
+        ...(isReadOnly && { backgroundColor: '#f5f5f5', color: '#666', cursor: 'not-allowed' }),
+        ...(isInGroup && { 
+          borderLeft: '2px solid #e2e8f0',
+          borderRight: '2px solid #e2e8f0',
+          position: 'relative' as const
+        })
+      };
 
       // 툴팁 메시지 설정 (SHI 필드만)
       const tooltipMessage = isReadOnly ? "SHI 전용 필드입니다" : "";
@@ -188,7 +205,7 @@ function createColumnDef(col: DataTableColumnJSON): ColumnDef<any> {
         
         return (
           <div 
-            className={readOnlyClass} 
+            className={combinedClass}
             style={cellStyle}
             title={tooltipMessage}
           >
@@ -204,7 +221,7 @@ function createColumnDef(col: DataTableColumnJSON): ColumnDef<any> {
         case "NUMBER":
           return (
             <div 
-              className={readOnlyClass} 
+              className={combinedClass}
               style={cellStyle} 
               title={tooltipMessage}
             >
@@ -215,7 +232,7 @@ function createColumnDef(col: DataTableColumnJSON): ColumnDef<any> {
         case "LIST":
           return (
             <div 
-              className={readOnlyClass} 
+              className={combinedClass}
               style={cellStyle}
               title={tooltipMessage}
             >
@@ -227,7 +244,7 @@ function createColumnDef(col: DataTableColumnJSON): ColumnDef<any> {
         default:
           return (
             <div 
-              className={readOnlyClass} 
+              className={combinedClass}
               style={cellStyle}
               title={tooltipMessage}
             >
@@ -243,7 +260,7 @@ function createColumnDef(col: DataTableColumnJSON): ColumnDef<any> {
  * getColumns 함수
  * 1) columnsJSON 배열을 필터링 (hidden이 true가 아닌 것들만)
  * 2) seq에 따라 정렬
- * 3) head 값에 따라 컬럼 그룹핑
+ * 3) seq 순서를 유지하면서 연속된 같은 head를 가진 컬럼들을 그룹으로 묶기
  * 4) 체크박스 컬럼 추가
  * 5) 마지막에 "Action" 칼럼 추가
  */
@@ -318,7 +335,7 @@ export function getColumns<TData extends object>({
   };
   columns.push(selectColumn);
 
-  // (2) 기본 컬럼들 (head에 따라 그룹핑 처리)
+  // (2) 기본 컬럼들 (seq 순서를 유지하면서 head에 따라 그룹핑 처리)
   const groupedColumns = groupColumnsByHead(visibleColumns);
   columns.push(...groupedColumns);
   
-- 
cgit v1.2.3

