"use client"; import { useState, useEffect, useMemo } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Badge } from "@/components/ui/badge"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { DataTable } from "@/components/common/DataTable"; import { LoadingSpinner } from "@/components/common/LoadingSpinner"; import { useAuth } from "@/hooks/useAuth"; import { apiClient } from "@/lib/api/client"; interface Language { langCode: string; langName: string; langNative: string; isActive: string; } interface LangKey { keyId: number; companyCode: string; menuCode: string; langKey: string; keyType: string; description: string; isActive: string; } interface LangText { textId: number; keyId: number; langCode: string; langText: string; isActive: string; } export default function MultiLangPage() { const { user } = useAuth(); const [loading, setLoading] = useState(true); const [languages, setLanguages] = useState([]); const [langKeys, setLangKeys] = useState([]); const [selectedCompany, setSelectedCompany] = useState(""); const [selectedMenu, setSelectedMenu] = useState(""); const [selectedKeyType, setSelectedKeyType] = useState(""); // 검색 관련 상태 추가 const [searchText, setSearchText] = useState(""); const [companySearchText, setCompanySearchText] = useState(""); const [isCompanyDropdownOpen, setIsCompanyDropdownOpen] = useState(false); const [companies] = useState([ { code: "ILSHIN", name: "일신공업" }, { code: "HUTECH", name: "후테크" }, { code: "DAIN", name: "다인" }, ]); const [menus] = useState([ { code: "DASHBOARD", name: "대시보드" }, { code: "USER_MANAGEMENT", name: "사용자 관리" }, { code: "MENU_MANAGEMENT", name: "메뉴 관리" }, { code: "MULTI_LANG", name: "다국어 관리" }, ]); const [keyTypes] = useState([ { code: "TEXT", name: "텍스트" }, { code: "TITLE", name: "제목" }, { code: "LABEL", name: "라벨" }, { code: "BUTTON", name: "버튼" }, { code: "MESSAGE", name: "메시지" }, { code: "ERROR", name: "오류" }, ]); // 드롭다운 외부 클릭 시 닫기 useEffect(() => { const handleClickOutside = (event: MouseEvent) => { const target = event.target as Element; if (!target.closest(".company-dropdown")) { setIsCompanyDropdownOpen(false); setCompanySearchText(""); } }; if (isCompanyDropdownOpen) { document.addEventListener("mousedown", handleClickOutside); } return () => { document.removeEventListener("mousedown", handleClickOutside); }; }, [isCompanyDropdownOpen]); // 언어 목록 조회 const fetchLanguages = async () => { try { const response = await apiClient.get("/api/admin/multilang/languages"); const data = response.data; if (data.success) { setLanguages(data.data); } } catch (error) { console.error("언어 목록 조회 실패:", error); } }; // 다국어 키 목록 조회 const fetchLangKeys = async () => { try { const response = await apiClient.get("/api/admin/multilang/keys"); const data = response.data; if (data.success) { setLangKeys(data.data); } } catch (error) { console.error("다국어 키 목록 조회 실패:", error); } }; useEffect(() => { const initializeData = async () => { setLoading(true); await Promise.all([fetchLanguages(), fetchLangKeys()]); setLoading(false); }; initializeData(); }, []); // 필터링된 데이터 계산 - 메뉴관리와 동일한 방식 const getFilteredLangKeys = () => { let filteredKeys = langKeys; // 회사 필터링 if (selectedCompany) { filteredKeys = filteredKeys.filter((key) => key.companyCode === selectedCompany); } // 메뉴 필터링 if (selectedMenu) { filteredKeys = filteredKeys.filter((key) => key.menuCode === selectedMenu); } // 키 타입 필터링 if (selectedKeyType) { filteredKeys = filteredKeys.filter((key) => key.keyType === selectedKeyType); } // 텍스트 검색 필터링 if (searchText.trim()) { const searchLower = searchText.toLowerCase(); filteredKeys = filteredKeys.filter((key) => { const langKey = (key.langKey || "").toLowerCase(); const description = (key.description || "").toLowerCase(); const companyName = companies.find((c) => c.code === key.companyCode)?.name?.toLowerCase() || ""; const menuName = menus.find((m) => m.code === key.menuCode)?.name?.toLowerCase() || ""; const keyTypeName = keyTypes.find((t) => t.code === key.keyType)?.name?.toLowerCase() || ""; return ( langKey.includes(searchLower) || description.includes(searchLower) || companyName.includes(searchLower) || menuName.includes(searchLower) || keyTypeName.includes(searchLower) ); }); } return filteredKeys; }; const columns = [ { accessorKey: "companyCode", header: "회사", cell: ({ row }: any) => { const company = companies.find((c) => c.code === row.original.companyCode); return company ? company.name : row.original.companyCode; }, }, { accessorKey: "menuCode", header: "메뉴", cell: ({ row }: any) => { const menu = menus.find((m) => m.code === row.original.menuCode); return menu ? menu.name : row.original.menuCode; }, }, { accessorKey: "langKey", header: "언어 키", }, { accessorKey: "keyType", header: "타입", cell: ({ row }: any) => { const type = keyTypes.find((t) => t.code === row.original.keyType); return type ? type.name : row.original.keyType; }, }, { accessorKey: "description", header: "설명", }, { accessorKey: "isActive", header: "상태", cell: ({ row }: any) => ( {row.original.isActive === "Y" ? "활성" : "비활성"} ), }, ]; if (loading) { return ; } const filteredLangKeys = getFilteredLangKeys(); return (

다국어 관리

다국어 키 관리 언어 관리 메뉴 관리 다국어 키 목록 {/* 검색 및 필터 영역 */}
{isCompanyDropdownOpen && (
{/* 검색 입력 */}
setCompanySearchText(e.target.value)} className="h-8 text-sm" onClick={(e) => e.stopPropagation()} />
{/* 회사 목록 */}
{ setSelectedCompany(""); setIsCompanyDropdownOpen(false); setCompanySearchText(""); }} > 전체 회사
{companies .filter( (company) => company.name.toLowerCase().includes(companySearchText.toLowerCase()) || company.code.toLowerCase().includes(companySearchText.toLowerCase()), ) .map((company) => (
{ setSelectedCompany(company.code); setIsCompanyDropdownOpen(false); setCompanySearchText(""); }} > {company.name}
))}
)}
{/* Radix UI Select v2.x: 빈 문자열 value="" 금지 → "__all__" 사용 */}
{/* Radix UI Select v2.x: 빈 문자열 value="" 금지 → "__all__" 사용 */}
setSearchText(e.target.value)} />
검색 결과: {filteredLangKeys.length}건
전체: {filteredLangKeys.length}건
{ // 키 상세 정보 모달 열기 console.log("선택된 키:", row); }} />
언어 관리
{languages.map((lang) => (
{lang.langName}
{lang.langNative}
{lang.isActive === "Y" ? "활성" : "비활성"}
))}
메뉴 관리
{companies.map((company) => (

{company.name}

{menus.map((menu) => (
{menu.name}
))}
))}
); }