"use client"; import { AutoRegisteringLayoutRenderer } from "../AutoRegisteringLayoutRenderer"; import { CardLayoutDefinition } from "./index"; import { CardLayoutLayout } from "./CardLayoutLayout"; import React, { useState, useEffect } from "react"; import { tableTypeApi } from "@/lib/api/screen"; /** * 카드 레이아웃 렌더러 컴포넌트 */ const CardLayoutRendererComponent: React.FC = (props) => { const { layout, children, onUpdateLayout, onSelectComponent, isDesignMode } = props; const [tableData, setTableData] = useState([]); const [tableColumns, setTableColumns] = useState([]); const [loading, setLoading] = useState(false); // 테이블 데이터 로딩 useEffect(() => { const loadTableData = async () => { // 디자인 모드에서는 테이블 데이터를 로드하지 않음 if (isDesignMode) { return; } // 카드 설정에서 테이블명 확인 (여러 소스에서 시도) const tableName = layout?.tableName || layout?.screenTableName || props?.tableName || props?.selectedScreen?.tableName || "company_mng"; // 임시 하드코딩 (테스트용) if (!tableName) { console.log("📋 카드 레이아웃: 테이블명이 설정되지 않음", { layoutTableName: layout?.tableName, screenTableName: layout?.screenTableName, propsTableName: props?.tableName, selectedScreenTableName: props?.selectedScreen?.tableName, }); return; } try { setLoading(true); console.log(`📋 카드 레이아웃: ${tableName} 테이블 데이터 로딩 시작`); // 테이블 데이터와 컬럼 정보를 병렬로 로드 const [dataResponse, columnsResponse] = await Promise.all([ tableTypeApi.getTableData(tableName, { page: 1, size: 50, // 카드 레이아웃용으로 적당한 개수 }), tableTypeApi.getColumns(tableName), ]); console.log(`📋 카드 레이아웃: ${tableName} 데이터 로딩 완료`, { total: dataResponse.total, dataLength: dataResponse.data.length, columnsLength: columnsResponse.length, sampleData: dataResponse.data.slice(0, 2), sampleColumns: columnsResponse.slice(0, 3), }); setTableData(dataResponse.data); setTableColumns(columnsResponse); } catch (error) { console.error(`❌ 카드 레이아웃: ${tableName} 데이터 로딩 실패`, error); setTableData([]); } finally { setLoading(false); } }; loadTableData(); }, [layout?.tableName, isDesignMode]); return ( ); }; /** * 카드 레이아웃 렌더러 * AutoRegisteringLayoutRenderer를 상속받아 자동 등록 기능 제공 */ export class CardLayoutRenderer extends AutoRegisteringLayoutRenderer { /** * 레이아웃 정의 (자동 등록용) */ static layoutDefinition = CardLayoutDefinition; /** * 카드 레이아웃 렌더링 */ render(): React.ReactElement { return ; } /** * 카드 컨테이너 스타일 계산 */ getCardContainerStyle(): React.CSSProperties { const cardConfig = this.props.layout.layoutConfig?.cardLayout || { columns: 3, gap: 16, }; return { display: "grid", gridTemplateColumns: `repeat(${cardConfig.columns}, 1fr)`, gridTemplateRows: "repeat(2, 300px)", gap: `${cardConfig.gap}px`, padding: "16px", width: "100%", height: "100%", }; } /** * 개별 카드 스타일 계산 */ getCardStyle(zoneId: string): React.CSSProperties { const baseStyle: React.CSSProperties = { backgroundColor: "white", border: "1px solid #e5e7eb", borderRadius: "8px", padding: "16px", boxShadow: "0 1px 3px 0 rgba(0, 0, 0, 0.1)", transition: "all 0.2s ease-in-out", overflow: "hidden", display: "flex", flexDirection: "column", position: "relative", minHeight: "200px", }; // 디자인 모드에서 추가 스타일 if (this.props.isDesignMode) { return { ...baseStyle, cursor: "pointer", borderColor: "#d1d5db", }; } return baseStyle; } /** * 카드 호버 효과 계산 */ getCardHoverStyle(): React.CSSProperties { return { borderColor: "#3b82f6", boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.1)", transform: "translateY(-1px)", }; } /** * 그리드 위치 계산 */ getGridPosition(index: number): { row: number; column: number } { const columns = this.props.layout.layoutConfig?.cardLayout?.columns || 3; return { row: Math.floor(index / columns), column: index % columns, }; } } // 자동 등록 실행 CardLayoutRenderer.registerSelf();