ERP-node/frontend/components/admin/dashboard/MenuAssignmentModal.tsx

211 lines
7.2 KiB
TypeScript

"use client";
import React, { useState, useEffect } from "react";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { toast } from "sonner";
import { menuApi, MenuItem } from "@/lib/api/menu";
import { Loader2 } from "lucide-react";
interface MenuAssignmentModalProps {
isOpen: boolean;
onClose: () => void;
onConfirm: (assignToMenu: boolean, menuId?: string, menuType?: "0" | "1") => void;
dashboardId: string;
dashboardTitle: string;
}
export const MenuAssignmentModal: React.FC<MenuAssignmentModalProps> = ({
isOpen,
onClose,
onConfirm,
dashboardId,
dashboardTitle,
}) => {
const [assignToMenu, setAssignToMenu] = useState<boolean>(false);
const [selectedMenuId, setSelectedMenuId] = useState<string>("");
const [selectedMenuType, setSelectedMenuType] = useState<"0" | "1">("0");
const [adminMenus, setAdminMenus] = useState<MenuItem[]>([]);
const [userMenus, setUserMenus] = useState<MenuItem[]>([]);
const [loading, setLoading] = useState(false);
// 메뉴 목록 로드
useEffect(() => {
if (isOpen && assignToMenu) {
loadMenus();
}
}, [isOpen, assignToMenu]);
const loadMenus = async () => {
try {
setLoading(true);
const [adminResponse, userResponse] = await Promise.all([
menuApi.getAdminMenus(), // 관리자 메뉴
menuApi.getUserMenus(), // 사용자 메뉴
]);
if (adminResponse.success) {
setAdminMenus(adminResponse.data || []);
}
if (userResponse.success) {
setUserMenus(userResponse.data || []);
}
} catch (error) {
console.error("메뉴 목록 로드 실패:", error);
toast.error("메뉴 목록을 불러오는데 실패했습니다.");
} finally {
setLoading(false);
}
};
// 메뉴 트리를 평탄화하여 Select 옵션으로 변환
const flattenMenus = (menus: MenuItem[], level: number = 0): Array<{ id: string; name: string; level: number }> => {
const result: Array<{ id: string; name: string; level: number }> = [];
menus.forEach((menu) => {
const menuId = menu.objid || menu.OBJID || "";
const menuName = menu.menu_name_kor || menu.MENU_NAME_KOR || "";
const parentId = menu.parent_obj_id || menu.PARENT_OBJ_ID || "0";
// 메뉴 이름이 있고, 최상위가 아닌 경우에만 추가
if (menuName && parentId !== "0") {
result.push({
id: menuId,
name: " ".repeat(level) + menuName,
level,
});
// 하위 메뉴가 있으면 재귀 호출
const children = menus.filter((m) => (m.parent_obj_id || m.PARENT_OBJ_ID) === menuId);
if (children.length > 0) {
result.push(...flattenMenus(children, level + 1));
}
}
});
return result;
};
const currentMenus = selectedMenuType === "0" ? adminMenus : userMenus;
const flatMenus = flattenMenus(currentMenus);
const handleConfirm = () => {
if (assignToMenu && !selectedMenuId) {
toast.error("메뉴를 선택해주세요.");
return;
}
onConfirm(assignToMenu, selectedMenuId, selectedMenuType);
};
const handleClose = () => {
setAssignToMenu(false);
setSelectedMenuId("");
setSelectedMenuType("0");
onClose();
};
return (
<Dialog open={isOpen} onOpenChange={handleClose}>
<DialogContent className="sm:max-w-[500px]">
<DialogHeader>
<DialogTitle> </DialogTitle>
<DialogDescription>'{dashboardTitle}' .</DialogDescription>
</DialogHeader>
<div className="space-y-4 py-4">
<div className="space-y-3">
<Label> ?</Label>
<RadioGroup
value={assignToMenu ? "yes" : "no"}
onValueChange={(value) => setAssignToMenu(value === "yes")}
className="flex space-x-4"
>
<div className="flex items-center space-x-2">
<RadioGroupItem value="yes" id="yes" />
<Label htmlFor="yes" className="cursor-pointer font-normal">
,
</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="no" id="no" />
<Label htmlFor="no" className="cursor-pointer font-normal">
,
</Label>
</div>
</RadioGroup>
</div>
{assignToMenu && (
<>
<div className="space-y-2">
<Label> </Label>
<RadioGroup
value={selectedMenuType}
onValueChange={(value) => {
setSelectedMenuType(value as "0" | "1");
setSelectedMenuId(""); // 메뉴 타입 변경 시 선택 초기화
}}
className="flex space-x-4"
>
<div className="flex items-center space-x-2">
<RadioGroupItem value="0" id="admin" />
<Label htmlFor="admin" className="cursor-pointer font-normal">
</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="1" id="user" />
<Label htmlFor="user" className="cursor-pointer font-normal">
</Label>
</div>
</RadioGroup>
</div>
<div className="space-y-2">
<Label> </Label>
{loading ? (
<div className="flex items-center justify-center py-4">
<Loader2 className="h-6 w-6 animate-spin text-gray-400" />
</div>
) : (
<Select value={selectedMenuId} onValueChange={setSelectedMenuId}>
<SelectTrigger>
<SelectValue placeholder="메뉴를 선택하세요" />
</SelectTrigger>
<SelectContent className="max-h-[300px]">
{flatMenus.map((menu) => (
<SelectItem key={menu.id} value={menu.id}>
{menu.name}
</SelectItem>
))}
</SelectContent>
</Select>
)}
</div>
</>
)}
</div>
<DialogFooter>
<Button variant="outline" onClick={handleClose}>
</Button>
<Button onClick={handleConfirm}>{assignToMenu ? "메뉴에 할당하고 완료" : "완료"}</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
};