"use client"; import React, { useEffect, useState } from "react"; import { toast } from "sonner"; import { menuApi } from "@/lib/api/menu"; import type { MenuItem, MenuFormData, LangKey } from "@/lib/api/menu"; import { companyAPI } from "@/lib/api/company"; import { MenuIconPicker } from "@/components/admin/MenuIconPicker"; interface Props { menu: MenuItem; parentName: string; onSaved: () => void; onDelete: (menuId: string) => void; onOpenAdvanced: (menuId: string) => void; } interface CompanyOption { company_code: string; company_name: string; status?: string; } interface FormState { menuNameKor: string; menuUrl: string; menuDesc: string; menuIcon: string; seq: number; companyCode: string; status: string; langKey: string; } const toForm = (m: MenuItem): FormState => ({ menuNameKor: m.menu_name_kor ?? m.MENU_NAME_KOR ?? "", menuUrl: m.menu_url ?? m.MENU_URL ?? "", menuDesc: m.menu_desc ?? m.MENU_DESC ?? "", menuIcon: m.menu_icon ?? m.MENU_ICON ?? "", seq: Number(m.seq ?? m.SEQ ?? 1), companyCode: m.company_code ?? m.COMPANY_CODE ?? "*", // DB는 소문자 'active'/'inactive' — 원본 그대로 유지 status: (m.status ?? m.STATUS ?? "active").toString().toLowerCase(), langKey: m.lang_key ?? m.LANG_KEY ?? "", }); export function MenuSettingsPanel({ menu, parentName, onSaved, onDelete, onOpenAdvanced }: Props) { const menuId = String(menu.objid ?? menu.OBJID ?? ""); const initial = toForm(menu); const [form, setForm] = useState(initial); const [saving, setSaving] = useState(false); // 드롭다운 옵션 소스 const [companies, setCompanies] = useState([]); const [langKeys, setLangKeys] = useState([]); useEffect(() => { setForm(toForm(menu)); }, [menu]); // 회사 목록 로드 (1회) useEffect(() => { let alive = true; (async () => { try { const list = await companyAPI.getList({ status: "active" }); if (alive) setCompanies(list || []); } catch { /* silent - 기본값 사용 */ } })(); return () => { alive = false; }; }, []); // 다국어 키 로드 (companyCode 변경 시 재로드, 활성 키만 필터) useEffect(() => { let alive = true; (async () => { try { const resp = await menuApi.getLangKeys({ companyCode: form.companyCode || "*", }); if (alive && resp.success && resp.data) { setLangKeys(resp.data.filter((k) => k.isActive === "Y")); } } catch { if (alive) setLangKeys([]); } })(); return () => { alive = false; }; }, [form.companyCode]); const isDirty = form.menuNameKor !== initial.menuNameKor || form.menuUrl !== initial.menuUrl || form.menuDesc !== initial.menuDesc || form.menuIcon !== initial.menuIcon || form.seq !== initial.seq || form.companyCode !== initial.companyCode || form.status !== initial.status || form.langKey !== initial.langKey; const set = (k: K, v: FormState[K]) => setForm((f) => ({ ...f, [k]: v })); const handleSave = async () => { if (!form.menuNameKor.trim()) { toast.error("메뉴명을 입력하세요"); return; } setSaving(true); try { const payload: MenuFormData = { objid: menuId, parentObjId: String(menu.parent_obj_id ?? menu.PARENT_OBJ_ID ?? "0"), menuNameKor: form.menuNameKor, menuUrl: form.menuUrl, menuDesc: form.menuDesc, seq: form.seq, menu_type: String(menu.menu_type ?? menu.MENU_TYPE ?? "1"), status: form.status, company_code: form.companyCode, langKey: form.langKey || undefined, menuIcon: form.menuIcon || undefined, }; const resp = await menuApi.updateMenu(menuId, payload); if (resp.success) { toast.success(resp.message || "저장되었습니다"); onSaved(); } else { toast.error(resp.message || "저장 실패"); } } catch (e) { toast.error("저장 중 오류가 발생했습니다"); } finally { setSaving(false); } }; const statusOn = form.status === "active"; return (
관리자 / {parentName || "최상위"}

{form.menuNameKor || "(이름 없음)"} {statusOn ? "Active" : "Inactive"} {form.companyCode === "*" ? "공용 *" : form.companyCode || "—"} L{Number(menu.lev ?? menu.LEV ?? 1)}

OBJID {menuId} 수정 {menu.regdate ?? menu.REGDATE ?? "—"} 작성 {menu.writer ?? menu.WRITER ?? "—"}

기본 정보

메뉴 이름, 다국어 키, 사용자에게 표시되는 설명을 설정합니다.

set("menuNameKor", e.target.value)} />
set("menuIcon", iconName)} label="" />