// app/evcp/menu-list/components/menu-list-table.tsx "use client"; import { useState, useMemo } from "react"; 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 { 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) { 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 matchesSearch = menu.menuTitle.toLowerCase().includes(searchQuery.toLowerCase()) || menu.menuPath.toLowerCase().includes(searchQuery.toLowerCase()) || menu.sectionTitle.toLowerCase().includes(searchQuery.toLowerCase()) || (menu.menuDescription?.toLowerCase().includes(searchQuery.toLowerCase()) ?? false); const matchesDomain = domainFilter === "all" || menu.domain === domainFilter; const matchesSection = sectionFilter === "all" || menu.sectionTitle === sectionFilter; const matchesStatus = statusFilter === "all" || (statusFilter === "active" && menu.isActive) || (statusFilter === "inactive" && !menu.isActive); return matchesSearch && matchesDomain && matchesSection && matchesStatus; }); }, [initialMenus, searchQuery, domainFilter, sectionFilter, statusFilter]); // 섹션 리스트 추출 const sections = useMemo(() => { const sectionSet = new Set(initialMenus.map(menu => menu.sectionTitle)); return Array.from(sectionSet).sort(); }, [initialMenus]); // 도메인별 사용자 필터링 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.menuTitle} {menu.sectionTitle} {menu.menuGroup && ( {menu.menuGroup} )}
{menu.menuPath}
{menu.menuDescription && (
{menu.menuDescription}
)}
{menu.domain.toUpperCase()} {/* */}
); }) )}
); }