Refactor BottomToolBar and update user types
Improved BottomToolBar command line UI with better line selection and clearing logic. Updated TUser type to include 'id' and 'email' fields, and fixed DragTabs to support both 'userId' and 'id' for user key mapping.
This commit is contained in:
parent
b5bb90ca4e
commit
1b9b18ce3b
|
|
@ -14,7 +14,7 @@ import {
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { useEffect, useMemo, useRef, useState } from "react";
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import classes from "./Component.module.css";
|
import classes from "./Component.module.css";
|
||||||
import type { IScenario, TLine, TStation } from "../untils/types";
|
import type { IScenario, TLine, TStation, TUser } from "../untils/types";
|
||||||
import type { Socket } from "socket.io-client";
|
import type { Socket } from "socket.io-client";
|
||||||
import { ButtonDPELP, ButtonSelect } from "./ButtonAction";
|
import { ButtonDPELP, ButtonSelect } from "./ButtonAction";
|
||||||
import DrawerLogs from "./DrawerLogs";
|
import DrawerLogs from "./DrawerLogs";
|
||||||
|
|
@ -22,7 +22,12 @@ import { DrawerAPCControl, DrawerSwitchControl } from "./DrawerControl";
|
||||||
import DrawerScenario from "./DrawerScenario";
|
import DrawerScenario from "./DrawerScenario";
|
||||||
import { isJsonString } from "../untils/helper";
|
import { isJsonString } from "../untils/helper";
|
||||||
import { motion } from "motion/react";
|
import { motion } from "motion/react";
|
||||||
import { IconCaretDown, IconCaretUp, IconPlayerPlay, IconPlus } from "@tabler/icons-react";
|
import {
|
||||||
|
IconCaretDown,
|
||||||
|
IconCaretUp,
|
||||||
|
IconPlayerPlay,
|
||||||
|
IconPlus,
|
||||||
|
} from "@tabler/icons-react";
|
||||||
|
|
||||||
interface TabsProps {
|
interface TabsProps {
|
||||||
selectedLines: TLine[];
|
selectedLines: TLine[];
|
||||||
|
|
@ -58,7 +63,7 @@ const ScenarioCard = ({
|
||||||
index: number;
|
index: number;
|
||||||
isDisable: boolean;
|
isDisable: boolean;
|
||||||
selectedLines: TLine[];
|
selectedLines: TLine[];
|
||||||
user: any;
|
user: TUser;
|
||||||
socket: Socket | null;
|
socket: Socket | null;
|
||||||
setOpenScenarioModal: (value: boolean) => void;
|
setOpenScenarioModal: (value: boolean) => void;
|
||||||
setIsDisable: (value: boolean) => void;
|
setIsDisable: (value: boolean) => void;
|
||||||
|
|
@ -138,10 +143,7 @@ const ScenarioCard = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid.Col key={scenario.id} span={3}>
|
<Grid.Col key={scenario.id} span={3}>
|
||||||
<div
|
<div ref={cardRef} style={{ position: "relative" }}>
|
||||||
ref={cardRef}
|
|
||||||
style={{ position: "relative" }}
|
|
||||||
>
|
|
||||||
<Card
|
<Card
|
||||||
shadow="sm"
|
shadow="sm"
|
||||||
padding="md"
|
padding="md"
|
||||||
|
|
@ -178,7 +180,8 @@ const ScenarioCard = ({
|
||||||
isDisable ||
|
isDisable ||
|
||||||
selectedLines.filter(
|
selectedLines.filter(
|
||||||
(el) =>
|
(el) =>
|
||||||
!el?.userEmailOpenCLI || el?.userEmailOpenCLI === user?.email
|
!el?.userEmailOpenCLI ||
|
||||||
|
el?.userEmailOpenCLI === user?.email
|
||||||
).length === 0
|
).length === 0
|
||||||
}
|
}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
@ -270,9 +273,7 @@ const ScenarioCard = ({
|
||||||
overflow: "auto",
|
overflow: "auto",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{steps
|
{steps.slice(0, 5).map((step: { send: string }, i: number) => (
|
||||||
.slice(0, 5)
|
|
||||||
.map((step: { send: string }, i: number) => (
|
|
||||||
<Text
|
<Text
|
||||||
key={i}
|
key={i}
|
||||||
size="xs"
|
size="xs"
|
||||||
|
|
@ -420,7 +421,11 @@ const BottomToolBar = ({
|
||||||
{scenarios.length > 0 ? (
|
{scenarios.length > 0 ? (
|
||||||
<Grid
|
<Grid
|
||||||
gutter="md"
|
gutter="md"
|
||||||
style={{ margin: 0, overflow: "visible", position: "relative" }}
|
style={{
|
||||||
|
margin: 0,
|
||||||
|
overflow: "visible",
|
||||||
|
position: "relative",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{scenarios.map((scenario, index) => (
|
{scenarios.map((scenario, index) => (
|
||||||
<ScenarioCard
|
<ScenarioCard
|
||||||
|
|
@ -524,7 +529,8 @@ const BottomToolBar = ({
|
||||||
</Tabs.Tab>
|
</Tabs.Tab>
|
||||||
<Tabs.Tab
|
<Tabs.Tab
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: activeTabBottom === "apc" ? "#c8d9fd" : "",
|
backgroundColor:
|
||||||
|
activeTabBottom === "apc" ? "#c8d9fd" : "",
|
||||||
fontSize: "13px",
|
fontSize: "13px",
|
||||||
paddingTop: "8px",
|
paddingTop: "8px",
|
||||||
paddingBottom: "8px",
|
paddingBottom: "8px",
|
||||||
|
|
@ -549,24 +555,33 @@ const BottomToolBar = ({
|
||||||
|
|
||||||
<Tabs.Panel value="command" p={"xs"}>
|
<Tabs.Panel value="command" p={"xs"}>
|
||||||
<Flex justify={"space-between"}>
|
<Flex justify={"space-between"}>
|
||||||
<ScrollArea h={"15vh"}>
|
<Box>
|
||||||
<Flex wrap={"wrap"} gap={"xs"} w={"400px"}>
|
<ScrollArea h={"12vh"}>
|
||||||
|
<Flex wrap={"wrap"} gap={"8px"} w={"420px"}>
|
||||||
{selectedLines.map((el) => (
|
{selectedLines.map((el) => (
|
||||||
<Box
|
<Box
|
||||||
key={el.id}
|
key={el.id}
|
||||||
style={{
|
style={{
|
||||||
paddingLeft: "4px",
|
position: "relative",
|
||||||
height: "30px",
|
padding: "4px 6px",
|
||||||
width: "80px",
|
height: "26px",
|
||||||
|
width: "60px",
|
||||||
backgroundColor: "#d4e3ff",
|
backgroundColor: "#d4e3ff",
|
||||||
borderRadius: "8px",
|
borderRadius: "8px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Flex align={"center"} justify={"center"} gap={"4px"}>
|
{/* Close button góc trên phải */}
|
||||||
<Text fz={"12px"}>Line {el.lineNumber}</Text>
|
|
||||||
<CloseButton
|
<CloseButton
|
||||||
style={{ minWidth: "24px" }}
|
size="xs"
|
||||||
aria-label="Clear input"
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
top: "-4px",
|
||||||
|
right: "-6px",
|
||||||
|
minWidth: "18px",
|
||||||
|
width: "18px",
|
||||||
|
height: "18px",
|
||||||
|
zIndex: 10,
|
||||||
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedLines(
|
setSelectedLines(
|
||||||
selectedLines.filter(
|
selectedLines.filter(
|
||||||
|
|
@ -579,11 +594,44 @@ const BottomToolBar = ({
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Flex
|
||||||
|
align={"center"}
|
||||||
|
justify={"center"}
|
||||||
|
h="100%"
|
||||||
|
>
|
||||||
|
<Text fz={"11px"}>Line {el.lineNumber}</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
))}
|
))}
|
||||||
</Flex>
|
</Flex>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
|
{selectedLines?.length > 0 ? (
|
||||||
|
<Button
|
||||||
|
fw={400}
|
||||||
|
className={classes.buttonControl}
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => {
|
||||||
|
const lines = station.lines.filter(
|
||||||
|
(line) =>
|
||||||
|
!line?.userOpenCLI ||
|
||||||
|
line?.userOpenCLI === user?.userName
|
||||||
|
);
|
||||||
|
lines.forEach((line) => {
|
||||||
|
socket?.emit("close_cli", {
|
||||||
|
lineId: line?.id,
|
||||||
|
stationId: line.stationId || line.station_id,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
setSelectedLines([]);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Clear
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
<Box pl={"md"} pr={"md"}>
|
<Box pl={"md"} pr={"md"}>
|
||||||
<Flex justify={"space-between"} mb={"xs"}>
|
<Flex justify={"space-between"} mb={"xs"}>
|
||||||
<Flex></Flex>
|
<Flex></Flex>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import {
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
Avatar,
|
Avatar,
|
||||||
Box,
|
Box,
|
||||||
Button,
|
|
||||||
Flex,
|
Flex,
|
||||||
Group,
|
Group,
|
||||||
Menu,
|
Menu,
|
||||||
|
|
@ -296,7 +295,7 @@ export default function DraggableTabs({
|
||||||
<Tooltip
|
<Tooltip
|
||||||
withArrow
|
withArrow
|
||||||
label={usersConnecting.map((el) => (
|
label={usersConnecting.map((el) => (
|
||||||
<Text key={el.userId}>{el.userName}</Text>
|
<Text key={el.userId || el.id}>{el.userName}</Text>
|
||||||
))}
|
))}
|
||||||
>
|
>
|
||||||
<Avatar radius="xl" me={"sm"}>
|
<Avatar radius="xl" me={"sm"}>
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,8 @@ export type TLine = {
|
||||||
export type TUser = {
|
export type TUser = {
|
||||||
userId: number;
|
userId: number;
|
||||||
userName: string;
|
userName: string;
|
||||||
|
id: number;
|
||||||
|
email: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type APCProps = {
|
export type APCProps = {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue