Fix giao diện tollbar

This commit is contained in:
Truong Vo 2025-12-15 11:10:11 +07:00
parent a37e647674
commit ae09fe1917
4 changed files with 224 additions and 60 deletions

View File

@ -458,7 +458,8 @@ function App() {
borderRadius: 8, borderRadius: 8,
}}> }}>
<ScrollArea <ScrollArea
h={expandedBottomBar ? "80vh" : "85vh"} // h={expandedBottomBar ? "80vh" : "85vh"}
h={expandedBottomBar ? "73vh" : "83vh"}
type="scroll" type="scroll"
scrollbars="y" scrollbars="y"
style={{ overflowX: "hidden" }} style={{ overflowX: "hidden" }}

View File

@ -352,7 +352,7 @@ const BottomToolBar = ({
<motion.div <motion.div
initial={false} initial={false}
animate={{ animate={{
height: isExpand ? "150px" : 0, height: isExpand ? "150px" : "60px",
y: 0, y: 0,
}} }}
transition={{ type: "spring", stiffness: 180, damping: 20 }} transition={{ type: "spring", stiffness: 180, damping: 20 }}
@ -362,18 +362,19 @@ const BottomToolBar = ({
bottom: 0, bottom: 0,
left: 0, left: 0,
zIndex: 1, zIndex: 1,
overflow: "hidden", overflow: "visible",
}} }}
> >
<Box style={{ position: "relative", height: isExpand ? "150px" : "0px" }}> {/* ActionIcon đặt bên ngoài Box để không bị overflow: hidden cắt */}
<ActionIcon <ActionIcon
style={{ style={{
position: "absolute", position: "absolute",
top: isExpand ? -4 : -24, top: isExpand ? "-4px" : "-30px",
left: "50%", left: "50%",
translate: "-19px 0", transform: "translateX(-50%)",
backgroundColor: "#e3e0e0", backgroundColor: "#e3e0e0",
width: "55px", width: "55px",
height: "30px",
zIndex: 10, zIndex: 10,
}} }}
variant="light" variant="light"
@ -382,14 +383,15 @@ const BottomToolBar = ({
}} }}
> >
{isExpand ? ( {isExpand ? (
<IconCaretDown color="green" /> <IconCaretDown color="green" size={20} />
) : ( ) : (
<IconCaretUp color="green" /> <IconCaretUp color="green" size={20} />
)} )}
</ActionIcon> </ActionIcon>
<Box style={{ position: "relative", height: isExpand ? "150px" : "60px", overflow: "hidden" }}>
<Grid style={{ height: "100%" }}> <Grid style={{ height: "100%" }}>
<Grid.Col span={isExpand ? 1 : 3.5}></Grid.Col> <Grid.Col span={isExpand ? 1 : 2}></Grid.Col>
<Grid.Col span={isExpand ? 10 : 5}> <Grid.Col span={isExpand ? 10 : 8 }>
{isExpand ? ( {isExpand ? (
<Tabs <Tabs
defaultValue="command" defaultValue="command"
@ -399,7 +401,7 @@ const BottomToolBar = ({
setActiveTabBottom(val || "command"); setActiveTabBottom(val || "command");
}} }}
className={classes.containerBottom} className={classes.containerBottom}
style={{ height: "100%" }} style={{ height: "100%",backgroundColor: "white", }}
> >
<Tabs.List> <Tabs.List>
<Tabs.Tab <Tabs.Tab
@ -443,11 +445,11 @@ const BottomToolBar = ({
<Tabs.Panel <Tabs.Panel
value="command" value="command"
p={4} p={4}
style={{ height: "100%", overflow: "auto" }} style={{ height: "200px", overflow: "auto" }}
> >
<Flex justify={"space-between"} align="flex-start"> <Flex justify={"space-between"} align="flex-start">
<Box> <Box>
<ScrollArea h={"8vh"}> <ScrollArea h={"11vh"}>
<Flex wrap={"wrap"} gap={"8px"} w={"420px"}> <Flex wrap={"wrap"} gap={"8px"} w={"420px"}>
{selectedLines.map((el) => ( {selectedLines.map((el) => (
<Box <Box
@ -692,9 +694,17 @@ const BottomToolBar = ({
</Tabs> </Tabs>
) : ( ) : (
<Box p={3} > <Box p={3} >
<Flex direction="column" gap="xs"> <Flex direction="row" align="center" gap="xs" wrap="nowrap" style={{ height: "100%" }}>
<Flex justify={"space-between"} align={"center"} wrap="wrap" gap="xs"> {/* Danh sách Line - chiếm 1 phần, cố định width và height, hiển thị 2 hàng */}
<Flex wrap={"wrap"} gap={"6px"} style={{ flex: 1, minWidth: 0 }}> <Box
style={{
flex: "1 1 0",
width: "100%",
height: "50px",
overflow: "auto",
}}
>
<Flex wrap={"wrap"} gap={"6px"} style={{ height: "100%" }}>
{selectedLines.map((el) => ( {selectedLines.map((el) => (
<Box <Box
key={el.id} key={el.id}
@ -705,6 +715,7 @@ const BottomToolBar = ({
width: "55px", width: "55px",
backgroundColor: "#d4e3ff", backgroundColor: "#d4e3ff",
borderRadius: "6px", borderRadius: "6px",
flexShrink: 0,
}} }}
> >
<CloseButton <CloseButton
@ -749,6 +760,7 @@ const BottomToolBar = ({
cursor: "pointer", cursor: "pointer",
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
flexShrink: 0,
}} }}
onClick={() => { onClick={() => {
selectedLines.forEach((line) => { selectedLines.forEach((line) => {
@ -767,11 +779,39 @@ const BottomToolBar = ({
</Box> </Box>
)} )}
</Flex> </Flex>
<Flex align={"center"} gap="xs"> </Box>
{/* Selected count - ở giữa */}
<Flex align={"center"} style={{ flex: "0 0 auto", flexShrink: 0 }}>
<Text fz={"10px"} c="dark" fw={600}> <Text fz={"10px"} c="dark" fw={600}>
Selected: {selectedLines.length} /{" "} Selected: {selectedLines.length} /{" "}
{station.lines.length} {station.lines.length}
</Text> </Text>
</Flex>
{/* Input + Select All - chiếm 1 phần */}
<Flex
direction="row"
align="center"
gap="xs"
style={{
flex: "1 1 0",
minWidth: "200px",
overflow: "hidden",
}}
>
{/* Input */}
<Box style={{ flexGrow: 1.5, flexShrink: 1, flexBasis: "auto", maxWidth: "100%", overflow: "hidden" }}>
<InputHistory
selectedLines={selectedLines}
socket={socket}
station={station}
inputStyle={{ width: "100%" }}
/>
</Box>
{/* Select All */}
<Flex align={"center"} style={{ flex: "0 0 auto", flexShrink: 0 }}>
<ButtonSelect <ButtonSelect
selectedLines={selectedLines} selectedLines={selectedLines}
setSelectedLines={setSelectedLines} setSelectedLines={setSelectedLines}
@ -806,13 +846,6 @@ const BottomToolBar = ({
/> />
</Flex> </Flex>
</Flex> </Flex>
<Box style={{ width: "100%" }}>
<InputHistory
selectedLines={selectedLines}
socket={socket}
station={station}
/>
</Box>
</Flex> </Flex>
</Box> </Box>
)} )}
@ -822,6 +855,129 @@ const BottomToolBar = ({
</Box> </Box>
</motion.div> </motion.div>
{openScenarioModal && (
<div
style={{
position: "fixed",
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: "rgba(0,0,0,0.6)",
zIndex: 99998,
display: "flex",
alignItems: "center",
justifyContent: "center",
backdropFilter: "blur(3px)",
}}
onClick={() => setOpenScenarioModal(false)}
>
<div
style={{
background: "white",
borderRadius: "12px",
maxWidth: "90vw",
width: "90%",
height: "85vh",
display: "flex",
flexDirection: "column",
boxShadow: "0 20px 60px rgba(0,0,0,0.3)",
overflowY: "auto",
overflowX: "visible",
}}
onClick={(e) => e.stopPropagation()}
>
{/* Header */}
<Flex
justify="space-between"
align="center"
p="lg"
style={{
borderBottom: "1px solid #e9ecef",
flexShrink: 0,
}}
>
<Text fw={700} size="xl">
🎯 Select Scenario to Run
</Text>
<Flex gap="md" align="center">
<Button
leftSection={<IconPlus size={16} />}
variant="light"
color="green"
size="sm"
onClick={(e) => {
e.stopPropagation();
setOpenDrawerScenario(true);
}}
>
Add/Edit Scenario
</Button>
<CloseButton
size="lg"
onClick={() => setOpenScenarioModal(false)}
/>
</Flex>
</Flex>
{/* Content */}
<div
style={{
padding: "20px",
overflowY: "auto",
overflowX: "visible",
flex: 1,
position: "relative",
}}
className={classes.hideScrollBar}
>
{scenarios.length > 0 ? (
<Grid
gutter="md"
style={{
margin: 0,
overflow: "visible",
position: "relative",
}}
>
{scenarios.map((scenario, index) => (
<ScenarioCard
key={scenario.id}
scenario={scenario}
index={index}
isDisable={isDisable}
selectedLines={selectedLines}
user={user}
socket={socket}
setOpenScenarioModal={setOpenScenarioModal}
setIsDisable={setIsDisable}
/>
))}
</Grid>
) : (
<Flex
direction="column"
align="center"
justify="center"
style={{ minHeight: "300px" }}
gap="md"
>
<Text size="xl" c="dimmed">
📋
</Text>
<Text ta="center" c="dimmed" size="lg">
No scenarios available
</Text>
<Text ta="center" c="dimmed" size="sm">
Please create a new scenario to get started
</Text>
</Flex>
)}
</div>
</div>
</div>
)}
{/* Drawer Scenario để Add/Edit */} {/* Drawer Scenario để Add/Edit */}
<DrawerScenario <DrawerScenario
scenarios={scenarios} scenarios={scenarios}

View File

@ -1164,7 +1164,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
</div> </div>
</div> </div>
<Grid.Col span={12} pt={"4px"}> <Grid.Col span={12} pt={"0px"}>
{listPorts?.length > 0 && ( {listPorts?.length > 0 && (
<Box> <Box>
<Flex gap={"8px"} wrap={"wrap"}> <Flex gap={"8px"} wrap={"wrap"}>
@ -1217,6 +1217,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
style={{ style={{
flex: "0 0 auto", flex: "0 0 auto",
position: "relative", position: "relative",
justifyContent: "center",
width: "34px", width: "34px",
height: "28px", height: "28px",
backgroundColor: backgroundColor:
@ -1248,7 +1249,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
flexWrap: "wrap", flexWrap: "wrap",
}} }}
> >
<Text fw={500} fz={"9px"}> <Text fw={600} fz={"10px"}>
{normalizePortName(port.name)} {normalizePortName(port.name)}
</Text> </Text>
</Box> </Box>
@ -1288,8 +1289,9 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
style={{ style={{
flex: "0 0 auto", flex: "0 0 auto",
position: "relative", position: "relative",
width: "40px", justifyContent: "center",
height: "32px", width: "34px",
height: "28px",
backgroundColor: backgroundColor:
port.poe === "ON" port.poe === "ON"
? "#f2dcf8" ? "#f2dcf8"
@ -1319,7 +1321,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
flexWrap: "wrap", flexWrap: "wrap",
}} }}
> >
<Text fw={500} fz={"11px"}> <Text fw={600} fz={"10px"}>
{normalizePortName(port.name)} {normalizePortName(port.name)}
</Text> </Text>
</Box> </Box>
@ -1359,11 +1361,11 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
<Box <Box
style={{ style={{
width: "fit-content", width: "fit-content",
minWidth: "40px", minWidth: "32px",
minHeight: "56px", minHeight: "56px",
}} }}
> >
<Flex gap={"6px"} wrap={"nowrap"}> <Flex gap={"4px"} wrap={"nowrap"}>
{sortedPorts(group) {sortedPorts(group)
.slice( .slice(
0, 0,
@ -1382,8 +1384,9 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
style={{ style={{
flex: "0 0 auto", flex: "0 0 auto",
position: "relative", position: "relative",
width: "40px", justifyContent: "center",
height: "32px", width: "34px",
height: "28px",
backgroundColor: backgroundColor:
port.poe === "ON" port.poe === "ON"
? "#f2dcf8" ? "#f2dcf8"
@ -1413,7 +1416,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
flexWrap: "wrap", flexWrap: "wrap",
}} }}
> >
<Text fw={500} fz={"10px"}> <Text fw={600} fz={"10px"}>
{normalizePortName(port.name)} {normalizePortName(port.name)}
</Text> </Text>
</Box> </Box>
@ -1434,7 +1437,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
</Card> </Card>
))} ))}
</Flex> </Flex>
<Flex gap={"6px"} wrap={"nowrap"} mt={"6px"}> <Flex gap={"4px"} wrap={"nowrap"} mt={"4px"}>
{sortedPorts(group) {sortedPorts(group)
.slice( .slice(
Math.ceil(sortedPorts(group).length / 2), Math.ceil(sortedPorts(group).length / 2),
@ -1453,8 +1456,9 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
style={{ style={{
flex: "0 0 auto", flex: "0 0 auto",
position: "relative", position: "relative",
width: "50px", justifyContent: "center",
height: "40px", width: "34px",
height: "28px",
backgroundColor: backgroundColor:
port.poe === "ON" port.poe === "ON"
? "#f2dcf8" ? "#f2dcf8"
@ -1484,7 +1488,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
flexWrap: "wrap", flexWrap: "wrap",
}} }}
> >
<Text fw={500} fz={"11px"}> <Text fw={600} fz={"10px"}>
{normalizePortName(port.name)} {normalizePortName(port.name)}
</Text> </Text>
</Box> </Box>

View File

@ -10,10 +10,12 @@ export default function InputHistory({
selectedLines, selectedLines,
socket, socket,
station, station,
inputStyle,
}: { }: {
selectedLines: TLine[]; selectedLines: TLine[];
socket: Socket | null; socket: Socket | null;
station: TStation; station: TStation;
inputStyle?: React.CSSProperties;
}) { }) {
const [value, setValue] = useState(""); const [value, setValue] = useState("");
const [history, setHistory] = useState<string[]>([]); const [history, setHistory] = useState<string[]>([]);
@ -115,6 +117,7 @@ export default function InputHistory({
style={{ style={{
width: "30vw", width: "30vw",
boxShadow: "0px 0px 10px rgba(0, 0, 0, 0.1)", boxShadow: "0px 0px 10px rgba(0, 0, 0, 0.1)",
...inputStyle,
}} }}
placeholder={"Send command to port(s)"} placeholder={"Send command to port(s)"}
value={value} value={value}