From d69feef9da2a6c18ba7933c1a06446d83f9acb6e Mon Sep 17 00:00:00 2001 From: leeheejin Date: Thu, 25 Sep 2025 18:54:12 +0900 Subject: [PATCH] =?UTF-8?q?=ED=99=94=EB=A9=B4=EA=B4=80=EB=A6=AC=EC=9D=98?= =?UTF-8?q?=20=ED=85=8C=EC=9D=B4=EB=B8=94=20=EB=A6=AC=EC=8A=A4=ED=8A=B8,?= =?UTF-8?q?=20=EC=B9=B4=EB=93=9C=20=EB=94=94=EC=8A=A4=ED=94=8C=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../table-list/CardModeRenderer.tsx | 224 ++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 frontend/lib/registry/components/table-list/CardModeRenderer.tsx diff --git a/frontend/lib/registry/components/table-list/CardModeRenderer.tsx b/frontend/lib/registry/components/table-list/CardModeRenderer.tsx new file mode 100644 index 00000000..2988f864 --- /dev/null +++ b/frontend/lib/registry/components/table-list/CardModeRenderer.tsx @@ -0,0 +1,224 @@ +"use client"; + +import React from "react"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { Eye, Edit, Trash2, MoreHorizontal } from "lucide-react"; +import { CardDisplayConfig, ColumnConfig } from "./types"; + +interface CardModeRendererProps { + data: Record[]; + cardConfig: CardDisplayConfig; + visibleColumns: ColumnConfig[]; + onRowClick?: (row: Record) => void; + onRowSelect?: (row: Record, selected: boolean) => void; + selectedRows?: string[]; + showActions?: boolean; +} + +/** + * 카드 모드 렌더러 + * 테이블 데이터를 카드 형태로 표시 + */ +export const CardModeRenderer: React.FC = ({ + data, + cardConfig, + visibleColumns, + onRowClick, + onRowSelect, + selectedRows = [], + showActions = true, +}) => { + // 기본값 설정 + const config = { + cardsPerRow: 3, + cardSpacing: 16, + showActions: true, + cardHeight: "auto", + ...cardConfig, + }; + + // 카드 그리드 스타일 계산 + const gridStyle: React.CSSProperties = { + display: "grid", + gridTemplateColumns: `repeat(${config.cardsPerRow}, 1fr)`, + gap: `${config.cardSpacing}px`, + padding: `${config.cardSpacing}px`, + }; + + // 카드 높이 스타일 + const cardStyle: React.CSSProperties = { + height: config.cardHeight === "auto" ? "auto" : `${config.cardHeight}px`, + cursor: onRowClick ? "pointer" : "default", + }; + + // 컬럼 값 가져오기 함수 + const getColumnValue = (row: Record, columnName?: string): string => { + if (!columnName || !row) return ""; + return String(row[columnName] || ""); + }; + + // 액션 버튼 렌더링 + const renderActions = (row: Record) => { + if (!showActions || !config.showActions) return null; + + return ( +
+ + + + +
+ ); + }; + + // 데이터가 없는 경우 + if (!data || data.length === 0) { + return ( +
+
+
+
+
표시할 데이터가 없습니다
+
조건을 변경하거나 새로운 데이터를 추가해보세요
+
+ ); + } + + return ( +
+ {data.map((row, index) => { + const idValue = getColumnValue(row, config.idColumn); + const titleValue = getColumnValue(row, config.titleColumn); + const subtitleValue = getColumnValue(row, config.subtitleColumn); + const descriptionValue = getColumnValue(row, config.descriptionColumn); + const imageValue = getColumnValue(row, config.imageColumn); + + const isSelected = selectedRows.includes(idValue); + + return ( + onRowClick?.(row)} + > + +
+
+ + {titleValue || "제목 없음"} + + {subtitleValue && ( +
+ {subtitleValue} +
+ )} +
+ + {/* ID 뱃지 */} + {idValue && ( + + {idValue} + + )} +
+
+ + + {/* 이미지 표시 */} + {imageValue && ( +
+ {titleValue} { + const target = e.target as HTMLImageElement; + target.style.display = "none"; + }} + /> +
+ )} + + {/* 설명 표시 */} + {descriptionValue && ( +
+ {descriptionValue} +
+ )} + + {/* 추가 필드들 표시 (선택적) */} +
+ {visibleColumns + .filter(col => + col.columnName !== config.idColumn && + col.columnName !== config.titleColumn && + col.columnName !== config.subtitleColumn && + col.columnName !== config.descriptionColumn && + col.columnName !== config.imageColumn && + col.columnName !== "__checkbox__" && + col.visible + ) + .slice(0, 3) // 최대 3개 추가 필드만 표시 + .map((col) => { + const value = getColumnValue(row, col.columnName); + if (!value) return null; + + return ( +
+ {col.displayName}: + {value} +
+ ); + })} +
+ + {/* 액션 버튼들 */} + {renderActions(row)} +
+
+ ); + })} +
+ ); +};