// app/evcp/menu-list/components/menu-list-table.tsx "use client"; import { useState, useMemo } from "react"; import { useParams } from "next/navigation"; import { useTranslation } from "@/i18n/client"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; import { Switch } from "@/components/ui/switch"; import { Button } from "@/components/ui/button"; import { Search, Filter, ExternalLink } from "lucide-react"; import { toast } from "sonner"; import { ManagerSelect } from "./manager-select"; import { InitializeButton } from "./initialize-button"; import { ExportButton } from "./export-button"; import { toggleMenuActive } from "../servcie"; interface MenuAssignment { id: number; menuPath: string; menuTitle: string; menuDescription?: string | null; menuGroup?: string | null; sectionTitle: string; domain: string; isActive: boolean; createdAt: Date; updatedAt: Date; manager1Id?: number | null; manager2Id?: number | null; manager1Name?: string | null; manager1Email?: string | null; manager2Name?: string | null; manager2Email?: string | null; } interface User { id: number; name: string; email: string; domain: string; } interface MenuListTableProps { initialMenus: MenuAssignment[]; initialUsers: User[]; } export function MenuListTable({ initialMenus, initialUsers }: MenuListTableProps) { // URL에서 언어 파라미터 가져오기 const params = useParams(); const lng = (params?.lng as string) || 'ko'; const { t } = useTranslation(lng, 'menu'); // 안전한 번역 함수 (키가 없을 때 원본 키 반환) const safeTranslate = (key: string): string => { try { const translated = t(key); // 번역 키가 그대로 반환되는 경우 원본 키 사용 if (translated === key) { return key; } return translated || key; } catch (error) { console.warn(`Translation failed for key: ${key}`, error); return key; } }; const [searchQuery, setSearchQuery] = useState(""); const [domainFilter, setDomainFilter] = useState("all"); const [sectionFilter, setSectionFilter] = useState("all"); const [statusFilter, setStatusFilter] = useState("all"); // 필터링된 메뉴 데이터 const filteredMenus = useMemo(() => { return initialMenus.filter((menu) => { const translatedTitle = safeTranslate(menu.menuTitle); const translatedSection = safeTranslate(menu.sectionTitle); const translatedDescription = menu.menuDescription ? safeTranslate(menu.menuDescription) : ''; const matchesSearch = translatedTitle.toLowerCase().includes(searchQuery.toLowerCase()) || menu.menuPath.toLowerCase().includes(searchQuery.toLowerCase()) || translatedSection.toLowerCase().includes(searchQuery.toLowerCase()) || translatedDescription.toLowerCase().includes(searchQuery.toLowerCase()); const matchesDomain = domainFilter === "all" || menu.domain === domainFilter; const matchesSection = sectionFilter === "all" || translatedSection === sectionFilter; const matchesStatus = statusFilter === "all" || (statusFilter === "active" && menu.isActive) || (statusFilter === "inactive" && !menu.isActive); return matchesSearch && matchesDomain && matchesSection && matchesStatus; }); }, [initialMenus, searchQuery, domainFilter, sectionFilter, statusFilter, safeTranslate]); // 섹션 리스트 추출 (번역된 이름으로) const sections = useMemo(() => { const sectionSet = new Set(initialMenus.map(menu => safeTranslate(menu.sectionTitle))); return Array.from(sectionSet).sort(); }, [initialMenus, safeTranslate]); // 도메인별 사용자 필터링 const getFilteredUsers = (domain: string) => { return initialUsers.filter(user => user.domain === domain); }; // 메뉴 활성화/비활성화 토글 const handleToggleActive = async (menuPath: string, isActive: boolean) => { try { const result = await toggleMenuActive(menuPath, isActive); if (result.success) { toast.success(result.message); } else { toast.error(result.message); } } catch (error) { toast.error("메뉴 상태 변경 중 오류가 발생했습니다."); } }; return (
{/* 필터 영역 */}
setSearchQuery(e.target.value)} className="pl-8" />
{/* 결과 요약, 엑셀 다운로드 및 초기화 버튼 */}
총 {filteredMenus.length}개의 메뉴 {searchQuery && ` (${initialMenus.length}개 중 검색 결과)`}
{/* 테이블 */}
상태 메뉴 정보 도메인 담당자 1 담당자 2 {/* 동작 */} {filteredMenus.length === 0 ? ( 조건에 맞는 메뉴가 없습니다. ) : ( filteredMenus.map((menu) => { const domainUsers = getFilteredUsers(menu.domain); return ( handleToggleActive(menu.menuPath, checked)} />
{(menu as any).translatedMenuTitle || safeTranslate(menu.menuTitle)} {(menu as any).translatedSectionTitle || safeTranslate(menu.sectionTitle)} {menu.menuGroup && ( {(menu as any).translatedMenuGroup || safeTranslate(menu.menuGroup)} )}
{menu.menuPath}
{menu.menuDescription && (
{(menu as any).translatedMenuDescription || safeTranslate(menu.menuDescription)}
)}
{menu.domain.toUpperCase()} {/* */}
); }) )}
); }