"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, }) => { console.log("๐ŸŽฏ MenuFormModal ๋ Œ๋”๋ง - Props:", { isOpen, menuId, parentId, menuType, level, parentCompanyCode, }); console.log("๐Ÿ” MenuFormModal ์ปดํฌ๋„ŒํŠธ ๋งˆ์šดํŠธ๋จ"); const [formData, setFormData] = useState({ parentObjId: parentId || "0", menuNameKor: "", menuUrl: "", menuDesc: "", seq: 1, menuType: "1", status: "ACTIVE", companyCode: parentCompanyCode || "none", 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(""); // loadMenuData ํ•จ์ˆ˜๋ฅผ ๋จผ์ € ์ •์˜ 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); } }; // useEffect๋ฅผ loadMenuData ํ•จ์ˆ˜ ์ •์˜ ํ›„๋กœ ์ด๋™ useEffect(() => { console.log("๐Ÿš€ MenuFormModal useEffect ์‹คํ–‰๋จ!"); console.log("๐Ÿ“‹ useEffect ํŒŒ๋ผ๋ฏธํ„ฐ:", { menuId, parentId, menuType }); 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]); // ๊ฐ•์ œ๋กœ useEffect ์‹คํ–‰์‹œํ‚ค๊ธฐ ์œ„ํ•œ ๋ณ„๋„ useEffect useEffect(() => { console.log("๐Ÿ”ง ๊ฐ•์ œ useEffect ์‹คํ–‰ - ์ปดํฌ๋„ŒํŠธ ๋งˆ์šดํŠธ๋จ"); console.log("๐Ÿ”ง ํ˜„์žฌ props:", { isOpen, menuId, parentId, menuType }); // isOpen์ด true์ผ ๋•Œ๋งŒ ์‹คํ–‰ if (isOpen && menuId) { console.log("๐Ÿ”ง ๋ชจ๋‹ฌ์ด ์—ด๋ ธ๊ณ  menuId๊ฐ€ ์žˆ์Œ - ๊ฐ•์ œ ์‹คํ–‰"); // ์•ฝ๊ฐ„์˜ ์ง€์—ฐ ํ›„ ์‹คํ–‰ setTimeout(() => { console.log("๐Ÿ”ง setTimeout์œผ๋กœ loadMenuData ์‹คํ–‰"); loadMenuData(); }, 100); } }, [isOpen]); // isOpen๋งŒ ์˜์กด์„ฑ์œผ๋กœ ์„ค์ • // ํšŒ์‚ฌ ๋ชฉ๋ก ๋กœ๋“œ 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([]); } }; 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); let response; if (isEdit && menuId) { // ์ˆ˜์ • ๋ชจ๋“œ: updateMenu API ํ˜ธ์ถœ console.log("๐Ÿ”ง ๋ฉ”๋‰ด ์ˆ˜์ • API ํ˜ธ์ถœ:", menuId); response = await menuApi.updateMenu(menuId, submitData); } else { // ์ถ”๊ฐ€ ๋ชจ๋“œ: saveMenu API ํ˜ธ์ถœ console.log("โž• ๋ฉ”๋‰ด ์ถ”๊ฐ€ API ํ˜ธ์ถœ"); response = await menuApi.saveMenu(submitData); } if (response.success) { toast.success(response.message); onSuccess(); onClose(); } else { toast.error(response.message); } } catch (error) { console.error("๋ฉ”๋‰ด ์ €์žฅ/์ˆ˜์ • ์‹คํŒจ:", 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(); // ์ „์—ญ ์‚ฌ์šฉ์ž ๋กœ์ผ€์ผ ๊ฐ€์ ธ์˜ค๊ธฐ const getCurrentUserLang = () => { return (window as any).__GLOBAL_USER_LANG || localStorage.getItem("userLocale") || "KR"; }; return ( {isEdit ? getMenuTextSync(MENU_MANAGEMENT_KEYS.MODAL_MENU_MODIFY_TITLE, getCurrentUserLang()) : getMenuTextSync(MENU_MANAGEMENT_KEYS.MODAL_MENU_REGISTER_TITLE, getCurrentUserLang())}
{!isEdit && level !== 1 && (

{getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_COMPANY_SUBMENU_NOTE, getCurrentUserLang())}

)}
{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, getCurrentUserLang())}
{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, getCurrentUserLang())} required />
handleInputChange("menuUrl", e.target.value)} placeholder={getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_MENU_URL_PLACEHOLDER, getCurrentUserLang())} />