diff --git a/FRONTEND/src/App.tsx b/FRONTEND/src/App.tsx index f90854e..658c938 100644 --- a/FRONTEND/src/App.tsx +++ b/FRONTEND/src/App.tsx @@ -583,6 +583,7 @@ function App() { setIsLogModalOpen={setIsLogModalOpen} setTestLogContent={setTestLogContent} scenarios={scenarios} + setScenarios={setScenarios} setExpanded={setExpandedBottomBar} activeTabBottom={activeTabBottom} setActiveTabBottom={setActiveTabBottom} diff --git a/FRONTEND/src/components/BottomToolBar.tsx b/FRONTEND/src/components/BottomToolBar.tsx index 356a74f..3f19c9f 100644 --- a/FRONTEND/src/components/BottomToolBar.tsx +++ b/FRONTEND/src/components/BottomToolBar.tsx @@ -19,9 +19,10 @@ import type { Socket } from "socket.io-client"; import { ButtonDPELP, ButtonSelect } from "./ButtonAction"; import DrawerLogs from "./DrawerLogs"; import { DrawerAPCControl, DrawerSwitchControl } from "./DrawerControl"; +import DrawerScenario from "./DrawerScenario"; import { isJsonString } from "../untils/helper"; import { motion } from "motion/react"; -import { IconCaretDown, IconCaretUp, IconPlayerPlay } from "@tabler/icons-react"; +import { IconCaretDown, IconCaretUp, IconPlayerPlay, IconPlus } from "@tabler/icons-react"; interface TabsProps { selectedLines: TLine[]; @@ -35,6 +36,7 @@ interface TabsProps { setIsLogModalOpen: (value: React.SetStateAction) => void; setTestLogContent: (value: React.SetStateAction) => void; scenarios: IScenario[]; + setScenarios: (value: React.SetStateAction) => void; setExpanded: (value: React.SetStateAction) => void; activeTabBottom: string; setActiveTabBottom: (value: React.SetStateAction) => void; @@ -53,6 +55,7 @@ const BottomToolBar = ({ setIsLogModalOpen, setTestLogContent, scenarios, + setScenarios, setExpanded, setActiveTabBottom, activeTabBottom, @@ -67,6 +70,7 @@ const BottomToolBar = ({ const [valueInput, setValueInput] = useState(""); const inputRef = useRef(null); const [openScenarioModal, setOpenScenarioModal] = useState(false); + const [openDrawerScenario, setOpenDrawerScenario] = useState(false); // const [activeTabBottom, setActiveTabBottom] = useState("command"); // const [isExpand, setIsExpand] = useState(true); @@ -123,10 +127,26 @@ const BottomToolBar = ({ 🎯 Select Scenario to Run - setOpenScenarioModal(false)} - /> + + + setOpenScenarioModal(false)} + /> + {/* Content */} @@ -542,6 +562,14 @@ const BottomToolBar = ({ + + {/* Drawer Scenario để Add/Edit */} + setOpenDrawerScenario(false)} + /> ); }; diff --git a/FRONTEND/src/components/DrawerScenario.tsx b/FRONTEND/src/components/DrawerScenario.tsx index 90bffe7..7e4bac4 100644 --- a/FRONTEND/src/components/DrawerScenario.tsx +++ b/FRONTEND/src/components/DrawerScenario.tsx @@ -1,22 +1,21 @@ import { useDisclosure } from "@mantine/hooks"; import { - Drawer, Box, ScrollArea, Table, Grid, TextInput, Button, - Checkbox, Text, + Flex, + CloseButton, } from "@mantine/core"; -import { IconSettingsPlus } from "@tabler/icons-react"; +import classes from "./Component.module.css"; import TableRows from "./Scenario/TableRows"; import { useEffect, useState } from "react"; import { useForm } from "@mantine/form"; import DialogConfirm from "./DialogConfirm"; import type { IBodyScenario, IScenario } from "../untils/types"; -import classes from "./Component.module.css"; import axios from "axios"; import { notifications } from "@mantine/notifications"; const apiUrl = import.meta.env.VITE_BACKEND_URL; @@ -24,11 +23,26 @@ const apiUrl = import.meta.env.VITE_BACKEND_URL; function DrawerScenario({ scenarios, setScenarios, + externalOpened, + onExternalClose, }: { scenarios: IScenario[]; setScenarios: (value: React.SetStateAction) => void; + externalOpened?: boolean; + onExternalClose?: () => void; }) { - const [opened, { open, close }] = useDisclosure(false); + const [opened, { close }] = useDisclosure(false); + + // Sử dụng external state nếu được provide, nếu không thì dùng internal state + const isOpened = externalOpened !== undefined ? externalOpened : opened; + + const handleClose = () => { + if (onExternalClose) { + onExternalClose(); + } else { + close(); + } + }; const [isEdit, setIsEdit] = useState(false); const [openConfirm, setOpenConfirm] = useState(false); const [isSubmit, setIsSubmit] = useState(false); @@ -178,62 +192,125 @@ function DrawerScenario({ }; useEffect(() => { - if (!opened) { + if (!isOpened) { setIsEdit(false); setIsSubmit(false); setDataScenario(undefined); form.reset(); } - }, [opened]); + }, [isOpened]); return ( <> - - - - {scenarios.map((scenario) => ( - - ))} - - + {/* Custom Modal - Giống như Modal Select Scenario */} + {isOpened && ( +
+
e.stopPropagation()} + > + {/* Header */} + + + {isEdit ? "✏️ Edit Scenarios" : "➕ Add Scenarios"} + + + + + {/* Content */} +
+ + {/* Sidebar - List Scenarios */} + + + + {scenarios.map((scenario) => ( + + ))} + + + + + {/* Main Content */} + @@ -318,7 +395,10 @@ function DrawerScenario({
- + - - - - - Scenarios - { - open(); - }} - /> - + + + + + + )} { setOpenConfirm(false); handleDelete(); - close(); + handleClose(); }} centered={true} />