Update modal Scenario

This commit is contained in:
nguyentrungthat 2025-12-15 17:10:50 +07:00
parent 5a8cf4b999
commit 2729feed4e
7 changed files with 915 additions and 630 deletions

View File

@ -4,7 +4,8 @@ import type { HttpContext } from '@adonisjs/core/http'
export default class BrandsController {
// GET /models
async index({}: HttpContext) {
return await Brand.all()
const brands = await Brand.all()
return brands.sort((a, b) => a.id - b.id)
}
// POST /models

View File

@ -4,7 +4,8 @@ import type { HttpContext } from '@adonisjs/core/http'
export default class CategoriesController {
// GET /models
async index({}: HttpContext) {
return await Category.all()
const categories = await Category.all()
return categories.sort((a, b) => a.id - b.id)
}
// POST /models

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,14 @@ import {
} from "@mantine/core";
import { useEffect, useMemo, useRef, useState } from "react";
import classes from "./Component.module.css";
import type { IScenario, TLine, TStation, TUser } from "../untils/types";
import type {
IScenario,
TBrands,
TCategories,
TLine,
TStation,
TUser,
} from "../untils/types";
import type { Socket } from "socket.io-client";
import { ButtonDPELP, ButtonSelect } from "./ButtonAction";
import DrawerLogs from "./Drawer/DrawerLogs";
@ -47,6 +54,8 @@ interface TabsProps {
activeTabBottom: string;
setActiveTabBottom: (value: React.SetStateAction<string>) => void;
isExpand: boolean;
listBrands: TBrands[];
listCategories: TCategories[];
}
// Component cho từng Scenario Card
@ -379,6 +388,8 @@ const BottomToolBar = ({
activeTabBottom,
isExpand,
stationId,
listBrands,
listCategories,
}: TabsProps) => {
const user = useMemo(() => {
return localStorage.getItem("user") &&
@ -1067,6 +1078,8 @@ const BottomToolBar = ({
setScenarios={setScenarios}
externalOpened={openDrawerScenario}
onExternalClose={() => setOpenDrawerScenario(false)}
listBrands={listBrands}
listCategories={listCategories}
/>
</>
);

View File

@ -37,7 +37,13 @@ import {
IconUsersGroup,
} from "@tabler/icons-react";
import classes from "./Component.module.css";
import type { IScenario, TStation, TUser } from "../untils/types";
import type {
IScenario,
TBrands,
TCategories,
TStation,
TUser,
} from "../untils/types";
import type { Socket } from "socket.io-client";
import ModalHistory from "./Modal/ModalHistory";
import ModalConfig from "./Modal/ModalConfig";
@ -60,6 +66,8 @@ interface DraggableTabsProps {
onSendCommand: (value: string) => void;
scenarios: IScenario[];
setScenarios: (value: React.SetStateAction<IScenario[]>) => void;
listBrands: TBrands[];
listCategories: TCategories[];
}
function SortableTab({
@ -123,6 +131,8 @@ export default function DraggableTabs({
setActive,
scenarios,
setScenarios,
listBrands,
listCategories,
}: DraggableTabsProps) {
const user = useMemo(() => {
return localStorage.getItem("user") &&
@ -396,6 +406,8 @@ export default function DraggableTabs({
setScenarios={setScenarios}
externalOpened={openDrawerScenario}
onExternalClose={() => setOpenDrawerScenario(false)}
listBrands={listBrands}
listCategories={listCategories}
/>
</DndContext>
);

View File

@ -10,15 +10,23 @@ import {
Flex,
CloseButton,
Checkbox,
Select,
TagsInput,
} from "@mantine/core";
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 type {
IBodyScenario,
IScenario,
TBrands,
TCategories,
} from "../../untils/types";
import axios from "axios";
import { notifications } from "@mantine/notifications";
import { isJsonString } from "../../untils/helper";
const apiUrl = import.meta.env.VITE_BACKEND_URL;
function ModalScenario({
@ -26,11 +34,15 @@ function ModalScenario({
setScenarios,
externalOpened,
onExternalClose,
listBrands,
listCategories,
}: {
scenarios: IScenario[];
setScenarios: (value: React.SetStateAction<IScenario[]>) => void;
externalOpened?: boolean;
onExternalClose?: () => void;
listBrands: TBrands[];
listCategories: TCategories[];
}) {
const [opened, { close }] = useDisclosure(false);
@ -60,9 +72,13 @@ function ModalScenario({
repeat: "1",
},
] as IBodyScenario[],
timeout: "30000",
timeout: "30",
isReboot: false,
send_result: false,
note: "",
series: [] as string[],
brandId: "",
categoryId: "",
},
validate: {
title: (value) => {
@ -129,6 +145,10 @@ function ModalScenario({
send_result: form.values.send_result,
body: body,
timeout: Number(form.values.timeout),
categoryId: Number(form.values.categoryId),
brandId: Number(form.values.brandId),
note: form.values.note,
series: form.values.series,
};
const url = isEdit ? "api/scenarios/update" : "api/scenarios/create";
const res = await axios.post(
@ -219,7 +239,7 @@ function ModalScenario({
right: 0,
bottom: 0,
backgroundColor: "rgba(0,0,0,0.6)",
zIndex: 100000,
zIndex: 100,
display: "flex",
alignItems: "center",
justifyContent: "center",
@ -248,13 +268,13 @@ function ModalScenario({
<Flex
justify="space-between"
align="center"
p="lg"
p="sm"
style={{
borderBottom: "1px solid #e9ecef",
flexShrink: 0,
}}
>
<Text fw={700} size="xl">
<Text fw={700} size="md">
{isEdit ? "✏️ Edit Scenarios" : " Add Scenarios"}
</Text>
<CloseButton size="lg" onClick={handleClose} />
@ -319,6 +339,25 @@ function ModalScenario({
"send_result",
scenario.send_result
);
form.setFieldValue("note", scenario.note);
form.setFieldValue(
"brandId",
scenario.brand_id
? scenario.brand_id.toString()
: scenario?.brandId?.toString()
);
form.setFieldValue(
"categoryId",
scenario.category_id
? scenario.category_id.toString()
: scenario.categoryId.toString()
);
form.setFieldValue(
"series",
isJsonString(scenario?.series)
? JSON.parse(scenario.series)
: []
);
}
}}
>
@ -425,6 +464,60 @@ function ModalScenario({
</Grid.Col>
</Grid>
</Box>
<Box>
<Grid>
<Grid.Col span={2}>
<Select
label="Brand"
placeholder="Select Brand"
data={listBrands?.map((el) => ({
value: el.id.toString(),
label: el.name,
}))}
value={form.values.brandId || null}
onChange={(value) =>
form.setFieldValue("brandId", value || "")
}
/>
</Grid.Col>
<Grid.Col span={2}>
<Select
label="Category"
placeholder="Select Category"
data={listCategories?.map((el) => ({
value: el.id.toString(),
label: el.name,
}))}
value={form.values.categoryId || null}
onChange={(value) =>
form.setFieldValue("categoryId", value || "")
}
/>
</Grid.Col>
<Grid.Col span={2}>
<TextInput
label="Note"
placeholder="Input note"
value={form.values.note}
onChange={(e) =>
form.setFieldValue("note", e.target.value)
}
required
/>
</Grid.Col>
<Grid.Col span={6}>
<TagsInput
label="Series"
placeholder="Enter Series"
data={[]}
value={form.values.series || []}
onChange={(value: string[]) =>
form.setFieldValue("series", value)
}
/>
</Grid.Col>
</Grid>
</Box>
<hr style={{ width: "100%" }} />
<Box>
<ScrollArea

View File

@ -165,6 +165,12 @@ export type IScenario = {
isReboot: boolean;
is_reboot: boolean;
send_result: boolean;
brandId: number;
brand_id?: number;
categoryId: number;
category_id?: number;
note: string;
series: string;
updated_at: string;
};
@ -241,3 +247,12 @@ export type TextTSMLicense = {
LICENSE_COUNT: string;
LICENSE_PRIORITY: string;
};
export type TBrands = {
id: number;
name: string;
};
export type TCategories = {
id: number;
name: string;
};