메뉴관리 다국어 적용
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user