From abfae279da003ad38bfbc26d81fd3774e3871424 Mon Sep 17 00:00:00 2001 From: nguyentrungthat <80239428+nguentrungthat@users.noreply.github.com> Date: Fri, 14 Nov 2025 16:29:35 +0700 Subject: [PATCH] Refactor BottomToolBar and DrawerControl UI layout Improved the BottomToolBar layout by wrapping it in a Grid and adjusting tab styles and heights for better alignment. Updated DrawerControl to refine port group rendering, including scrollable areas for large groups, reduced card widths, and minor style tweaks for consistency and usability. --- FRONTEND/src/App.tsx | 2 +- FRONTEND/src/components/BottomToolBar.tsx | 516 +++++++++++----------- FRONTEND/src/components/DrawerControl.tsx | 205 +++++++-- 3 files changed, 424 insertions(+), 299 deletions(-) diff --git a/FRONTEND/src/App.tsx b/FRONTEND/src/App.tsx index 002e1e9..17497dc 100644 --- a/FRONTEND/src/App.tsx +++ b/FRONTEND/src/App.tsx @@ -419,7 +419,7 @@ function App() { borderRadius: 8, }} > - + {station.lines.length > 8 ? ( ("command"); return ( - { - setActiveBottom(val || "command"); - }} - className={classes.containerBottom} - > - - + + + { + setActiveBottom(val || "command"); }} - value="command" + className={classes.containerBottom} + style={{ height: "14vh" }} > - Command Line - - - APC - - - Switch - - + + + Command Line + + + APC + + + Switch + + - - - - - {selectedLines.map((el) => ( - - - Line {el.lineNumber} - { - setSelectedLines( - selectedLines.filter((line) => line.id !== el.id) - ); - socket?.emit("close_cli", { - lineId: el?.id, - stationId: el.stationId || el.station_id, - }); + + + + + {selectedLines.map((el) => ( + - - - ))} - - - - - - - - - { - const newValue = event.currentTarget.value; - setValueInput(newValue); - }} - onKeyDown={(event) => { - if (event.key === "Enter") { - const listLine = selectedLines.length - ? selectedLines - : station?.lines; - if (listLine?.length) { - socket?.emit("write_command_line_from_web", { - lineIds: listLine.map((line) => line.id), - stationId: station.id, - command: valueInput + "\n", - }); - // setTimeout(() => { - // socket?.emit("write_command_line_from_web", { - // lineIds: listLine.map((line) => line.id), - // stationId: station.id, - // command: " \n", - // }); - // }, 1000); - } - setValueInput(""); - } - }} - rightSectionPointerEvents="all" - rightSection={ - setValueInput("")} - style={{ - display: valueInput ? undefined : "none", - }} - /> - } - /> - - - - - { - const lines = station.lines.filter( - (line) => - !line?.userOpenCLI || line?.userOpenCLI === user?.userName - ); - if (selectedLines.length !== lines.length) { - setSelectedLines(lines); - lines.forEach((line) => { - socket?.emit("open_cli", { - lineId: line.id, - stationId: line.stationId || line.station_id, - userEmail: user?.email, - userName: user?.userName, - }); - }); - } else { - lines.forEach((line) => { - socket?.emit("close_cli", { - lineId: line?.id, - stationId: line.stationId || line.station_id, - }); - }); - setSelectedLines([]); - } - }} - /> - { - // setSelectedLines([]); - setIsDisable(true); - setTimeout(() => { - setIsDisable(false); - }, 5000); - }} - /> - - + > + + Line {el.lineNumber} + { + setSelectedLines( + selectedLines.filter((line) => line.id !== el.id) + ); + socket?.emit("close_cli", { + lineId: el?.id, + stationId: el.stationId || el.station_id, + }); + }} + /> + + + ))} + + + + + - - - { + const listLine = selectedLines.length + ? selectedLines + : station?.lines; + if (listLine.length) { + socket?.emit("write_command_line_from_web", { + lineIds: listLine.map((line) => line.id), + stationId: station.id, + command: "spam_break", + }); + setIsDisable(true); + setTimeout(() => { + setIsDisable(false); + }, 5000); + } }} > - {scenarios.map((el, i) => ( - - !el?.userEmailOpenCLI || - el?.userEmailOpenCLI === user?.email - )} - isDisable={ - isDisable || - selectedLines.filter( - (el) => - !el?.userEmailOpenCLI || - el?.userEmailOpenCLI === user?.email - ).length === 0 + Send Break + + + + { + const newValue = event.currentTarget.value; + setValueInput(newValue); + }} + onKeyDown={(event) => { + if (event.key === "Enter") { + const listLine = selectedLines.length + ? selectedLines + : station?.lines; + if (listLine?.length) { + socket?.emit("write_command_line_from_web", { + lineIds: listLine.map((line) => line.id), + stationId: station.id, + command: valueInput + "\n", + }); + // setTimeout(() => { + // socket?.emit("write_command_line_from_web", { + // lineIds: listLine.map((line) => line.id), + // stationId: station.id, + // command: " \n", + // }); + // }, 1000); } - onClick={() => { - // setSelectedLines([]); - setIsDisable(true); - setTimeout(() => { - setIsDisable(false); - }, 5000); + setValueInput(""); + } + }} + rightSectionPointerEvents="all" + rightSection={ + setValueInput("")} + style={{ + display: valueInput ? undefined : "none", }} - scenario={el} /> - ))} - - - - + } + /> + + + + + { + const lines = station.lines.filter( + (line) => + !line?.userOpenCLI || + line?.userOpenCLI === user?.userName + ); + if (selectedLines.length !== lines.length) { + setSelectedLines(lines); + lines.forEach((line) => { + socket?.emit("open_cli", { + lineId: line.id, + stationId: line.stationId || line.station_id, + userEmail: user?.email, + userName: user?.userName, + }); + }); + } else { + lines.forEach((line) => { + socket?.emit("close_cli", { + lineId: line?.id, + stationId: line.stationId || line.station_id, + }); + }); + setSelectedLines([]); + } + }} + /> + { + // setSelectedLines([]); + setIsDisable(true); + setTimeout(() => { + setIsDisable(false); + }, 5000); + }} + /> + + + + + + + {scenarios.map((el, i) => ( + + !el?.userEmailOpenCLI || + el?.userEmailOpenCLI === user?.email + )} + isDisable={ + isDisable || + selectedLines.filter( + (el) => + !el?.userEmailOpenCLI || + el?.userEmailOpenCLI === user?.email + ).length === 0 + } + onClick={() => { + // setSelectedLines([]); + setIsDisable(true); + setTimeout(() => { + setIsDisable(false); + }, 5000); + }} + scenario={el} + /> + ))} + + + + + + - - - - - - - - - - + + + + + + + + + + + ); }; diff --git a/FRONTEND/src/components/DrawerControl.tsx b/FRONTEND/src/components/DrawerControl.tsx index a845602..46f9358 100644 --- a/FRONTEND/src/components/DrawerControl.tsx +++ b/FRONTEND/src/components/DrawerControl.tsx @@ -1,5 +1,14 @@ -import { Box, Button, Card, Grid, Loader, Text } from "@mantine/core"; -import { IconRepeat, IconSection } from "@tabler/icons-react"; +import { + Box, + Button, + Card, + Flex, + Grid, + Loader, + ScrollArea, + Text, +} from "@mantine/core"; +import { IconRepeat } from "@tabler/icons-react"; import { useEffect, useState } from "react"; import classes from "./Component.module.css"; import type { APCProps, SwitchPortsProps, TStation } from "../untils/types"; @@ -270,8 +279,10 @@ export const DrawerAPCControl: React.FC = ({ withBorder className={`${isSubmit ? classes.isDisabled : ""}`} style={{ + paddingLeft: 0, + paddingRight: 0, + width: "65px", position: "relative", - width: "80px", cursor: "pointer", textAlign: "center", border: listOutletSelected.find( @@ -303,7 +314,7 @@ export const DrawerAPCControl: React.FC = ({ display: "flex", justifyContent: "left", marginTop: "10px", - marginBottom: "10px", + // marginBottom: "10px", gap: "20px", }} > @@ -526,8 +537,10 @@ export const DrawerAPCControl: React.FC = ({ withBorder className={`${isSubmit ? classes.isDisabled : ""}`} style={{ + paddingLeft: 0, + paddingRight: 0, + width: "65px", position: "relative", - width: "80px", cursor: "pointer", textAlign: "center", border: listOutletSelected.find( @@ -559,7 +572,7 @@ export const DrawerAPCControl: React.FC = ({ display: "flex", justifyContent: "left", marginTop: "10px", - marginBottom: "10px", + // marginBottom: "10px", gap: "20px", }} > @@ -916,7 +929,6 @@ export const DrawerSwitchControl: React.FC = ({ ? "Deselect All" : "Select All" } - // mt={'xs'} miw={"80px"} size="xs" fz={"xs"} @@ -1105,45 +1117,139 @@ export const DrawerSwitchControl: React.FC = ({ - + {listPorts?.length > 0 && ( - {listPorts?.map((group, key) => ( - 20 - ? 11 - : group?.length > 0 && group?.length < 4 - ? 1 - : 12 - } - > -
{ + const isMini = group?.length > 0 && group?.length < 4; + const isLarge = group?.length > 20; + return ( + - - - {group[0]?.name.substring(0, 2) || ""} - - - - {group?.length > 0 && - sortedPorts(group)?.map((port, i) => ( + {isLarge ? ( + + + {sortedPorts(group) + .slice(0, sortedPorts(group).length / 2) + ?.map((port, i) => ( + el.name === port.name + )?.name + ? "1px solid #0018ff" + : "", + }} + className={`${ + isSubmit ? classes.isDisabled : "" + }`} + onClick={() => { + toggleSelect(port); + }} + > + + + {port.name} + + + + ))} + + + {sortedPorts(group) + .slice( + sortedPorts(group).length / 2, + sortedPorts(group).length + ) + ?.map((port, i) => ( + el.name === port.name + )?.name + ? "1px solid #0018ff" + : "", + }} + className={`${ + isSubmit ? classes.isDisabled : "" + }`} + onClick={() => { + toggleSelect(port); + }} + > + + + {port.name} + + + + ))} + + + ) : ( + + {sortedPorts(group)?.map((port, i) => ( = ({ withBorder style={{ position: "relative", - width: "60px", + width: "50px", backgroundColor: port.poe === "ON" ? "#f2dcf8" @@ -1180,7 +1286,7 @@ export const DrawerSwitchControl: React.FC = ({ flexWrap: "wrap", }} > - = ({ ? "#40c057" : "#b8b8b8" } - /> + /> */} {port.name} ))} - -
-
- ))} +
+ )} +
+ ); + })} )}