"use client"; import React, { useState, useEffect } from "react"; import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { Switch } from "@/components/ui/switch"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from "@/components/ui/command"; import { Plus, Trash2, GripVertical, Loader2, Check, ChevronsUpDown, Database } from "lucide-react"; import { ConditionalContainerConfig, ConditionalSection } from "./types"; import { screenApi } from "@/lib/api/screen"; import { cn } from "@/lib/utils"; import { getCategoryColumnsByMenu, getCategoryValues, getSecondLevelMenus } from "@/lib/api/tableCategoryValue"; interface ConditionalContainerConfigPanelProps { config: ConditionalContainerConfig; onChange?: (config: ConditionalContainerConfig) => void; onConfigChange?: (config: ConditionalContainerConfig) => void; } export function ConditionalContainerConfigPanel({ config, onChange, onConfigChange, }: ConditionalContainerConfigPanelProps) { // onChange 또는 onConfigChange 둘 다 지원 const handleConfigChange = onChange || onConfigChange; const [localConfig, setLocalConfig] = useState({ controlField: config.controlField || "condition", controlLabel: config.controlLabel || "조건 선택", sections: config.sections || [], defaultValue: config.defaultValue || "", showBorder: config.showBorder ?? true, spacing: config.spacing || "normal", }); // 화면 목록 상태 const [screens, setScreens] = useState([]); const [screensLoading, setScreensLoading] = useState(false); // 🆕 메뉴 기반 카테고리 관련 상태 const [availableMenus, setAvailableMenus] = useState>([]); const [menusLoading, setMenusLoading] = useState(false); const [selectedMenuObjid, setSelectedMenuObjid] = useState(null); const [menuPopoverOpen, setMenuPopoverOpen] = useState(false); const [categoryColumns, setCategoryColumns] = useState>([]); const [categoryColumnsLoading, setCategoryColumnsLoading] = useState(false); const [selectedCategoryColumn, setSelectedCategoryColumn] = useState(""); const [selectedCategoryTableName, setSelectedCategoryTableName] = useState(""); const [columnPopoverOpen, setColumnPopoverOpen] = useState(false); const [categoryValues, setCategoryValues] = useState>([]); const [categoryValuesLoading, setCategoryValuesLoading] = useState(false); // 화면 목록 로드 useEffect(() => { const loadScreens = async () => { setScreensLoading(true); try { const response = await screenApi.getScreens({ page: 1, size: 1000 }); if (response.data) { setScreens(response.data); } } catch (error) { console.error("화면 목록 로드 실패:", error); } finally { setScreensLoading(false); } }; loadScreens(); }, []); // 🆕 2레벨 메뉴 목록 로드 useEffect(() => { const loadMenus = async () => { setMenusLoading(true); try { const response = await getSecondLevelMenus(); console.log("🔍 [ConditionalContainer] 메뉴 목록 응답:", response); if (response.success && response.data) { setAvailableMenus(response.data); } } catch (error) { console.error("메뉴 목록 로드 실패:", error); } finally { setMenusLoading(false); } }; loadMenus(); }, []); // 🆕 선택된 메뉴의 카테고리 컬럼 목록 로드 useEffect(() => { if (!selectedMenuObjid) { setCategoryColumns([]); setSelectedCategoryColumn(""); setSelectedCategoryTableName(""); setCategoryValues([]); return; } const loadCategoryColumns = async () => { setCategoryColumnsLoading(true); try { console.log("🔍 [ConditionalContainer] 메뉴별 카테고리 컬럼 로드:", selectedMenuObjid); const response = await getCategoryColumnsByMenu(selectedMenuObjid); console.log("✅ [ConditionalContainer] 카테고리 컬럼 응답:", response); if (response.success && response.data) { setCategoryColumns(response.data.map((col: any) => ({ columnName: col.columnName || col.column_name, columnLabel: col.columnLabel || col.column_label || col.columnName || col.column_name, tableName: col.tableName || col.table_name, }))); } else { setCategoryColumns([]); } } catch (error) { console.error("카테고리 컬럼 로드 실패:", error); setCategoryColumns([]); } finally { setCategoryColumnsLoading(false); } }; loadCategoryColumns(); }, [selectedMenuObjid]); // 🆕 선택된 카테고리 컬럼의 값 목록 로드 useEffect(() => { if (!selectedCategoryTableName || !selectedCategoryColumn || !selectedMenuObjid) { setCategoryValues([]); return; } const loadCategoryValues = async () => { setCategoryValuesLoading(true); try { console.log("🔍 [ConditionalContainer] 카테고리 값 로드:", selectedCategoryTableName, selectedCategoryColumn, selectedMenuObjid); const response = await getCategoryValues(selectedCategoryTableName, selectedCategoryColumn, false, selectedMenuObjid); console.log("✅ [ConditionalContainer] 카테고리 값 응답:", response); if (response.success && response.data) { const values = response.data.map((v: any) => ({ value: v.valueCode || v.value_code, label: v.valueLabel || v.value_label || v.valueCode || v.value_code, })); setCategoryValues(values); } else { setCategoryValues([]); } } catch (error) { console.error("카테고리 값 로드 실패:", error); setCategoryValues([]); } finally { setCategoryValuesLoading(false); } }; loadCategoryValues(); }, [selectedCategoryTableName, selectedCategoryColumn, selectedMenuObjid]); // 🆕 테이블 카테고리에서 섹션 자동 생성 const generateSectionsFromCategory = () => { if (categoryValues.length === 0) { alert("먼저 테이블과 카테고리 컬럼을 선택하고 값을 로드해주세요."); return; } const newSections: ConditionalSection[] = categoryValues.map((option, index) => ({ id: `section_${Date.now()}_${index}`, condition: option.value, label: option.label, screenId: null, screenName: undefined, })); updateConfig({ sections: newSections, controlField: selectedCategoryColumn, // 카테고리 컬럼명을 제어 필드로 사용 }); alert(`${newSections.length}개의 섹션이 생성되었습니다.`); }; // 설정 업데이트 헬퍼 const updateConfig = (updates: Partial) => { const newConfig = { ...localConfig, ...updates }; setLocalConfig(newConfig); handleConfigChange?.(newConfig); }; // 새 섹션 추가 const addSection = () => { const newSection: ConditionalSection = { id: `section_${Date.now()}`, condition: `condition_${localConfig.sections.length + 1}`, label: `조건 ${localConfig.sections.length + 1}`, screenId: null, screenName: undefined, }; updateConfig({ sections: [...localConfig.sections, newSection], }); }; // 섹션 삭제 const removeSection = (sectionId: string) => { updateConfig({ sections: localConfig.sections.filter((s) => s.id !== sectionId), }); }; // 섹션 업데이트 const updateSection = ( sectionId: string, updates: Partial ) => { updateConfig({ sections: localConfig.sections.map((s) => s.id === sectionId ? { ...s, ...updates } : s ), }); }; return (

조건부 컨테이너 설정

{/* 제어 필드 설정 */}
updateConfig({ controlField: e.target.value })} placeholder="예: inputMode" className="h-8 text-xs" />

formData에 저장될 필드명

updateConfig({ controlLabel: e.target.value })} placeholder="예: 입력 방식" className="h-8 text-xs" />
{/* 🆕 메뉴별 카테고리에서 섹션 자동 생성 */}
{/* 1. 메뉴 선택 */}
메뉴를 찾을 수 없습니다 {availableMenus.map((menu) => ( { setSelectedMenuObjid(menu.menuObjid); setSelectedCategoryColumn(""); setSelectedCategoryTableName(""); setMenuPopoverOpen(false); }} className="text-xs" >
{menu.parentMenuName} > {menu.menuName} {menu.screenCode && ( {menu.screenCode} )}
))}
{/* 2. 카테고리 컬럼 선택 */} {selectedMenuObjid && (
{categoryColumnsLoading ? (
로딩 중...
) : categoryColumns.length > 0 ? ( 카테고리 컬럼이 없습니다 {categoryColumns.map((col) => ( { setSelectedCategoryColumn(col.columnName); setSelectedCategoryTableName(col.tableName); setColumnPopoverOpen(false); }} className="text-xs" >
{col.columnLabel} {col.tableName}.{col.columnName}
))}
) : (

이 메뉴에 설정된 카테고리 컬럼이 없습니다. 카테고리 관리에서 먼저 설정해주세요.

)}
)} {/* 3. 카테고리 값 미리보기 */} {selectedCategoryColumn && (
{categoryValuesLoading ? (
로딩 중...
) : categoryValues.length > 0 ? (
{categoryValues.map((option) => ( {option.label} ))}
) : (

이 컬럼에 등록된 카테고리 값이 없습니다. 카테고리 관리에서 값을 먼저 등록해주세요.

)}
)}

선택한 메뉴의 카테고리 값들로 조건별 섹션을 자동으로 생성합니다. 각 섹션에 표시할 화면은 아래에서 개별 설정하세요.

{/* 조건별 섹션 설정 */}
{localConfig.sections.length === 0 ? (

조건별 섹션을 추가하세요

) : (
{localConfig.sections.map((section, index) => (
{/* 섹션 헤더 */}
섹션 {index + 1}
{/* 조건 값 */}
updateSection(section.id, { condition: e.target.value }) } placeholder="예: customer_first" className="h-7 text-xs" />
{/* 조건 라벨 */}
updateSection(section.id, { label: e.target.value }) } placeholder="예: 거래처 우선" className="h-7 text-xs" />
{/* 화면 선택 */}
{screensLoading ? (
로딩 중...
) : ( )} {section.screenId && (
화면 ID: {section.screenId}
)}
))}
)}
{/* 기본값 설정 */} {localConfig.sections.length > 0 && (
)} {/* 스타일 설정 */}
{/* 테두리 표시 */}
updateConfig({ showBorder: checked }) } />
{/* 간격 설정 */}
); }