"use client"; import React from "react"; import { Table, Filter, Search, Download, RefreshCw, Plus, Edit, Trash2 } from "lucide-react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Checkbox } from "@/components/ui/checkbox"; /** * 데이터 테이블 템플릿 컴포넌트 * 기존 하드코딩된 데이터 테이블 기능을 독립적인 컴포넌트로 분리 */ export interface DataTableTemplateProps { /** * 테이블 제목 */ title?: string; /** * 테이블 설명 */ description?: string; /** * 컬럼 정의 */ columns?: Array<{ id: string; label: string; type: string; visible: boolean; sortable: boolean; filterable: boolean; width?: number; }>; /** * 필터 설정 */ filters?: Array<{ id: string; label: string; type: "text" | "select" | "date" | "number"; options?: Array<{ label: string; value: string }>; }>; /** * 페이징 설정 */ pagination?: { enabled: boolean; pageSize: number; pageSizeOptions: number[]; showPageSizeSelector: boolean; showPageInfo: boolean; showFirstLast: boolean; }; /** * 액션 버튼 설정 */ actions?: { showSearchButton: boolean; searchButtonText: string; enableExport: boolean; enableRefresh: boolean; enableAdd: boolean; enableEdit: boolean; enableDelete: boolean; addButtonText: string; editButtonText: string; deleteButtonText: string; }; /** * 스타일 설정 */ style?: React.CSSProperties; /** * 클래스명 */ className?: string; /** * 미리보기 모드 (실제 데이터 없이 구조만 표시) */ isPreview?: boolean; } export const DataTableTemplate: React.FC = ({ title = "데이터 테이블", description = "데이터를 표시하고 관리하는 테이블", columns = [], filters = [], pagination = { enabled: true, pageSize: 10, pageSizeOptions: [5, 10, 20, 50], showPageSizeSelector: true, showPageInfo: true, showFirstLast: true, }, actions = { showSearchButton: true, searchButtonText: "검색", enableExport: true, enableRefresh: true, enableAdd: true, enableEdit: true, enableDelete: true, addButtonText: "추가", editButtonText: "수정", deleteButtonText: "삭제", }, style, className = "", isPreview = true, }) => { // 설정된 컬럼만 사용 (자동 생성 안함) const defaultColumns = React.useMemo(() => { return columns || []; }, [columns]); // 미리보기용 샘플 데이터 const sampleData = React.useMemo(() => { if (!isPreview) return []; return [ { id: 1, name: "홍길동", email: "hong@example.com", status: "활성", created_date: "2024-01-15" }, { id: 2, name: "김철수", email: "kim@example.com", status: "비활성", created_date: "2024-01-14" }, { id: 3, name: "이영희", email: "lee@example.com", status: "활성", created_date: "2024-01-13" }, ]; }, [isPreview]); const visibleColumns = defaultColumns.filter((col) => col.visible); return ( {/* 헤더 영역 */}
{title} {description &&

{description}

} {/* 액션 버튼들 */}
{actions.enableRefresh && ( )} {actions.enableExport && ( )} {actions.enableAdd && ( )}
{/* 검색 및 필터 영역 */}
{/* 검색 입력 */}
{actions.showSearchButton && ( )}
{/* 필터 영역 */} {filters.length > 0 && (
{filters.slice(0, 3).map((filter, index) => ( ))}
)}
{/* 데이터 테이블 */}
{/* 테이블 헤더 */} {/* 선택 체크박스 */} {/* 컬럼 헤더 */} {visibleColumns.map((column) => ( ))} {/* 액션 컬럼 */} {(actions.enableEdit || actions.enableDelete) && } {/* 테이블 바디 */} {isPreview ? ( // 미리보기 데이터 sampleData.map((row, index) => ( {visibleColumns.map((column) => ( ))} {(actions.enableEdit || actions.enableDelete) && ( )} )) ) : ( // 실제 데이터가 없는 경우 플레이스홀더 )}
{column.label} {column.sortable && (
)}
액션
{column.type === "select" && column.id === "status" ? ( {row[column.id]} ) : ( {row[column.id]} )}
{actions.enableEdit && ( )} {actions.enableDelete && ( )}
데이터가 없습니다.
{/* 페이징 영역 */} {pagination.enabled && (
{pagination.showPageInfo && {isPreview ? "1-3 of 3" : "0-0 of 0"} 항목 표시}
{/* 페이지 크기 선택 */} {pagination.showPageSizeSelector && (
표시:
)} {/* 페이지 네비게이션 */}
{pagination.showFirstLast && ( )} {pagination.showFirstLast && ( )}
)}
); }; /** * 데이터 테이블 템플릿 기본 설정 */ export const getDefaultDataTableConfig = () => ({ template_code: "advanced-data-table-v2", template_name: "고급 데이터 테이블 v2", template_name_eng: "Advanced Data Table v2", description: "검색, 필터링, 페이징, CRUD 기능이 포함된 완전한 데이터 테이블 컴포넌트", category: "table", icon_name: "table", default_size: { width: 1000, height: 680, }, layout_config: { components: [ { type: "datatable", label: "고급 데이터 테이블", position: { x: 0, y: 0 }, size: { width: 1000, height: 680 }, style: { border: "1px solid #e5e7eb", borderRadius: "8px", backgroundColor: "#ffffff", padding: "0", }, // 데이터 테이블 전용 설정 columns: [ { id: "id", label: "ID", type: "number", visible: true, sortable: true, filterable: false, width: 80 }, { id: "name", label: "이름", type: "text", visible: true, sortable: true, filterable: true, width: 150 }, { id: "email", label: "이메일", type: "email", visible: true, sortable: true, filterable: true, width: 200 }, { id: "status", label: "상태", type: "select", visible: true, sortable: true, filterable: true, width: 100 }, { id: "created_date", label: "생성일", type: "date", visible: true, sortable: true, filterable: true, width: 120, }, ], filters: [ { id: "status", label: "상태", type: "select", options: [ { label: "전체", value: "" }, { label: "활성", value: "active" }, { label: "비활성", value: "inactive" }, ], }, { id: "name", label: "이름", type: "text" }, { id: "email", label: "이메일", type: "text" }, ], pagination: { enabled: true, pageSize: 10, pageSizeOptions: [5, 10, 20, 50, 100], showPageSizeSelector: true, showPageInfo: true, showFirstLast: true, }, actions: { showSearchButton: true, searchButtonText: "검색", enableExport: true, enableRefresh: true, enableAdd: true, enableEdit: true, enableDelete: true, addButtonText: "추가", editButtonText: "수정", deleteButtonText: "삭제", }, // 모달 설정 addModalConfig: { title: "새 데이터 추가", description: "테이블에 새로운 데이터를 추가합니다.", width: "lg", layout: "two-column", gridColumns: 2, fieldOrder: ["name", "email", "status"], requiredFields: ["name", "email"], hiddenFields: ["id", "created_date"], advancedFieldConfigs: { status: { type: "select", options: [ { label: "활성", value: "active" }, { label: "비활성", value: "inactive" }, ], }, }, submitButtonText: "추가", cancelButtonText: "취소", }, }, ], }, }); export default DataTableTemplate;