메뉴관리 다국어 적용

This commit is contained in:
kjs
2025-08-25 17:56:33 +09:00
parent 307faba089
commit 7bb7f1621f
4 changed files with 241 additions and 127 deletions

View File

@@ -10,7 +10,7 @@ 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";
import { MENU_MANAGEMENT_KEYS } from "@/lib/utils/multilang";
interface Company {
company_code: string;
@@ -27,6 +27,8 @@ interface MenuFormModalProps {
menuType?: string;
level?: number;
parentCompanyCode?: string;
// 다국어 텍스트 props 추가
uiTexts: Record<string, string>;
}
export const MenuFormModal: React.FC<MenuFormModalProps> = ({
@@ -38,6 +40,7 @@ export const MenuFormModal: React.FC<MenuFormModalProps> = ({
menuType,
level,
parentCompanyCode,
uiTexts,
}) => {
console.log("🎯 MenuFormModal 렌더링 - Props:", {
isOpen,
@@ -48,6 +51,11 @@ export const MenuFormModal: React.FC<MenuFormModalProps> = ({
parentCompanyCode,
});
// 다국어 텍스트 가져오기 함수
const getText = (key: string, fallback?: string): string => {
return uiTexts[key] || fallback || key;
};
console.log("🔍 MenuFormModal 컴포넌트 마운트됨");
const [formData, setFormData] = useState<MenuFormData>({
@@ -149,7 +157,7 @@ export const MenuFormModal: React.FC<MenuFormModalProps> = ({
stack: error?.stack,
response: error?.response,
});
toast.error(getMenuTextSync(MENU_MANAGEMENT_KEYS.MESSAGE_ERROR_LOAD_MENU_INFO));
toast.error(getText(MENU_MANAGEMENT_KEYS.MESSAGE_ERROR_LOAD_MENU_INFO));
} finally {
setLoading(false);
}
@@ -254,7 +262,7 @@ export const MenuFormModal: React.FC<MenuFormModalProps> = ({
setCompanies(companyList);
} catch (error) {
console.error("회사 목록 로딩 오류:", error);
toast.error(getMenuTextSync(MENU_MANAGEMENT_KEYS.MESSAGE_ERROR_LOAD_COMPANY_LIST));
toast.error(getText(MENU_MANAGEMENT_KEYS.MESSAGE_ERROR_LOAD_COMPANY_LIST));
}
};
@@ -273,7 +281,7 @@ export const MenuFormModal: React.FC<MenuFormModalProps> = ({
}
} catch (error) {
console.error("❌ 다국어 키 목록 로딩 오류:", error);
toast.error(getMenuTextSync(MENU_MANAGEMENT_KEYS.MESSAGE_ERROR_LOAD_LANG_KEY_LIST));
toast.error(getText(MENU_MANAGEMENT_KEYS.MESSAGE_ERROR_LOAD_LANG_KEY_LIST));
setLangKeys([]);
}
};
@@ -282,12 +290,12 @@ export const MenuFormModal: React.FC<MenuFormModalProps> = ({
e.preventDefault();
if (!formData.menuNameKor.trim()) {
toast.error(getMenuTextSync(MENU_MANAGEMENT_KEYS.MESSAGE_VALIDATION_MENU_NAME_REQUIRED));
toast.error(getText(MENU_MANAGEMENT_KEYS.MESSAGE_VALIDATION_MENU_NAME_REQUIRED));
return;
}
if (!formData.companyCode) {
toast.error(getMenuTextSync(MENU_MANAGEMENT_KEYS.MESSAGE_VALIDATION_COMPANY_REQUIRED));
toast.error(getText(MENU_MANAGEMENT_KEYS.MESSAGE_VALIDATION_COMPANY_REQUIRED));
return;
}
@@ -324,7 +332,7 @@ export const MenuFormModal: React.FC<MenuFormModalProps> = ({
}
} catch (error) {
console.error("메뉴 저장/수정 실패:", error);
toast.error(getMenuTextSync(MENU_MANAGEMENT_KEYS.MESSAGE_MENU_SAVE_FAILED));
toast.error(getText(MENU_MANAGEMENT_KEYS.MESSAGE_MENU_SAVE_FAILED));
} finally {
setLoading(false);
}
@@ -356,68 +364,52 @@ export const MenuFormModal: React.FC<MenuFormModalProps> = ({
<DialogHeader>
<DialogTitle>
{isEdit
? getMenuTextSync(MENU_MANAGEMENT_KEYS.MODAL_MENU_MODIFY_TITLE, getCurrentUserLang())
: getMenuTextSync(MENU_MANAGEMENT_KEYS.MODAL_MENU_REGISTER_TITLE, getCurrentUserLang())}
? getText(MENU_MANAGEMENT_KEYS.MODAL_MENU_MODIFY_TITLE)
: getText(MENU_MANAGEMENT_KEYS.MODAL_MENU_REGISTER_TITLE)}
</DialogTitle>
</DialogHeader>
<form onSubmit={handleSubmit} className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="menuType">
{getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_MENU_TYPE, getCurrentUserLang())}
</Label>
<Label htmlFor="menuType">{getText(MENU_MANAGEMENT_KEYS.FORM_MENU_TYPE)}</Label>
<Select value={formData.menuType} onValueChange={(value) => handleInputChange("menuType", value)}>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="0">
{getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_MENU_TYPE_ADMIN, getCurrentUserLang())}
</SelectItem>
<SelectItem value="1">
{getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_MENU_TYPE_USER, getCurrentUserLang())}
</SelectItem>
<SelectItem value="0">{getText(MENU_MANAGEMENT_KEYS.FORM_MENU_TYPE_ADMIN)}</SelectItem>
<SelectItem value="1">{getText(MENU_MANAGEMENT_KEYS.FORM_MENU_TYPE_USER)}</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label htmlFor="status">{getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_STATUS, getCurrentUserLang())}</Label>
<Label htmlFor="status">{getText(MENU_MANAGEMENT_KEYS.TABLE_HEADER_STATUS)}</Label>
<Select value={formData.status} onValueChange={(value) => handleInputChange("status", value)}>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="ACTIVE">
{getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_STATUS_ACTIVE, getCurrentUserLang())}
</SelectItem>
<SelectItem value="INACTIVE">
{getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_STATUS_INACTIVE, getCurrentUserLang())}
</SelectItem>
<SelectItem value="ACTIVE">{getText(MENU_MANAGEMENT_KEYS.STATUS_ACTIVE)}</SelectItem>
<SelectItem value="INACTIVE">{getText(MENU_MANAGEMENT_KEYS.STATUS_INACTIVE)}</SelectItem>
</SelectContent>
</Select>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="companyCode">
{getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_COMPANY, getCurrentUserLang())} *
</Label>
<Label htmlFor="companyCode">{getText(MENU_MANAGEMENT_KEYS.FORM_COMPANY)} *</Label>
<Select
value={formData.companyCode}
onValueChange={(value) => handleInputChange("companyCode", value)}
disabled={!isEdit && level !== 1} // 수정 모드가 아니고 최상위 메뉴가 아니면 비활성화
>
<SelectTrigger>
<SelectValue
placeholder={getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_COMPANY_SELECT, getCurrentUserLang())}
/>
<SelectValue placeholder={getText(MENU_MANAGEMENT_KEYS.FORM_COMPANY_SELECT)} />
</SelectTrigger>
<SelectContent>
<SelectItem value="none">
{getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_COMPANY_COMMON, getCurrentUserLang())}
</SelectItem>
<SelectItem value="none">{getText(MENU_MANAGEMENT_KEYS.FORM_COMPANY_COMMON)}</SelectItem>
{companies.map((company) => (
<SelectItem key={company.company_code} value={company.company_code}>
{company.company_name}
@@ -426,14 +418,12 @@ export const MenuFormModal: React.FC<MenuFormModalProps> = ({
</SelectContent>
</Select>
{!isEdit && level !== 1 && (
<p className="text-xs text-gray-500">
{getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_COMPANY_SUBMENU_NOTE, getCurrentUserLang())}
</p>
<p className="text-xs text-gray-500">{getText(MENU_MANAGEMENT_KEYS.FORM_COMPANY_SUBMENU_NOTE)}</p>
)}
</div>
<div className="space-y-2">
<Label htmlFor="langKey">{getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_LANG_KEY, getCurrentUserLang())}</Label>
<Label htmlFor="langKey">{getText(MENU_MANAGEMENT_KEYS.FORM_LANG_KEY)}</Label>
<div className="langkey-dropdown relative">
<button
type="button"
@@ -442,7 +432,7 @@ export const MenuFormModal: React.FC<MenuFormModalProps> = ({
disabled={!formData.companyCode}
>
<span className={!formData.langKey ? "text-muted-foreground" : ""}>
{formData.langKey || getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_LANG_KEY_SELECT, getCurrentUserLang())}
{formData.langKey || getText(MENU_MANAGEMENT_KEYS.FORM_LANG_KEY_SELECT)}
</span>
<svg
className={`h-4 w-4 transition-transform ${isLangKeyDropdownOpen ? "rotate-180" : ""}`}
@@ -459,7 +449,7 @@ export const MenuFormModal: React.FC<MenuFormModalProps> = ({
{/* 검색 입력 */}
<div className="border-b p-2">
<Input
placeholder={getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_LANG_KEY_SEARCH, getCurrentUserLang())}
placeholder={getText(MENU_MANAGEMENT_KEYS.FORM_LANG_KEY_SEARCH)}
value={langKeySearchText}
onChange={(e) => setLangKeySearchText(e.target.value)}
className="h-8 text-sm"
@@ -477,7 +467,7 @@ export const MenuFormModal: React.FC<MenuFormModalProps> = ({
setLangKeySearchText("");
}}
>
{getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_LANG_KEY_NONE, getCurrentUserLang())}
{getText(MENU_MANAGEMENT_KEYS.FORM_LANG_KEY_NONE)}
</div>
{langKeys
@@ -506,57 +496,47 @@ export const MenuFormModal: React.FC<MenuFormModalProps> = ({
</div>
{selectedLangKeyInfo && (
<p className="text-xs text-gray-500">
{getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_LANG_KEY_SELECTED, {
key: selectedLangKeyInfo.langKey,
description: selectedLangKeyInfo.description,
})}
{getText(MENU_MANAGEMENT_KEYS.FORM_LANG_KEY_SELECTED)
.replace("{key}", selectedLangKeyInfo.langKey)
.replace("{description}", selectedLangKeyInfo.description)}
</p>
)}
</div>
<div className="space-y-2">
<Label htmlFor="menuNameKor">
{getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_MENU_NAME, getCurrentUserLang())} *
</Label>
<Label htmlFor="menuNameKor">{getText(MENU_MANAGEMENT_KEYS.FORM_MENU_NAME)} *</Label>
<Input
id="menuNameKor"
value={formData.menuNameKor}
onChange={(e) => handleInputChange("menuNameKor", e.target.value)}
placeholder={getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_MENU_NAME_PLACEHOLDER, getCurrentUserLang())}
placeholder={getText(MENU_MANAGEMENT_KEYS.FORM_MENU_NAME_PLACEHOLDER)}
required
/>
</div>
<div className="space-y-2">
<Label htmlFor="menuUrl">{getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_MENU_URL, getCurrentUserLang())}</Label>
<Label htmlFor="menuUrl">{getText(MENU_MANAGEMENT_KEYS.FORM_MENU_URL)}</Label>
<Input
id="menuUrl"
value={formData.menuUrl}
onChange={(e) => handleInputChange("menuUrl", e.target.value)}
placeholder={getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_MENU_URL_PLACEHOLDER, getCurrentUserLang())}
placeholder={getText(MENU_MANAGEMENT_KEYS.FORM_MENU_URL_PLACEHOLDER)}
/>
</div>
<div className="space-y-2">
<Label htmlFor="menuDesc">
{getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_MENU_DESCRIPTION, getCurrentUserLang())}
</Label>
<Label htmlFor="menuDesc">{getText(MENU_MANAGEMENT_KEYS.FORM_MENU_DESCRIPTION)}</Label>
<Textarea
id="menuDesc"
value={formData.menuDesc}
onChange={(e) => handleInputChange("menuDesc", e.target.value)}
placeholder={getMenuTextSync(
MENU_MANAGEMENT_KEYS.FORM_MENU_DESCRIPTION_PLACEHOLDER,
getCurrentUserLang(),
)}
placeholder={getText(MENU_MANAGEMENT_KEYS.FORM_MENU_DESCRIPTION_PLACEHOLDER)}
rows={3}
/>
</div>
<div className="space-y-2">
<Label htmlFor="seq">
{getMenuTextSync(MENU_MANAGEMENT_KEYS.FORM_MENU_SEQUENCE, getCurrentUserLang())}
</Label>
<Label htmlFor="seq">{getText(MENU_MANAGEMENT_KEYS.FORM_MENU_SEQUENCE)}</Label>
<Input
id="seq"
type="number"
@@ -568,14 +548,14 @@ export const MenuFormModal: React.FC<MenuFormModalProps> = ({
<div className="flex justify-end space-x-2 pt-4">
<Button type="button" variant="outline" onClick={onClose}>
{getMenuTextSync(MENU_MANAGEMENT_KEYS.BUTTON_CANCEL, getCurrentUserLang())}
{getText(MENU_MANAGEMENT_KEYS.BUTTON_CANCEL)}
</Button>
<Button type="submit" disabled={loading}>
{loading
? getMenuTextSync(MENU_MANAGEMENT_KEYS.BUTTON_SAVE_PROCESSING, getCurrentUserLang())
? getText(MENU_MANAGEMENT_KEYS.BUTTON_SAVE_PROCESSING)
: isEdit
? getMenuTextSync(MENU_MANAGEMENT_KEYS.BUTTON_MODIFY, getCurrentUserLang())
: getMenuTextSync(MENU_MANAGEMENT_KEYS.BUTTON_REGISTER, getCurrentUserLang())}
? getText(MENU_MANAGEMENT_KEYS.BUTTON_MODIFY)
: getText(MENU_MANAGEMENT_KEYS.BUTTON_REGISTER)}
</Button>
</div>
</form>