"use client"; import React, { useState, useEffect } from "react"; import { entityJoinApi } from "@/lib/api/entityJoin"; import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { Checkbox } from "@/components/ui/checkbox"; import { Trash2 } from "lucide-react"; interface CardDisplayConfigPanelProps { config: any; onChange: (config: any) => void; screenTableName?: string; tableColumns?: any[]; } interface EntityJoinColumn { tableName: string; columnName: string; columnLabel: string; dataType: string; joinAlias: string; suggestedLabel: string; } interface JoinTable { tableName: string; currentDisplayColumn: string; joinConfig?: { sourceColumn: string; }; availableColumns: Array<{ columnName: string; columnLabel: string; dataType: string; description?: string; }>; } /** * CardDisplay 설정 패널 * 카드 레이아웃과 동일한 설정 UI 제공 + 엔티티 조인 컬럼 지원 */ export const CardDisplayConfigPanel: React.FC = ({ config, onChange, screenTableName, tableColumns = [], }) => { // 엔티티 조인 컬럼 상태 const [entityJoinColumns, setEntityJoinColumns] = useState<{ availableColumns: EntityJoinColumn[]; joinTables: JoinTable[]; }>({ availableColumns: [], joinTables: [] }); const [loadingEntityJoins, setLoadingEntityJoins] = useState(false); // 엔티티 조인 컬럼 정보 가져오기 useEffect(() => { const fetchEntityJoinColumns = async () => { const tableName = config.tableName || screenTableName; if (!tableName) { setEntityJoinColumns({ availableColumns: [], joinTables: [] }); return; } setLoadingEntityJoins(true); try { const result = await entityJoinApi.getEntityJoinColumns(tableName); setEntityJoinColumns({ availableColumns: result.availableColumns || [], joinTables: result.joinTables || [], }); } catch (error) { console.error("Entity 조인 컬럼 조회 오류:", error); setEntityJoinColumns({ availableColumns: [], joinTables: [] }); } finally { setLoadingEntityJoins(false); } }; fetchEntityJoinColumns(); }, [config.tableName, screenTableName]); const handleChange = (key: string, value: any) => { onChange({ ...config, [key]: value }); }; const handleNestedChange = (path: string, value: any) => { const keys = path.split("."); let newConfig = { ...config }; let current = newConfig; for (let i = 0; i < keys.length - 1; i++) { if (!current[keys[i]]) { current[keys[i]] = {}; } current = current[keys[i]]; } current[keys[keys.length - 1]] = value; onChange(newConfig); }; // 컬럼 선택 시 조인 컬럼이면 joinColumns 설정도 함께 업데이트 const handleColumnSelect = (path: string, columnName: string) => { const joinColumn = entityJoinColumns.availableColumns.find( (col) => col.joinAlias === columnName ); if (joinColumn) { const joinColumnsConfig = config.joinColumns || []; const existingJoinColumn = joinColumnsConfig.find( (jc: any) => jc.columnName === columnName ); if (!existingJoinColumn) { const joinTableInfo = entityJoinColumns.joinTables?.find( (jt) => jt.tableName === joinColumn.tableName ); const newJoinColumnConfig = { columnName: joinColumn.joinAlias, label: joinColumn.suggestedLabel || joinColumn.columnLabel, sourceColumn: joinTableInfo?.joinConfig?.sourceColumn || "", referenceTable: joinColumn.tableName, referenceColumn: joinColumn.columnName, isJoinColumn: true, }; onChange({ ...config, columnMapping: { ...config.columnMapping, [path.split(".")[1]]: columnName, }, joinColumns: [...joinColumnsConfig, newJoinColumnConfig], }); return; } } handleNestedChange(path, columnName); }; // 표시 컬럼 추가 const addDisplayColumn = () => { const currentColumns = config.columnMapping?.displayColumns || []; const newColumns = [...currentColumns, ""]; handleNestedChange("columnMapping.displayColumns", newColumns); }; // 표시 컬럼 삭제 const removeDisplayColumn = (index: number) => { const currentColumns = [...(config.columnMapping?.displayColumns || [])]; currentColumns.splice(index, 1); handleNestedChange("columnMapping.displayColumns", currentColumns); }; // 표시 컬럼 값 변경 const updateDisplayColumn = (index: number, value: string) => { const currentColumns = [...(config.columnMapping?.displayColumns || [])]; currentColumns[index] = value; const joinColumn = entityJoinColumns.availableColumns.find( (col) => col.joinAlias === value ); if (joinColumn) { const joinColumnsConfig = config.joinColumns || []; const existingJoinColumn = joinColumnsConfig.find( (jc: any) => jc.columnName === value ); if (!existingJoinColumn) { const joinTableInfo = entityJoinColumns.joinTables?.find( (jt) => jt.tableName === joinColumn.tableName ); const newJoinColumnConfig = { columnName: joinColumn.joinAlias, label: joinColumn.suggestedLabel || joinColumn.columnLabel, sourceColumn: joinTableInfo?.joinConfig?.sourceColumn || "", referenceTable: joinColumn.tableName, referenceColumn: joinColumn.columnName, isJoinColumn: true, }; onChange({ ...config, columnMapping: { ...config.columnMapping, displayColumns: currentColumns, }, joinColumns: [...joinColumnsConfig, newJoinColumnConfig], }); return; } } handleNestedChange("columnMapping.displayColumns", currentColumns); }; // 테이블별로 조인 컬럼 그룹화 const joinColumnsByTable: Record = {}; entityJoinColumns.availableColumns.forEach((col) => { if (!joinColumnsByTable[col.tableName]) { joinColumnsByTable[col.tableName] = []; } joinColumnsByTable[col.tableName].push(col); }); // 컬럼 선택 셀렉트 박스 렌더링 (Shadcn UI) const renderColumnSelect = ( value: string, onChangeHandler: (value: string) => void, placeholder: string = "컬럼을 선택하세요" ) => { return ( ); }; return (
카드 디스플레이 설정
{/* 테이블이 선택된 경우 컬럼 매핑 설정 */} {tableColumns && tableColumns.length > 0 && (
컬럼 매핑
{loadingEntityJoins && (
조인 컬럼 로딩 중...
)}
{renderColumnSelect( config.columnMapping?.titleColumn || "", (value) => handleColumnSelect("columnMapping.titleColumn", value) )}
{renderColumnSelect( config.columnMapping?.subtitleColumn || "", (value) => handleColumnSelect("columnMapping.subtitleColumn", value) )}
{renderColumnSelect( config.columnMapping?.descriptionColumn || "", (value) => handleColumnSelect("columnMapping.descriptionColumn", value) )}
{renderColumnSelect( config.columnMapping?.imageColumn || "", (value) => handleColumnSelect("columnMapping.imageColumn", value) )}
{/* 동적 표시 컬럼 추가 */}
{(config.columnMapping?.displayColumns || []).map((column: string, index: number) => (
{renderColumnSelect( column, (value) => updateDisplayColumn(index, value) )}
))} {(!config.columnMapping?.displayColumns || config.columnMapping.displayColumns.length === 0) && (
"컬럼 추가" 버튼을 클릭하여 표시할 컬럼을 추가하세요
)}
)} {/* 카드 스타일 설정 */}
카드 스타일
handleChange("cardsPerRow", parseInt(e.target.value))} className="h-8 text-xs" />
handleChange("cardSpacing", parseInt(e.target.value))} className="h-8 text-xs" />
handleNestedChange("cardStyle.showTitle", checked)} />
handleNestedChange("cardStyle.showSubtitle", checked)} />
handleNestedChange("cardStyle.showDescription", checked)} />
handleNestedChange("cardStyle.showImage", checked)} />
handleNestedChange("cardStyle.showActions", checked)} />
{/* 개별 버튼 설정 */} {(config.cardStyle?.showActions ?? true) && (
handleNestedChange("cardStyle.showViewButton", checked)} />
handleNestedChange("cardStyle.showEditButton", checked)} />
handleNestedChange("cardStyle.showDeleteButton", checked)} />
)}
handleNestedChange("cardStyle.maxDescriptionLength", parseInt(e.target.value))} className="h-8 text-xs" />
{/* 공통 설정 */}
공통 설정
handleChange("disabled", checked)} />
handleChange("readonly", checked)} />
); };