"use client"; import React, { useState, useEffect } from "react"; import { MenuItem, MenuFormData, menuApi, LangKey } from "@/lib/api/menu"; import { companyAPI } from "@/lib/api/company"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { toast } from "sonner"; import { getMenuTextSync, MENU_MANAGEMENT_KEYS, setTranslationCache } from "@/lib/utils/multilang"; interface Company { company_code: string; company_name: string; status: string; } interface MenuFormModalProps { isOpen: boolean; onClose: () => void; onSuccess: () => void; menuId?: string; parentId?: string; menuType?: string; level?: number; parentCompanyCode?: string; } export const MenuFormModal: React.FC = ({ isOpen, onClose, onSuccess, menuId, parentId, menuType, level, parentCompanyCode, }) => { const [formData, setFormData] = useState({ parentObjId: parentId || "0", menuNameKor: "", menuUrl: "", menuDesc: "", seq: 1, menuType: menuType || "1", status: "active", companyCode: "", langKey: "", // 다국어 키 추가 }); const [loading, setLoading] = useState(false); const [isEdit, setIsEdit] = useState(false); const [companies, setCompanies] = useState([]); const [langKeys, setLangKeys] = useState([]); const [isLangKeyDropdownOpen, setIsLangKeyDropdownOpen] = useState(false); const [langKeySearchText, setLangKeySearchText] = useState(""); // 회사 목록 로드 useEffect(() => { if (isOpen) { loadCompanies(); } }, [isOpen]); // 다국어 키 목록 로드 useEffect(() => { if (isOpen && formData.companyCode) { loadLangKeys(); } }, [isOpen, formData.companyCode]); // 드롭다운 외부 클릭 시 닫기 useEffect(() => { const handleClickOutside = (event: MouseEvent) => { const target = event.target as Element; if (!target.closest(".langkey-dropdown")) { setIsLangKeyDropdownOpen(false); setLangKeySearchText(""); } }; if (isLangKeyDropdownOpen) { document.addEventListener("mousedown", handleClickOutside); } return () => { document.removeEventListener("mousedown", handleClickOutside); }; }, [isLangKeyDropdownOpen]); const loadCompanies = async () => { try { const companyList = await companyAPI.getList({ status: "active" }); setCompanies(companyList); } catch (error) { console.error("회사 목록 로딩 오류:", error); toast.error(getMenuTextSync(MENU_MANAGEMENT_KEYS.MESSAGE_ERROR_LOAD_COMPANY_LIST)); } }; const loadLangKeys = async () => { console.log(`🔤 다국어 키 목록 조회 시작 - companyCode:`, formData.companyCode); try { const response = await menuApi.getLangKeys({ companyCode: formData.companyCode === "none" ? "*" : formData.companyCode, }); if (response.success && response.data) { // 활성화된 다국어 키만 필터링 const activeKeys = response.data.filter((key) => key.isActive === "Y"); console.log(`🔤 다국어 키 목록 조회 성공:`, activeKeys.length, "개 (활성화된 키)"); setLangKeys(activeKeys); } } catch (error) { console.error("❌ 다국어 키 목록 로딩 오류:", error); toast.error(getMenuTextSync(MENU_MANAGEMENT_KEYS.MESSAGE_ERROR_LOAD_LANG_KEY_LIST)); setLangKeys([]); } }; useEffect(() => { console.log("MenuFormModal useEffect - menuId:", menuId, "parentId:", parentId, "menuType:", menuType); if (menuId) { console.log("메뉴 수정 모드 - menuId:", menuId); setIsEdit(true); loadMenuData(); } else { console.log("메뉴 등록 모드 - parentId:", parentId, "menuType:", menuType); setIsEdit(false); // 메뉴 타입 변환 (0 -> 0, 1 -> 1, admin -> 0, user -> 1) let defaultMenuType = "1"; // 기본값은 사용자 if (menuType === "0" || menuType === "admin") { defaultMenuType = "0"; // 관리자 } else if (menuType === "1" || menuType === "user") { defaultMenuType = "1"; // 사용자 } setFormData({ parentObjId: parentId || "0", menuNameKor: "", menuUrl: "", menuDesc: "", seq: 1, menuType: defaultMenuType, status: "ACTIVE", // 기본값은 활성화 companyCode: parentCompanyCode || "none", // 상위 메뉴의 회사 코드를 기본값으로 설정 langKey: "", // 다국어 키 초기화 }); console.log("메뉴 등록 기본값 설정:", { parentObjId: parentId || "0", menuType: defaultMenuType, status: "ACTIVE", companyCode: "", langKey: "", }); } }, [menuId, parentId, menuType]); const loadMenuData = async () => { console.log("loadMenuData 호출됨 - menuId:", menuId); if (!menuId) { console.log("menuId가 없어서 loadMenuData 종료"); return; } try { setLoading(true); console.log("API 호출 시작 - menuId:", menuId); console.log("API URL:", `/admin/menus/${menuId}`); const response = await menuApi.getMenuInfo(menuId); console.log("메뉴 정보 조회 응답:", response); console.log("응답 success:", response.success); console.log("응답 data:", response.data); console.log("응답 message:", response.message); console.log("응답 errorCode:", response.errorCode); if (response.success && response.data) { const menu = response.data; console.log("메뉴 데이터:", menu); console.log("메뉴 데이터 키들:", Object.keys(menu)); // 대문자 키와 소문자 키 모두 처리 const menuType = menu.menu_type || menu.MENU_TYPE || "1"; const status = menu.status || menu.STATUS || "active"; const companyCode = menu.company_code || menu.COMPANY_CODE || ""; const langKey = menu.lang_key || menu.LANG_KEY || ""; // 메뉴 타입 변환 (admin/user -> 0/1) let convertedMenuType = menuType; if (menuType === "admin" || menuType === "0") { convertedMenuType = "0"; } else if (menuType === "user" || menuType === "1") { convertedMenuType = "1"; } // 상태 변환 (active/inactive/inActive -> ACTIVE/INACTIVE) let convertedStatus = status; if (status === "active") { convertedStatus = "ACTIVE"; } else if (status === "inactive" || status === "inActive") { convertedStatus = "INACTIVE"; } setFormData({ objid: menu.objid || menu.OBJID, parentObjId: menu.parent_obj_id || menu.PARENT_OBJ_ID || "0", menuNameKor: menu.menu_name_kor || menu.MENU_NAME_KOR || "", menuUrl: menu.menu_url || menu.MENU_URL || "", menuDesc: menu.menu_desc || menu.MENU_DESC || "", seq: menu.seq || menu.SEQ || 1, menuType: convertedMenuType, status: convertedStatus, companyCode: companyCode, langKey: langKey, // 다국어 키 설정 }); console.log("설정된 폼 데이터:", { objid: menu.objid || menu.OBJID, parentObjId: menu.parent_obj_id || menu.PARENT_OBJ_ID || "0", menuNameKor: menu.menu_name_kor || menu.MENU_NAME_KOR || "", menuUrl: menu.menu_url || menu.MENU_URL || "", menuDesc: menu.menu_desc || menu.MENU_DESC || "", seq: menu.seq || menu.SEQ || 1, menuType: convertedMenuType, status: convertedStatus, companyCode: companyCode, langKey: langKey, }); } } catch (error: any) { console.error("메뉴 정보 로딩 오류:", error); console.error("오류 상세 정보:", { message: error?.message, stack: error?.stack, response: error?.response, }); toast.error(getMenuTextSync(MENU_MANAGEMENT_KEYS.MESSAGE_ERROR_LOAD_MENU_INFO)); } finally { setLoading(false); } }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!formData.menuNameKor.trim()) { toast.error(getMenuTextSync(MENU_MANAGEMENT_KEYS.MESSAGE_VALIDATION_MENU_NAME_REQUIRED)); return; } if (!formData.companyCode) { toast.error(getMenuTextSync(MENU_MANAGEMENT_KEYS.MESSAGE_VALIDATION_COMPANY_REQUIRED)); return; } try { setLoading(true); // 백엔드에 전송할 데이터 변환 const submitData = { ...formData, // 상태를 소문자로 변환 (백엔드에서 소문자 기대) status: formData.status.toLowerCase(), }; console.log("저장할 데이터:", submitData); const response = await menuApi.saveMenu(submitData); if (response.success) { toast.success(response.message); onSuccess(); onClose(); } else { toast.error(response.message); } } catch (error) { toast.error(getMenuTextSync(MENU_MANAGEMENT_KEYS.MESSAGE_MENU_SAVE_FAILED)); } finally { setLoading(false); } }; const handleInputChange = (field: keyof MenuFormData, value: string | number) => { setFormData((prev) => ({ ...prev, [field]: value, })); }; // 선택된 다국어 키 정보 가져오기 const getSelectedLangKeyInfo = () => { if (!formData.langKey) return null; return langKeys.find((key) => key.langKey === formData.langKey); }; const selectedLangKeyInfo = getSelectedLangKeyInfo(); return ( {isEdit ? getMenuTextSync(MENU_MANAGEMENT_KEYS.MODAL_MENU_MODIFY_TITLE) : getMenuTextSync(MENU_MANAGEMENT_KEYS.MODAL_MENU_REGISTER_TITLE)}
{!isEdit && level !== 1 && (

{getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_COMPANY_SUBMENU_NOTE)}

)}
{isLangKeyDropdownOpen && (
{/* 검색 입력 */}
setLangKeySearchText(e.target.value)} className="h-8 text-sm" onClick={(e) => e.stopPropagation()} />
{/* 다국어 키 목록 */}
{ handleInputChange("langKey", ""); setIsLangKeyDropdownOpen(false); setLangKeySearchText(""); }} > {getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_LANG_KEY_NONE)}
{langKeys .filter( (key) => key.langKey.toLowerCase().includes(langKeySearchText.toLowerCase()) || key.description.toLowerCase().includes(langKeySearchText.toLowerCase()), ) .map((key) => (
{ handleInputChange("langKey", key.langKey); setIsLangKeyDropdownOpen(false); setLangKeySearchText(""); }} >
{key.langKey}
{key.description &&
{key.description}
}
))}
)}
{selectedLangKeyInfo && (

{getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_LANG_KEY_SELECTED, { key: selectedLangKeyInfo.langKey, description: selectedLangKeyInfo.description, })}

)}
handleInputChange("menuNameKor", e.target.value)} placeholder={getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_MENU_NAME_PLACEHOLDER)} required />
handleInputChange("menuUrl", e.target.value)} placeholder={getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_MENU_URL_PLACEHOLDER)} />