add road patrol
This commit is contained in:
@@ -29,8 +29,24 @@ const validationSchema = object({
|
||||
item_id: number().required("نوع آیتم را مشخص کنید!"),
|
||||
sub_item_id: number().required("اقدام انجام شده را مشخص کنید!"),
|
||||
amount: string().required("وارد کردن مقدار الزامیست!"),
|
||||
cmms_machines: array().required("وارد کردن کد خودرو الزامیست!").min(1, "حداقل یک کد خودرو باید وارد شود!"),
|
||||
rahdaran_id: array().required("وارد کردن کد راهداران الزامیست!").min(1, "حداقل یک کد راهدار باید وارد شود!"), // بررسی حداقل یک آیتم,
|
||||
cmms_machines: array()
|
||||
.test("cmms-machines-conditional", "وارد کردن کد خودرو الزامیست!", function (value) {
|
||||
const { is_gasht } = this.options.context;
|
||||
if (is_gasht) {
|
||||
return true; // اگر is_gasht true باشد، این فیلد نیاز به اعتبارسنجی ندارد
|
||||
}
|
||||
return Array.isArray(value) && value.length > 0; // حداقل یک کد باید وجود داشته باشد
|
||||
})
|
||||
.min(1, "حداقل یک کد خودرو باید وارد شود!"), // پیام خطا برای زمانی که شرط تست برقرار باشد
|
||||
rahdaran_id: array()
|
||||
.test("rahdaran-id-conditional", "وارد کردن کد راهداران الزامیست!", function (value) {
|
||||
const { is_gasht } = this.options.context;
|
||||
if (is_gasht) {
|
||||
return true; // اگر is_gasht true باشد، این فیلد نیاز به اعتبارسنجی ندارد
|
||||
}
|
||||
return Array.isArray(value) && value.length > 0; // حداقل یک کد باید وجود داشته باشد
|
||||
})
|
||||
.min(1, "حداقل یک کد راهدار باید وارد شود!"), // پیام خطا برای زمانی که شرط تست برقرار باشد
|
||||
activity_time: string().test("activity-time-conditional", "لطفا زمان فعالیت را انتخاب کنید!", function (value) {
|
||||
const { is_gasht } = this.options.context; // دسترسی به context
|
||||
if (is_gasht) {
|
||||
@@ -91,11 +107,14 @@ const CreateFormContent = ({ setOpen, onSubmit, is_gasht = false }) => {
|
||||
amount: "",
|
||||
before_image: null,
|
||||
after_image: null,
|
||||
cmms_machines: null,
|
||||
rahdaran_id: null,
|
||||
start_point: "",
|
||||
end_point: "",
|
||||
...(!is_gasht && { activity_time: "", activity_date: "" }),
|
||||
...(!is_gasht && {
|
||||
activity_time: "",
|
||||
activity_date: "",
|
||||
cmms_machines: [],
|
||||
rahdaran_id: [],
|
||||
}),
|
||||
};
|
||||
|
||||
const [tabState, setTabState] = useState(0);
|
||||
@@ -175,17 +194,24 @@ const CreateFormContent = ({ setOpen, onSubmit, is_gasht = false }) => {
|
||||
result.start_point = `${result.start_point.lat},${result.start_point.lng}`;
|
||||
}
|
||||
|
||||
result.rahdaran_id.forEach((rahdar, index) => {
|
||||
result[`rahdaran_id[${index}]`] = rahdar.id;
|
||||
});
|
||||
delete result.rahdaran_id;
|
||||
if (!is_gasht) {
|
||||
result.rahdaran_id.forEach((rahdar, index) => {
|
||||
result[`rahdaran_id[${index}]`] = rahdar.id;
|
||||
});
|
||||
delete result.rahdaran_id;
|
||||
|
||||
result.cmms_machines.forEach((cmms_machine, index) => {
|
||||
result[`machines_id[${index}]`] = cmms_machine.id;
|
||||
});
|
||||
delete result.cmms_machines;
|
||||
result.cmms_machines.forEach((cmms_machine, index) => {
|
||||
result[`machines_id[${index}]`] = cmms_machine.id;
|
||||
});
|
||||
delete result.cmms_machines;
|
||||
|
||||
result[`activity_time`] = format(new Date(result.activity_time), "HH:mm");
|
||||
result[`activity_time`] = format(new Date(result.activity_time), "HH:mm");
|
||||
} else {
|
||||
delete result.rahdaran_id;
|
||||
delete result.cmms_machines;
|
||||
delete result.activity_date;
|
||||
delete result.activity_time;
|
||||
}
|
||||
|
||||
await onSubmit({
|
||||
result,
|
||||
|
||||
@@ -43,37 +43,41 @@ const GetItemInfo = ({ register, itemsList, subItemsList, control, setValue, err
|
||||
fullWidth
|
||||
/>
|
||||
</Stack>
|
||||
<Stack>
|
||||
<Controller
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
return (
|
||||
<CarCode
|
||||
carCode={field.value || []}
|
||||
setCarCode={(value) => field.onChange(value || [])}
|
||||
error={error}
|
||||
multiple={true}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
name={"cmms_machines"}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack>
|
||||
<Controller
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
return (
|
||||
<RahdarCode
|
||||
rahdarsCode={field.value || []}
|
||||
setRahdarsCode={(value) => field.onChange(value || [])}
|
||||
error={error}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
name={"rahdaran_id"}
|
||||
/>
|
||||
</Stack>
|
||||
{!is_gasht && (
|
||||
<Stack>
|
||||
<Controller
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
return (
|
||||
<CarCode
|
||||
carCode={field.value || []}
|
||||
setCarCode={(value) => field.onChange(value || [])}
|
||||
error={error}
|
||||
multiple={true}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
name={"cmms_machines"}
|
||||
/>
|
||||
</Stack>
|
||||
)}
|
||||
{!is_gasht && (
|
||||
<Stack>
|
||||
<Controller
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
return (
|
||||
<RahdarCode
|
||||
rahdarsCode={field.value || []}
|
||||
setRahdarsCode={(value) => field.onChange(value || [])}
|
||||
error={error}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
name={"rahdaran_id"}
|
||||
/>
|
||||
</Stack>
|
||||
)}
|
||||
<Stack>
|
||||
{subItemsList.needs_image ? (
|
||||
<ImageUpload setValue={setValue} control={control} errors={errors} getValues={getValues} />
|
||||
|
||||
@@ -18,11 +18,13 @@ const OperatorCreateForm = ({ open, setOpen, mutate, rowId }) => {
|
||||
mutate();
|
||||
setOpen(false);
|
||||
})
|
||||
.catch((error) => {});
|
||||
.catch((error) => { });
|
||||
};
|
||||
return (
|
||||
<Dialog open={open} fullWidth maxWidth="sm">
|
||||
<CreateFormContent setOpen={setOpen} mutate={mutate} onSubmit={HandleSubmit} />
|
||||
{open && (
|
||||
<CreateFormContent setOpen={setOpen} mutate={mutate} onSubmit={HandleSubmit} />
|
||||
)}
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -31,7 +31,7 @@ const OperatorCreate = ({ mutate }) => {
|
||||
ثبت فعالیت
|
||||
</Button>
|
||||
)}
|
||||
{open && <OperatorCreateForm open={open} setOpen={setOpen} mutate={mutate} />}
|
||||
<OperatorCreateForm open={open} setOpen={setOpen} mutate={mutate} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -6,7 +6,9 @@ const GashtCreate = ({ open, setOpen, mutate, rowId }) => {
|
||||
const [tabState, setTabState] = useState(0);
|
||||
return (
|
||||
<Dialog open={open} fullWidth maxWidth={tabState === 0 ? "md" : "sm"}>
|
||||
<GashtCreateContent mutate={mutate} setOpen={setOpen} setTabState={setTabState} tabState={tabState} />
|
||||
{open && (
|
||||
<GashtCreateContent mutate={mutate} setOpen={setOpen} setTabState={setTabState} tabState={tabState} />
|
||||
)}
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -35,7 +35,7 @@ const ObservedGashtCreate = ({ mutate }) => {
|
||||
ثبت فعالیت برای موارد مشاهده شده در گشت راهداری
|
||||
</Button>
|
||||
)}
|
||||
{open && <GashtCreate open={open} setOpen={setOpen} mutate={mutate} />}
|
||||
<GashtCreate open={open} setOpen={setOpen} mutate={mutate} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@ import React from "react";
|
||||
import useRoadItemGetISubtems from "@/lib/hooks/useRoadItemGetISubtems";
|
||||
import EditFormCreate from "@/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormCreate";
|
||||
|
||||
const EditFormContent = ({ setOpenEditDialog, onSubmit, defaultData }) => {
|
||||
const EditFormContent = ({ setOpenEditDialog, onSubmit, defaultData, is_gasht }) => {
|
||||
const { subItemsList, loadingSubItemsList, errorSubItemsList } = useRoadItemGetISubtems(defaultData?.item_id);
|
||||
const subItem = subItemsList.find((SubItem) => SubItem.sub_item === defaultData?.sub_item_id);
|
||||
|
||||
@@ -13,8 +13,10 @@ const EditFormContent = ({ setOpenEditDialog, onSubmit, defaultData }) => {
|
||||
amount: defaultData?.amount || null,
|
||||
start_point: defaultData?.start_point || { lat: "", lng: "" },
|
||||
end_point: defaultData?.end_point || { lat: "", lng: "" },
|
||||
cmms_machines: defaultData?.cmms_machines || null,
|
||||
rahdaran_id: defaultData?.rahdaran_id || null,
|
||||
...(!is_gasht && {
|
||||
cmms_machines: defaultData?.cmms_machines || null,
|
||||
rahdaran_id: defaultData?.rahdaran_id || null,
|
||||
}),
|
||||
};
|
||||
|
||||
const onSubmitBase = async (data) => {
|
||||
@@ -43,15 +45,20 @@ const EditFormContent = ({ setOpenEditDialog, onSubmit, defaultData }) => {
|
||||
result.start_point = `${result.start_point.lat},${result.start_point.lng}`;
|
||||
}
|
||||
|
||||
result.rahdaran_id.forEach((rahdar, index) => {
|
||||
result[`rahdaran_id[${index}]`] = rahdar.id;
|
||||
});
|
||||
delete result.rahdaran_id;
|
||||
if (!is_gasht) {
|
||||
result.rahdaran_id.forEach((rahdar, index) => {
|
||||
result[`rahdaran_id[${index}]`] = rahdar.id;
|
||||
});
|
||||
delete result.rahdaran_id;
|
||||
|
||||
result.cmms_machines.forEach((cmms_machine, index) => {
|
||||
result[`machines_id[${index}]`] = cmms_machine.id;
|
||||
});
|
||||
delete result.cmms_machines;
|
||||
result.cmms_machines.forEach((cmms_machine, index) => {
|
||||
result[`machines_id[${index}]`] = cmms_machine.id;
|
||||
});
|
||||
delete result.cmms_machines;
|
||||
} else {
|
||||
delete result.rahdaran_id;
|
||||
delete result.cmms_machines;
|
||||
}
|
||||
|
||||
await onSubmit({
|
||||
result,
|
||||
@@ -81,6 +88,7 @@ const EditFormContent = ({ setOpenEditDialog, onSubmit, defaultData }) => {
|
||||
defaultData={defaultData}
|
||||
defaultValues={defaultValues}
|
||||
setOpenEditDialog={setOpenEditDialog}
|
||||
is_gasht={is_gasht}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -13,8 +13,24 @@ import { array, mixed, object, string } from "yup";
|
||||
|
||||
const validationSchema = object({
|
||||
amount: string().required("وارد کردن مقدار الزامیست!"),
|
||||
cmms_machines: array().required("وارد کردن کد خودرو الزامیست!").min(1, "حداقل یک کد خودرو باید وارد شود!"),
|
||||
rahdaran_id: array().required("وارد کردن کد راهداران الزامیست!").min(1, "حداقل یک کد راهدار باید وارد شود!"),
|
||||
cmms_machines: array()
|
||||
.test("cmms-machines-conditional", "وارد کردن کد خودرو الزامیست!", function (value) {
|
||||
const { is_gasht } = this.options.context;
|
||||
if (is_gasht) {
|
||||
return true; // اگر is_gasht true باشد، این فیلد نیاز به اعتبارسنجی ندارد
|
||||
}
|
||||
return Array.isArray(value) && value.length > 0; // حداقل یک کد باید وجود داشته باشد
|
||||
})
|
||||
.min(1, "حداقل یک کد خودرو باید وارد شود!"), // پیام خطا برای زمانی که شرط تست برقرار باشد
|
||||
rahdaran_id: array()
|
||||
.test("rahdaran-id-conditional", "وارد کردن کد راهداران الزامیست!", function (value) {
|
||||
const { is_gasht } = this.options.context;
|
||||
if (is_gasht) {
|
||||
return true; // اگر is_gasht true باشد، این فیلد نیاز به اعتبارسنجی ندارد
|
||||
}
|
||||
return Array.isArray(value) && value.length > 0; // حداقل یک کد باید وجود داشته باشد
|
||||
})
|
||||
.min(1, "حداقل یک کد راهدار باید وارد شود!"),
|
||||
before_image: mixed()
|
||||
.nullable()
|
||||
.test("before-image-required", "لطفا عکس قبل از اقدام را بارگذاری کنید!", function (value) {
|
||||
@@ -50,7 +66,7 @@ const validationSchema = object({
|
||||
}),
|
||||
});
|
||||
|
||||
const EditFormCreate = ({ defaultData, subItem, onSubmitBase, defaultValues, setOpenEditDialog }) => {
|
||||
const EditFormCreate = ({ defaultData, subItem, onSubmitBase, defaultValues, setOpenEditDialog, is_gasht }) => {
|
||||
const {
|
||||
control,
|
||||
getValues,
|
||||
@@ -63,7 +79,7 @@ const EditFormCreate = ({ defaultData, subItem, onSubmitBase, defaultValues, set
|
||||
defaultValues,
|
||||
resolver: yupResolver(validationSchema),
|
||||
mode: "onBlur",
|
||||
context: { subItem },
|
||||
context: { subItem, is_gasht },
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -108,38 +124,42 @@ const EditFormCreate = ({ defaultData, subItem, onSubmitBase, defaultValues, set
|
||||
fullWidth
|
||||
/>
|
||||
</Stack>
|
||||
<Stack>
|
||||
<Controller
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
return (
|
||||
<CarCode
|
||||
carCode={field.value || []}
|
||||
setCarCode={(value) => field.onChange(value || [])}
|
||||
inputValueDefault={defaultData?.cmms_machines}
|
||||
multiple={true}
|
||||
error={error} // اگر خطا وجود داشته باشد
|
||||
/>
|
||||
);
|
||||
}}
|
||||
name={"cmms_machines"}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack>
|
||||
<Controller
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
return (
|
||||
<RahdarCode
|
||||
rahdarsCode={field.value || []}
|
||||
setRahdarsCode={(value) => field.onChange(value || [])}
|
||||
error={error}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
name={"rahdaran_id"}
|
||||
/>
|
||||
</Stack>
|
||||
{!is_gasht && (
|
||||
<Stack>
|
||||
<Controller
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
return (
|
||||
<CarCode
|
||||
carCode={field.value || []}
|
||||
setCarCode={(value) => field.onChange(value || [])}
|
||||
inputValueDefault={defaultData?.cmms_machines}
|
||||
multiple={true}
|
||||
error={error} // اگر خطا وجود داشته باشد
|
||||
/>
|
||||
);
|
||||
}}
|
||||
name={"cmms_machines"}
|
||||
/>
|
||||
</Stack>
|
||||
)}
|
||||
{!is_gasht && (
|
||||
<Stack>
|
||||
<Controller
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
return (
|
||||
<RahdarCode
|
||||
rahdarsCode={field.value || []}
|
||||
setRahdarsCode={(value) => field.onChange(value || [])}
|
||||
error={error}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
name={"rahdaran_id"}
|
||||
/>
|
||||
</Stack>
|
||||
)}
|
||||
<Stack>
|
||||
{subItem.needs_end_point === 1 ? (
|
||||
<MapInfoTwoMarker
|
||||
|
||||
@@ -26,7 +26,7 @@ const OperatorCreate = ({ mutate }) => {
|
||||
ثبت اقدام
|
||||
</Button>
|
||||
)}
|
||||
{open && <CreatePatrol open={open} setOpen={setOpen} mutate={mutate} />}
|
||||
<CreatePatrol open={open} setOpen={setOpen} mutate={mutate} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import dynamic from "next/dynamic";
|
||||
import MapLoading from "@/core/components/MapLayer/Loading";
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import DesignServicesIcon from "@mui/icons-material/DesignServices";
|
||||
import DirectionsCarIcon from "@mui/icons-material/DirectionsCar";
|
||||
import HandymanIcon from "@mui/icons-material/Handyman";
|
||||
import PersonIcon from "@mui/icons-material/Person";
|
||||
import {
|
||||
Box,
|
||||
Card,
|
||||
@@ -15,18 +17,8 @@ import {
|
||||
Stack,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import HandymanIcon from "@mui/icons-material/Handyman";
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import DirectionsCarIcon from "@mui/icons-material/DirectionsCar";
|
||||
import PersonIcon from "@mui/icons-material/Person";
|
||||
import DesignServicesIcon from "@mui/icons-material/DesignServices";
|
||||
import EditActionDuringPatrol from "./EditActionDuringPatrol";
|
||||
|
||||
const MapLayer = dynamic(() => import("@/core/components/MapLayer"), {
|
||||
loading: () => <MapLoading />,
|
||||
ssr: false,
|
||||
});
|
||||
|
||||
const ActionInfo = ({ action, setActionsList, index, deleteAction }) => {
|
||||
return (
|
||||
<Card sx={{ maxWidth: 300 }}>
|
||||
@@ -35,41 +27,6 @@ const ActionInfo = ({ action, setActionsList, index, deleteAction }) => {
|
||||
title={<Typography sx={{ fontSize: "14px", fontWeight: 500 }}>{action.data.item_name}</Typography>}
|
||||
subheader={action.data.sub_item_name}
|
||||
/>
|
||||
<CardContent>
|
||||
<Stack sx={{ gap: 1 }}>
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
|
||||
<DesignServicesIcon />
|
||||
<Typography variant="button">میزان فعالیت انجام شده:</Typography>
|
||||
<Typography variant="button">
|
||||
{action.data.amount}({action.data.unit_fa})
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box>
|
||||
<Divider sx={{ mb: 1 }}>
|
||||
<Chip size="small" label="خودرو ها" icon={<DirectionsCarIcon />} />
|
||||
</Divider>
|
||||
<Stack>
|
||||
{action.data.cmms_machines.map((cmms_machine, index) => (
|
||||
<Typography variant="button" key={index}>
|
||||
{index + 1}: {cmms_machine.car_name}
|
||||
</Typography>
|
||||
))}
|
||||
</Stack>
|
||||
</Box>
|
||||
<Box>
|
||||
<Divider sx={{ mb: 1 }}>
|
||||
<Chip size="small" label="راهداران" icon={<PersonIcon />} />
|
||||
</Divider>
|
||||
<Stack>
|
||||
{action.data.rahdaran_id.map((rahdar, index) => (
|
||||
<Typography variant="button" key={index}>
|
||||
{index + 1}: {rahdar.name}
|
||||
</Typography>
|
||||
))}
|
||||
</Stack>
|
||||
</Box>
|
||||
</Stack>
|
||||
</CardContent>
|
||||
<CardActions disableSpacing>
|
||||
<Box>
|
||||
<IconButton aria-label="حذف فعالیت" color="error" onClick={deleteAction}>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { Box, Button, Divider, Grid, Typography } from "@mui/material";
|
||||
import AddCircleIcon from "@mui/icons-material/AddCircle";
|
||||
import React, { useState } from "react";
|
||||
import ModalActionsDuringPatrol from "./ModalActionsDuringPatrol";
|
||||
import ExitToAppIcon from "@mui/icons-material/ExitToApp";
|
||||
import { Box, Button, Chip, DialogActions, DialogContent, Divider, Grid, Stack, Typography } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
import ActionInfo from "./ActionInfo";
|
||||
import KeyboardDoubleArrowLeftIcon from "@mui/icons-material/KeyboardDoubleArrowLeft";
|
||||
import ModalActionsDuringPatrol from "./ModalActionsDuringPatrol";
|
||||
|
||||
const ActionsDuringPatrol = ({ setValue, tabState, setTabState }) => {
|
||||
const [ActionsList, setActionsList] = useState([]);
|
||||
const ActionsDuringPatrol = ({ allData, setAllData, handlePrev, setTabState }) => {
|
||||
const [actionsList, setActionsList] = useState(allData.observed_items);
|
||||
const [open, setOpen] = useState(false);
|
||||
const handleOpen = () => {
|
||||
setOpen(true);
|
||||
@@ -18,71 +18,86 @@ const ActionsDuringPatrol = ({ setValue, tabState, setTabState }) => {
|
||||
setActionsList((prev) => prev.filter((_, index) => index !== indexToRemove));
|
||||
};
|
||||
|
||||
const SubmitActionDuringPatrol = () => {
|
||||
setTabState(tabState + 1);
|
||||
const resultItems = ActionsList.map((item) => item.result);
|
||||
setValue("observed_items", resultItems);
|
||||
const handleNext = (data) => {
|
||||
setAllData({ observed_items: data });
|
||||
setTabState(s => s + 1);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
|
||||
<Typography variant="h6">لیست اقدامات حین گشت</Typography>
|
||||
<Button
|
||||
onClick={handleOpen}
|
||||
startIcon={<AddCircleIcon />}
|
||||
variant="outlined"
|
||||
sx={{ mb: 1, alignSelf: "end" }}
|
||||
>
|
||||
ثبت اقدام
|
||||
</Button>
|
||||
<ModalActionsDuringPatrol open={open} setOpen={setOpen} setActionsList={setActionsList} />
|
||||
</Box>
|
||||
<Divider />
|
||||
{ActionsList.length !== 0 ? (
|
||||
<Grid
|
||||
container
|
||||
spacing={2}
|
||||
sx={{
|
||||
p: 1,
|
||||
mt: 1,
|
||||
maxHeight: "300px",
|
||||
overflowY: "auto",
|
||||
}}
|
||||
>
|
||||
{ActionsList.map((action, index) => (
|
||||
<Grid key={index} item xs={12} sm={6} lg={4}>
|
||||
<ActionInfo
|
||||
action={action}
|
||||
setActionsList={setActionsList}
|
||||
index={index}
|
||||
deleteAction={() => deleteAction(index)}
|
||||
/>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
) : (
|
||||
<Box sx={{ my: 5, width: "100%", textAlign: "center" }}>
|
||||
<Typography variant="h6" sx={{ letterSpacing: "2px", color: "#606060" }}>
|
||||
فعالیتی ثبت نکرده اید
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
<Box>
|
||||
<Box sx={{ display: "flex", gap: 1, justifyContent: "center" }}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={SubmitActionDuringPatrol}
|
||||
disabled={ActionsList === []}
|
||||
endIcon={<KeyboardDoubleArrowLeftIcon />}
|
||||
sx={{ mt: 2 }}
|
||||
<>
|
||||
<DialogContent dividers sx={{ display: "flex" }}>
|
||||
<Box sx={{ flex: 1 }}>
|
||||
<Stack
|
||||
direction={'row'}
|
||||
justifyContent={'center'}
|
||||
sx={{
|
||||
mt: 1,
|
||||
mb: 2,
|
||||
}}
|
||||
>
|
||||
نهایی کردن درخواست
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleOpen}
|
||||
startIcon={<AddCircleIcon />}
|
||||
variant="outlined"
|
||||
sx={{ mb: 1 }}
|
||||
>
|
||||
ثبت اقدام انجام شده
|
||||
</Button>
|
||||
<ModalActionsDuringPatrol open={open} setOpen={setOpen} setActionsList={setActionsList} />
|
||||
</Stack>
|
||||
<Divider sx={{ my: 2, width: "100%" }}>
|
||||
<Chip variant="outlined" label="لیست اقدامات حین گشت" />
|
||||
</Divider>
|
||||
{actionsList.length !== 0 ? (
|
||||
<Grid
|
||||
container
|
||||
spacing={2}
|
||||
sx={{
|
||||
p: 1,
|
||||
mt: 1,
|
||||
maxHeight: "400px",
|
||||
overflowY: "auto",
|
||||
}}
|
||||
>
|
||||
{actionsList.map((action, index) => (
|
||||
<Grid key={index} item xs={12} sm={6} lg={4}>
|
||||
<ActionInfo
|
||||
action={action}
|
||||
setActionsList={setActionsList}
|
||||
index={index}
|
||||
deleteAction={() => deleteAction(index)}
|
||||
/>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
) : (
|
||||
<Box sx={{ my: 5, width: "100%", textAlign: "center" }}>
|
||||
<Typography variant="h6" sx={{ letterSpacing: "2px", color: "#606060" }}>
|
||||
فعالیتی ثبت نکرده اید
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</DialogContent >
|
||||
<DialogActions sx={{ alignItems: "center", justifyContent: "center" }}>
|
||||
<Button
|
||||
onClick={handlePrev}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
size="large"
|
||||
startIcon={<ExitToAppIcon />}
|
||||
>
|
||||
{"صفحه قبل"}
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
size="large"
|
||||
onClick={() => handleNext(actionsList)}
|
||||
>
|
||||
{"تایید اقدامات و ادامه"}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
"use client";
|
||||
|
||||
import React, { useEffect, useState } from "react";
|
||||
import StyledForm from "@/core/components/StyledForm";
|
||||
import { formatCounter } from "@/core/utils/formatCounter";
|
||||
import { CREATE_PATROL, GET_OTP_TOKEN } from "@/core/utils/routes";
|
||||
import useRequest from "@/lib/hooks/useRequest";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import ExitToAppIcon from "@mui/icons-material/ExitToApp";
|
||||
import ForwardToInboxIcon from "@mui/icons-material/ForwardToInbox";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Chip,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
Divider,
|
||||
FormControl,
|
||||
Grid,
|
||||
@@ -14,39 +22,47 @@ import {
|
||||
Stack,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import BeenhereIcon from "@mui/icons-material/Beenhere";
|
||||
import ForwardToInboxIcon from "@mui/icons-material/ForwardToInbox";
|
||||
import { formatCounter } from "@/core/utils/formatCounter";
|
||||
import useRequest from "@/lib/hooks/useRequest";
|
||||
import { GET_OTP_TOKEN } from "@/core/utils/routes";
|
||||
import moment from "jalali-moment";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import * as yup from "yup";
|
||||
|
||||
const CompeleteRequest = ({ watch, isSubmitting, setValue, register }) => {
|
||||
const requestServer = useRequest({ auth: true });
|
||||
const schemaOtp = yup.object().shape({
|
||||
phoneNumber: yup
|
||||
.string()
|
||||
.matches(/^09\d{9}$/, "شماره تماس باید با 09 شروع شود و 11 رقم باشد.")
|
||||
.required("شماره تماس الزامی است."),
|
||||
});
|
||||
|
||||
const schemaSend = yup.object().shape({
|
||||
phoneNumber: yup
|
||||
.string()
|
||||
.matches(/^09\d{9}$/, "شماره تماس باید با 09 شروع شود و 11 رقم باشد.")
|
||||
.required("شماره تماس الزامی است."),
|
||||
code: yup
|
||||
.string()
|
||||
.length(6)
|
||||
.required("شماره تماس الزامی است."),
|
||||
});
|
||||
|
||||
const CompeleteRequest = ({ allData, handlePrev, mutate, setOpen }) => {
|
||||
const requestServer = useRequest();
|
||||
const [delayPerRequest, setDelayPerRequest] = useState(false);
|
||||
const [phoneNumber, setPhoneNumber] = useState("");
|
||||
const [validPhone, setValidPhone] = useState(false);
|
||||
const [verificationCode, setVerificationCode] = useState("");
|
||||
const [counter, setCounter] = useState(120);
|
||||
const [otpSended, setOtpSended] = useState(false);
|
||||
const [readyToVerify, setReadyToVerify] = useState(false);
|
||||
|
||||
const handleNumericInput = (e) => {
|
||||
e.target.value = e.target.value.replace(/[^0-9]/g, "");
|
||||
};
|
||||
const defaultValuesOtp = {
|
||||
phoneNumber: ''
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (phoneNumber.length === 11) {
|
||||
setValidPhone(true);
|
||||
} else {
|
||||
setValidPhone(false);
|
||||
}
|
||||
if (verificationCode.length === 6 && phoneNumber.length === 11) {
|
||||
setReadyToVerify(true);
|
||||
} else {
|
||||
setReadyToVerify(false);
|
||||
}
|
||||
}, [phoneNumber, verificationCode]);
|
||||
const defaultValuesSend = {
|
||||
phoneNumber: '',
|
||||
code: ''
|
||||
}
|
||||
|
||||
const { handleSubmit: handleSubmitOtp, register: registerOtp, formState: { isSubmitting: isSubmittingOtp, isValid: isValidOtp } } = useForm({ defaultValues: defaultValuesOtp, resolver: yupResolver(schemaOtp), mode: 'onBlur' })
|
||||
|
||||
const { handleSubmit: handleSubmitSend, setValue: setValueSend, register: registerSend, formState: { isSubmitting: isSubmittingSend, isValid: isValidSend } } = useForm({ defaultValues: defaultValuesSend, resolver: yupResolver(schemaSend), mode: 'onBlur' })
|
||||
|
||||
useEffect(() => {
|
||||
if (counter === 0) {
|
||||
@@ -62,167 +78,219 @@ const CompeleteRequest = ({ watch, isSubmitting, setValue, register }) => {
|
||||
}
|
||||
}, [counter, delayPerRequest]);
|
||||
|
||||
const sendOtp = () => {
|
||||
if (!validPhone) return false;
|
||||
requestServer(`${GET_OTP_TOKEN}?phone_number=${phoneNumber}`, "get")
|
||||
.then((response) => {
|
||||
setOtpSended(true);
|
||||
setDelayPerRequest(true);
|
||||
})
|
||||
.catch(() => {});
|
||||
const sendOtp = async (data) => {
|
||||
try {
|
||||
const response = await requestServer(`${GET_OTP_TOKEN}?phone_number=${data.phoneNumber}`, "get")
|
||||
setOtpSended(true)
|
||||
setDelayPerRequest(true);
|
||||
setValueSend("phoneNumber", data.phoneNumber)
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
const sendData = useCallback(async (data) => {
|
||||
console.log(allData);
|
||||
|
||||
const formData = new FormData();
|
||||
allData.road_patrol_rahdaran_id.forEach((rahdar, index) => formData.append(`road_patrol_rahdaran_id[${index}]`, rahdar.id));
|
||||
formData.append(`road_patrol_machines_id[0]`, allData.roadPatrolMachinesId.id)
|
||||
allData.stopPoints.forEach((stop_point, index) => formData.append(`stop_points[${index}]`, stop_point))
|
||||
allData.observed_items.forEach((observed_item, index) => {
|
||||
formData.append(`observed_items[${index}][instant_action]`, 1);
|
||||
formData.append(`observed_items[${index}][local_name]`, "");
|
||||
formData.append(`observed_items[${index}][start_point]`, observed_item.result.start_point);
|
||||
formData.append(`observed_items[${index}][end_point]`, observed_item.result.end_point);
|
||||
formData.append(`observed_items[${index}][amount]`, observed_item.result.amount);
|
||||
formData.append(`observed_items[${index}][before_image]`, observed_item.result.before_image);
|
||||
formData.append(`observed_items[${index}][after_image]`, observed_item.result.after_image);
|
||||
formData.append(`observed_items[${index}][item_id]`, observed_item.result.item_id);
|
||||
formData.append(`observed_items[${index}][sub_item_id]`, observed_item.result.sub_item_id);
|
||||
formData.append(`observed_items[${index}][road_item_machines_id][]`, allData.roadPatrolMachinesId.id)
|
||||
allData.road_patrol_rahdaran_id.forEach((rahdar, index) => formData.append(`observed_items[${index}][road_item_rahdaran_id][]`, rahdar.id));
|
||||
})
|
||||
formData.append("start_time", allData.start_time);
|
||||
formData.append("end_time", allData.end_time);
|
||||
formData.append("vehicle_runtime", allData.accOnDuration);
|
||||
formData.append("fuel_consumption", +allData.fuelConsumption);
|
||||
formData.append("distance", allData.mileage);
|
||||
// formData.append("description", "");
|
||||
formData.append("phone_number", data.phoneNumber);
|
||||
formData.append("verification_code", data.code);
|
||||
try {
|
||||
await requestServer(CREATE_PATROL, "post", {
|
||||
data: formData,
|
||||
});
|
||||
mutate();
|
||||
setOpen(false);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
|
||||
}
|
||||
}, [allData])
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<Stack>
|
||||
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
|
||||
<Box>
|
||||
<Typography sx={{ color: "#777777", fontWeight: 500 }} variant="body1">
|
||||
{moment(watch("start_time")).locale("fa").format("YYYY/MM/DD | HH:mm")}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box>
|
||||
<Typography sx={{ color: "#777777", fontWeight: 500 }} variant="body1">
|
||||
{moment(watch("end_time")).locale("fa").format("YYYY/MM/DD | HH:mm")}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
<Grid container spacing={2} sx={{ alignItems: "start", my: 1 }}>
|
||||
<Grid item xs={12} lg={6} sx={{ display: "flex", alignItems: "center" }}>
|
||||
<Chip label="مدت زمان روشن بودن خودرو" />
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography>{watch("vehicle_runtime")}</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} lg={6} sx={{ display: "flex", alignItems: "center" }}>
|
||||
<Chip label="میزان سوخت مصرفی" />
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography>{watch("fuel_consumption")}</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} lg={6} sx={{ display: "flex", alignItems: "center" }}>
|
||||
<Chip label="تعداد نقاط توقف" />
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography>{watch("stop_points").length}</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} lg={6} sx={{ display: "flex", alignItems: "center" }}>
|
||||
<Chip label="مسافت پیموده شده" />
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography>{watch("distance")}</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} lg={6} sx={{ display: "flex", alignItems: "center" }}>
|
||||
<Chip label="تعداد فعالیت های حین گشت" />
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography>{watch("observed_items").length}</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container spacing={3} sx={{ alignItems: "start", my: 2 }}>
|
||||
<Grid item xs={12} lg={6}>
|
||||
<Divider>
|
||||
<Chip label="خودرو گشت" />
|
||||
</Divider>
|
||||
<Box sx={{ display: "flex", alignItems: "center", my: 1 }}>
|
||||
<Typography>کد</Typography>
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography>{watch("road_patrol_machines_id.machine_code")}</Typography>
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", alignItems: "center", my: 1 }}>
|
||||
<Typography>نام</Typography>
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography>{watch("road_patrol_machines_id.car_name")}</Typography>
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", alignItems: "center", my: 1 }}>
|
||||
<Typography>پلاک</Typography>
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography>{watch("road_patrol_machines_id.plak_number")}</Typography>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item xs={12} lg={6}>
|
||||
<Divider>
|
||||
<Chip label="راهدار / راهداران حاضر در گشت" />
|
||||
</Divider>
|
||||
{watch("road_patrol_rahdaran_id")?.map((rahdar, index) => (
|
||||
<Box key={index} sx={{ display: "flex", alignItems: "center", my: 1 }}>
|
||||
<Typography>نام و کد راهدار</Typography>
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography>
|
||||
{rahdar.name} | {rahdar.code}
|
||||
<>
|
||||
<DialogContent dividers sx={{ display: "flex" }}>
|
||||
<Box sx={{ flex: 1 }}>
|
||||
<Stack>
|
||||
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
|
||||
<Box>
|
||||
<Typography sx={{ color: "#777777", fontWeight: 500 }} variant="body1">
|
||||
{allData.start_time !== '' && moment(allData.start_time).locale("fa").format("YYYY/MM/DD | HH:mm")}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box>
|
||||
<Typography sx={{ color: "#777777", fontWeight: 500 }} variant="body1">
|
||||
{allData.end_time !== '' && moment(allData.end_time).locale("fa").format("YYYY/MM/DD | HH:mm")}
|
||||
</Typography>
|
||||
</Box>
|
||||
))}
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Box sx={{ display: "flex", gap: 2, my: 2, justifyContent: "space-around" }}>
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: 2 }}>
|
||||
<FormControl size="small" fullWidth variant="outlined">
|
||||
<InputLabel htmlFor="phone_number">شماره تلفن مامور گشت</InputLabel>
|
||||
<OutlinedInput
|
||||
id="phone_number"
|
||||
label={"شماره تلفن مامور گشت"}
|
||||
disabled={delayPerRequest}
|
||||
autoComplete="off"
|
||||
size="small"
|
||||
fullWidth
|
||||
{...register("phone_number")}
|
||||
value={phoneNumber}
|
||||
onChange={(e) => setPhoneNumber(e.target.value)}
|
||||
onInput={handleNumericInput}
|
||||
type="text"
|
||||
inputProps={{
|
||||
maxLength: 11,
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
<Button
|
||||
onClick={sendOtp}
|
||||
disabled={!validPhone || delayPerRequest}
|
||||
variant="contained"
|
||||
color="success"
|
||||
sx={{ textWrap: "nowrap", px: 4 }}
|
||||
endIcon={<ForwardToInboxIcon />}
|
||||
>
|
||||
{delayPerRequest ? formatCounter(counter) : "دریافت کد"}
|
||||
</Button>
|
||||
</Box>
|
||||
<Slide in={otpSended}>
|
||||
<Box>
|
||||
<FormControl size="small" fullWidth variant="outlined" focused>
|
||||
<InputLabel htmlFor="verification_code">کد پیامک شده</InputLabel>
|
||||
<OutlinedInput
|
||||
id="verification_code"
|
||||
label={"کد پیامک شده"}
|
||||
placeholder="------"
|
||||
autoComplete="off"
|
||||
size="small"
|
||||
fullWidth
|
||||
{...register("verification_code")}
|
||||
value={verificationCode}
|
||||
onChange={(e) => setVerificationCode(e.target.value)}
|
||||
onInput={handleNumericInput}
|
||||
type="text"
|
||||
inputProps={{
|
||||
maxLength: 6,
|
||||
inputMode: "numeric",
|
||||
style: {
|
||||
textAlign: "center",
|
||||
letterSpacing: "10px",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
</Box>
|
||||
</Slide>
|
||||
<Grid container spacing={2} sx={{ alignItems: "start", my: 1 }}>
|
||||
<Grid item xs={12} lg={6} sx={{ display: "flex", alignItems: "center" }}>
|
||||
<Chip label="مدت زمان روشن بودن خودرو" />
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography>{allData.accOnDuration && allData.accOnDuration}</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} lg={6} sx={{ display: "flex", alignItems: "center" }}>
|
||||
<Chip label="میزان سوخت مصرفی" />
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography>{allData.fuelConsumption && allData.fuelConsumption}</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} lg={6} sx={{ display: "flex", alignItems: "center" }}>
|
||||
<Chip label="تعداد نقاط توقف" />
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography>{allData.stopPoints && allData.stopPoints.length}</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} lg={6} sx={{ display: "flex", alignItems: "center" }}>
|
||||
<Chip label="مسافت پیموده شده" />
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography>{allData.mileage && allData.mileage}</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} lg={6} sx={{ display: "flex", alignItems: "center" }}>
|
||||
<Chip label="تعداد فعالیت های حین گشت" />
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography>{allData.observed_items && allData.observed_items.length}</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container spacing={3} sx={{ alignItems: "start", my: 2 }}>
|
||||
<Grid item xs={12} lg={6}>
|
||||
<Divider>
|
||||
<Chip label="خودرو گشت" />
|
||||
</Divider>
|
||||
<Box sx={{ display: "flex", alignItems: "center", my: 1 }}>
|
||||
<Typography>کد</Typography>
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography>{allData.roadPatrolMachinesId && allData.roadPatrolMachinesId.machine_code}</Typography>
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", alignItems: "center", my: 1 }}>
|
||||
<Typography>نام</Typography>
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography>{allData.roadPatrolMachinesId && allData.roadPatrolMachinesId.car_name}</Typography>
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", alignItems: "center", my: 1 }}>
|
||||
<Typography>پلاک</Typography>
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography>{allData.roadPatrolMachinesId && allData.roadPatrolMachinesId.plak_number}</Typography>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item xs={12} lg={6}>
|
||||
<Divider>
|
||||
<Chip label="راهدار / راهداران حاضر در گشت" />
|
||||
</Divider>
|
||||
{allData.road_patrol_rahdaran_id.map((rahdar, index) => (
|
||||
<Box key={index} sx={{ display: "flex", alignItems: "center", my: 1 }}>
|
||||
<Typography>نام و کد راهدار</Typography>
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography>
|
||||
{rahdar.name} | {rahdar.code}
|
||||
</Typography>
|
||||
</Box>
|
||||
))}
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Box sx={{ display: "flex", gap: 2, my: 2, justifyContent: "space-around", flexDirection: { xs: 'column', md: 'row' } }}>
|
||||
<StyledForm onSubmit={handleSubmitOtp(sendOtp)}>
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: 2 }}>
|
||||
<FormControl size="small" fullWidth variant="outlined">
|
||||
<InputLabel htmlFor="phoneNumber">شماره تلفن مامور گشت</InputLabel>
|
||||
<OutlinedInput
|
||||
id="phoneNumber"
|
||||
label={"شماره تلفن مامور گشت"}
|
||||
disabled={delayPerRequest}
|
||||
autoComplete="off"
|
||||
size="small"
|
||||
fullWidth
|
||||
{...registerOtp("phoneNumber")}
|
||||
type="text"
|
||||
inputProps={{
|
||||
maxLength: 11,
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
<Button
|
||||
disabled={isSubmittingOtp || !isValidOtp || delayPerRequest}
|
||||
variant="contained"
|
||||
type="submit"
|
||||
sx={{ textWrap: "nowrap", width: 200 }}
|
||||
endIcon={<ForwardToInboxIcon />}
|
||||
>
|
||||
{delayPerRequest ? formatCounter(counter) : isSubmittingOtp ? 'درحال دریافت کد ...' : "دریافت کد"}
|
||||
</Button>
|
||||
</Box>
|
||||
</StyledForm>
|
||||
<Slide in={otpSended}>
|
||||
<StyledForm onSubmit={handleSubmitSend(sendData)} id="sendForm">
|
||||
<Box>
|
||||
<FormControl size="small" fullWidth variant="outlined">
|
||||
<InputLabel htmlFor="code">کد تایید پیامک شده</InputLabel>
|
||||
<OutlinedInput
|
||||
id="code"
|
||||
label={"کد تایید پیامک شده"}
|
||||
placeholder="------"
|
||||
autoComplete="off"
|
||||
size="small"
|
||||
fullWidth
|
||||
{...registerSend("code")}
|
||||
type="text"
|
||||
inputProps={{
|
||||
maxLength: 6,
|
||||
inputMode: "numeric",
|
||||
style: {
|
||||
textAlign: "center",
|
||||
letterSpacing: "10px",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
</Box>
|
||||
</StyledForm>
|
||||
</Slide>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Stack>
|
||||
<Button
|
||||
variant="contained"
|
||||
size="large"
|
||||
disabled={isSubmitting}
|
||||
type={"submit"}
|
||||
form="patrol_form"
|
||||
endIcon={<BeenhereIcon />}
|
||||
>
|
||||
{isSubmitting ? "در حال ثبت فعالیت" : "ثبت فعالیت"}
|
||||
</Button>
|
||||
</Stack>
|
||||
</DialogContent >
|
||||
<DialogActions sx={{ alignItems: "center", justifyContent: "center" }}>
|
||||
<Button
|
||||
onClick={handlePrev}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
size="large"
|
||||
startIcon={<ExitToAppIcon />}
|
||||
>
|
||||
{"صفحه قبل"}
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
size="large"
|
||||
type="submit"
|
||||
form="sendForm"
|
||||
disabled={isSubmittingSend || !isValidSend}
|
||||
>
|
||||
{isSubmittingSend ? "در حال ثبت ..." : "تایید نهایی و ثبت"}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import { IconButton, InputAdornment } from "@mui/material";
|
||||
import { ClearIcon, MobileDateTimePicker } from "@mui/x-date-pickers";
|
||||
import moment from "jalali-moment";
|
||||
import { useWatch } from "react-hook-form";
|
||||
|
||||
const DatePickerForEndTime = ({ field, fieldState: { error }, control }) => {
|
||||
const startTime = useWatch({ control, name: "start_time" })
|
||||
return (
|
||||
<MobileDateTimePicker
|
||||
value={field.value ? new Date(field.value) : null}
|
||||
ampm={false}
|
||||
name="تاریخ و ساعت پایان گشت"
|
||||
closeOnSelect
|
||||
minDateTime={startTime ? new Date(startTime) : null}
|
||||
onChange={(end_time) => {
|
||||
const date = new Date(end_time);
|
||||
const formattedDate = moment(date).locale("en").format("YYYY-MM-DD HH:mm");
|
||||
field.onChange(formattedDate);
|
||||
}}
|
||||
slotProps={{
|
||||
textField: {
|
||||
size: "small",
|
||||
placeholder: "تاریخ و ساعت وارد کنید",
|
||||
InputLabelProps: { shrink: true },
|
||||
sx: { width: { xs: '100%', md: 200 } },
|
||||
InputProps: {
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
field.onChange("");
|
||||
}}
|
||||
sx={{
|
||||
color: "#bfbfbf",
|
||||
"&:hover": {
|
||||
backgroundColor: "rgba(189, 189, 189, 0.1)",
|
||||
color: "#363434",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ClearIcon />
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
},
|
||||
},
|
||||
}}
|
||||
label="تاریخ و ساعت پایان گشت"
|
||||
/>
|
||||
);
|
||||
}
|
||||
export default DatePickerForEndTime
|
||||
@@ -0,0 +1,54 @@
|
||||
import { IconButton, InputAdornment } from "@mui/material";
|
||||
import { ClearIcon, MobileDateTimePicker } from "@mui/x-date-pickers";
|
||||
import moment from "jalali-moment";
|
||||
import { useWatch } from "react-hook-form";
|
||||
|
||||
const DatePickerForStartTime = ({ field, fieldState: { error }, control }) => {
|
||||
const endTime = useWatch({ control, name: "end_time" })
|
||||
return (
|
||||
<MobileDateTimePicker
|
||||
value={field.value ? new Date(field.value) : null}
|
||||
ampm={false}
|
||||
name="تاریخ و ساعت شروع گشت"
|
||||
closeOnSelect
|
||||
maxDateTime={endTime ? new Date(endTime) : null}
|
||||
onChange={(start_time) => {
|
||||
const date = new Date(start_time);
|
||||
const formattedDate = moment(date).locale("en").format("YYYY-MM-DD HH:mm");
|
||||
field.onChange(formattedDate);
|
||||
}}
|
||||
slotProps={{
|
||||
textField: {
|
||||
size: "small",
|
||||
placeholder: "تاریخ و ساعت وارد کنید",
|
||||
InputLabelProps: { shrink: true },
|
||||
sx: { width: { xs: '100%', md: 200 } },
|
||||
InputProps: {
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
field.onChange("");
|
||||
}}
|
||||
sx={{
|
||||
color: "#bfbfbf",
|
||||
"&:hover": {
|
||||
backgroundColor: "rgba(189, 189, 189, 0.1)",
|
||||
color: "#363434",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ClearIcon />
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
},
|
||||
},
|
||||
}}
|
||||
label="تاریخ و ساعت شروع گشت"
|
||||
/>
|
||||
);
|
||||
}
|
||||
export default DatePickerForStartTime
|
||||
@@ -48,7 +48,7 @@ const EditActionDuringPatrol = ({ action, index, setActionsList }) => {
|
||||
}}
|
||||
>
|
||||
<DialogTitle>ویرایش اطلاعات</DialogTitle>
|
||||
<EditFormContent setOpenEditDialog={setOpen} onSubmit={HandleSubmit} defaultData={action.data} />
|
||||
<EditFormContent setOpenEditDialog={setOpen} onSubmit={HandleSubmit} defaultData={action.data} is_gasht={true} />
|
||||
</Dialog>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,202 +1,180 @@
|
||||
"use client";
|
||||
|
||||
import { Box, Button, Chip, Divider, IconButton, InputAdornment, Stack } from "@mui/material";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import CarCode from "@/core/components/CarCode";
|
||||
import StyledForm from "@/core/components/StyledForm";
|
||||
import { GET_FMS_DATA as GET_VAHICLE_OPRATION } from "@/core/utils/routes";
|
||||
import useRequest from "@/lib/hooks/useRequest";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import ExitToAppIcon from "@mui/icons-material/ExitToApp";
|
||||
import SearchIcon from "@mui/icons-material/Search";
|
||||
import { Box, Button, Chip, DialogActions, DialogContent, Divider, Stack } from "@mui/material";
|
||||
import { LocalizationProvider } from "@mui/x-date-pickers";
|
||||
import { AdapterDateFnsJalali } from "@mui/x-date-pickers/AdapterDateFnsJalali";
|
||||
import { faIR } from "@mui/x-date-pickers/locales";
|
||||
import { LocalizationProvider, MobileDateTimePicker } from "@mui/x-date-pickers";
|
||||
import ClearIcon from "@mui/icons-material/Clear";
|
||||
import moment from "jalali-moment";
|
||||
import dynamic from "next/dynamic";
|
||||
import MapLoading from "@/core/components/MapLayer/Loading";
|
||||
import { Controller } from "react-hook-form";
|
||||
import { GET_FMS_DATA } from "@/core/utils/routes";
|
||||
import useRequest from "@/lib/hooks/useRequest";
|
||||
import { useState } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import * as yup from "yup";
|
||||
import DatePickerForEndTime from "./DatePickerForEndTime";
|
||||
import DatePickerForStartTime from "./DatePickerForStartTime";
|
||||
import PatrolDetailInfo from "./PatrolDetailInfo";
|
||||
import PatrolResultCodeErrors from "./PatrolResultCodeErrors";
|
||||
|
||||
const MapLayer = dynamic(() => import("@/core/components/MapLayer"), {
|
||||
loading: () => <MapLoading />,
|
||||
ssr: false,
|
||||
const schema = yup.object().shape({
|
||||
roadPatrolMachinesId: yup
|
||||
.object()
|
||||
.required("خودرو الزامی است."),
|
||||
start_time: yup
|
||||
.string()
|
||||
.required("زمان شروع الزامی است."),
|
||||
end_time: yup
|
||||
.string()
|
||||
.required("زمان پایان الزامی است.")
|
||||
});
|
||||
|
||||
const PatrolDetail = ({ control, watch, setValue, tabState, setTabState }) => {
|
||||
const requestServer = useRequest({ notificationSuccess: true });
|
||||
const [patrolResultStatus, setPatrolResultStatus] = useState(null);
|
||||
const [readyToRequest, setReadyToRequest] = useState(false);
|
||||
const [patrolData, setPatrolData] = useState(null);
|
||||
const PatrolDetail = ({ allData, setAllData, handlePrev, setTabState }) => {
|
||||
const defaultValues = {
|
||||
has_vehicle_operation: allData.has_vehicle_operation,
|
||||
roadPatrolMachinesId: allData.roadPatrolMachinesId,
|
||||
start_time: allData.start_time,
|
||||
end_time: allData.end_time,
|
||||
stopPoints: allData.stopPoints,
|
||||
accOnDuration: allData.accOnDuration,
|
||||
fuelConsumption: allData.fuelConsumption,
|
||||
mileage: allData.mileage,
|
||||
};
|
||||
const requestServer = useRequest();
|
||||
const [patrolResultStatus, setPatrolResultStatus] = useState(allData.resultCode);
|
||||
const [patrolData, setPatrolData] = useState(defaultValues);
|
||||
|
||||
const requestPatrolInfo = async () => {
|
||||
|
||||
const { control, handleSubmit, setValue, formState: { isSubmitting, isValid } } = useForm({ defaultValues, resolver: yupResolver(schema), mode: 'onBlur' })
|
||||
|
||||
const requestPatrolInfo = async (data) => {
|
||||
setPatrolResultStatus(1)
|
||||
setPatrolData(pd => ({ ...pd, has_vehicle_operation: false }))
|
||||
const formData = new FormData();
|
||||
formData.append("machineCode", watch("road_patrol_machines_id").machine_code);
|
||||
formData.append("startDT", moment(watch("start_time")).format("YYYY-MM-DDTHH:mm"));
|
||||
formData.append("endDT", moment(watch("end_time")).format("YYYY-MM-DDTHH:mm"));
|
||||
await requestServer(GET_FMS_DATA, "post", {
|
||||
data: formData,
|
||||
})
|
||||
.then((response) => {
|
||||
const data = response.data.data;
|
||||
setPatrolData({
|
||||
...data,
|
||||
roadPatrolMachinesId: watch("road_patrol_machines_id"),
|
||||
start_time: watch("start_time"),
|
||||
end_time: watch("end_time"),
|
||||
});
|
||||
setPatrolResultStatus(data.resultCode);
|
||||
formData.append("machineCode", data.roadPatrolMachinesId.machine_code);
|
||||
formData.append("startDT", moment(data.start_time).format("YYYY-MM-DDTHH:mm"));
|
||||
formData.append("endDT", moment(data.end_time).format("YYYY-MM-DDTHH:mm"));
|
||||
try {
|
||||
const response = await requestServer(GET_VAHICLE_OPRATION, "post", {
|
||||
data: formData,
|
||||
})
|
||||
.catch((error) => {});
|
||||
const result = response.data.data;
|
||||
setPatrolData({
|
||||
...result,
|
||||
roadPatrolMachinesId: data.roadPatrolMachinesId,
|
||||
start_time: data.start_time,
|
||||
end_time: data.end_time,
|
||||
has_vehicle_operation: result.resultCode == 0
|
||||
});
|
||||
|
||||
setValue('stopPoints', result.stopPoints)
|
||||
setValue('accOnDuration', result.accOnDuration)
|
||||
setValue('fuelConsumption', result.fuelConsumption)
|
||||
setValue('mileage', result.mileage)
|
||||
setValue('has_vehicle_operation', true)
|
||||
setPatrolResultStatus(result.resultCode);
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const roadPatrolMachinesId = watch("road_patrol_machines_id");
|
||||
const startTime = watch("start_time");
|
||||
const endTime = watch("end_time");
|
||||
|
||||
const isReady = roadPatrolMachinesId !== null && startTime !== "" && endTime !== "";
|
||||
setReadyToRequest(isReady);
|
||||
}, [watch("road_patrol_machines_id"), watch("start_time"), watch("end_time")]);
|
||||
const handleNext = (data) => {
|
||||
setAllData(data);
|
||||
setTabState(s => s + 1)
|
||||
}
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
my: 3,
|
||||
}}
|
||||
>
|
||||
<Box sx={{ display: "flex", flexDirection: { xs: "column", lg: "row" }, gap: 2 }}>
|
||||
<Stack sx={{ minWidth: "200px" }}>
|
||||
<Controller
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
return (
|
||||
<CarCode
|
||||
carCode={field.value}
|
||||
setCarCode={(value) => field.onChange(value)}
|
||||
error={error}
|
||||
/>
|
||||
);
|
||||
<>
|
||||
<DialogContent dividers sx={{ display: "flex" }}>
|
||||
<Box sx={{ flex: 1 }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
mt: 1,
|
||||
mb: 2
|
||||
}}
|
||||
name={"road_patrol_machines_id"}
|
||||
/>
|
||||
</Stack>
|
||||
<Box sx={{ display: "flex", gap: 2 }}>
|
||||
<LocalizationProvider
|
||||
dateAdapter={AdapterDateFnsJalali}
|
||||
localeText={faIR.components.MuiLocalizationProvider.defaultProps.localeText}
|
||||
>
|
||||
<MobileDateTimePicker
|
||||
value={watch("start_time") ? new Date(watch("start_time")) : null}
|
||||
ampm={false}
|
||||
name="تاریخ و ساعت شروع گشت"
|
||||
closeOnSelect
|
||||
maxDateTime={watch("end_time") ? new Date(watch("end_time")) : null}
|
||||
onChange={(start_time) => {
|
||||
const date = new Date(start_time);
|
||||
const formattedDate = moment(date).locale("en").format("YYYY-MM-DD HH:mm");
|
||||
setValue("start_time", formattedDate);
|
||||
}}
|
||||
slotProps={{
|
||||
textField: {
|
||||
size: "small",
|
||||
placeholder: "تاریخ و ساعت شروع گشت",
|
||||
InputProps: {
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
setValue("start_time", "");
|
||||
}}
|
||||
sx={{
|
||||
color: "#bfbfbf",
|
||||
"&:hover": {
|
||||
backgroundColor: "rgba(189, 189, 189, 0.1)",
|
||||
color: "#363434",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ClearIcon />
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
},
|
||||
},
|
||||
}}
|
||||
label="تاریخ و ساعت شروع گشت"
|
||||
<StyledForm onSubmit={handleSubmit(requestPatrolInfo)}>
|
||||
<Box sx={{ display: "flex", flexDirection: { xs: "column", md: "row" }, rowGap: 2, columnGap: 1 }}>
|
||||
<Stack sx={{ minWidth: "200px" }}>
|
||||
<Controller
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
return (
|
||||
<CarCode
|
||||
carCode={field.value}
|
||||
setCarCode={(value) => field.onChange(value)}
|
||||
error={error}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
name={"roadPatrolMachinesId"}
|
||||
/>
|
||||
</Stack>
|
||||
<Box sx={{ display: "flex", gap: 1 }}>
|
||||
<LocalizationProvider
|
||||
dateAdapter={AdapterDateFnsJalali}
|
||||
localeText={faIR.components.MuiLocalizationProvider.defaultProps.localeText}
|
||||
>
|
||||
<Controller
|
||||
control={control}
|
||||
render={(props) => <DatePickerForStartTime {...props} control={control} />}
|
||||
name={"start_time"}
|
||||
/>
|
||||
<Controller
|
||||
control={control}
|
||||
render={(props) => <DatePickerForEndTime {...props} control={control} />}
|
||||
name={"end_time"}
|
||||
/>
|
||||
</LocalizationProvider>
|
||||
</Box>
|
||||
<Button
|
||||
sx={{ flex: 1 }}
|
||||
variant="contained"
|
||||
type="submit"
|
||||
disabled={isSubmitting || !isValid}
|
||||
endIcon={<SearchIcon />}
|
||||
>
|
||||
{isSubmitting ? "درحال دریافت عملکرد خودرو ..." : 'دریافت عملکرد خوردو'}
|
||||
</Button>
|
||||
</Box>
|
||||
</StyledForm>
|
||||
<Divider sx={{ my: 2, width: "100%" }}>
|
||||
<Chip label="مشخصات گشت" variant="outlined" />
|
||||
</Divider>
|
||||
{patrolResultStatus !== 0 && (
|
||||
<PatrolResultCodeErrors ResultCode={patrolResultStatus} />
|
||||
)}
|
||||
<PatrolDetailInfo
|
||||
patrolData={patrolData}
|
||||
/>
|
||||
<MobileDateTimePicker
|
||||
value={watch("end_time") ? new Date(watch("end_time")) : null}
|
||||
ampm={false}
|
||||
name="تاریخ و ساعت پایان گشت"
|
||||
closeOnSelect
|
||||
minDateTime={watch("start_time") ? new Date(watch("start_time")) : null}
|
||||
onChange={(end_time) => {
|
||||
const date = new Date(end_time);
|
||||
const formattedDate = moment(date).locale("en").format("YYYY-MM-DD HH:mm");
|
||||
setValue("end_time", formattedDate);
|
||||
}}
|
||||
slotProps={{
|
||||
textField: {
|
||||
size: "small",
|
||||
placeholder: "تاریخ و ساعت پایان گشت",
|
||||
InputProps: {
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
setValue("end_time", "");
|
||||
}}
|
||||
sx={{
|
||||
color: "#bfbfbf",
|
||||
"&:hover": {
|
||||
backgroundColor: "rgba(189, 189, 189, 0.1)",
|
||||
color: "#363434",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ClearIcon />
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
},
|
||||
},
|
||||
}}
|
||||
label="تاریخ و ساعت پایان گشت"
|
||||
/>
|
||||
</LocalizationProvider>
|
||||
</Box>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ alignItems: "center", justifyContent: "center" }}>
|
||||
<Button
|
||||
onClick={handlePrev}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
size="large"
|
||||
startIcon={<ExitToAppIcon />}
|
||||
>
|
||||
{"بستن"}
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={requestPatrolInfo}
|
||||
color="success"
|
||||
disabled={!readyToRequest}
|
||||
endIcon={<SearchIcon />}
|
||||
size="large"
|
||||
disabled={!patrolData?.has_vehicle_operation}
|
||||
onClick={() => handleNext(patrolData)}
|
||||
>
|
||||
درخواست اطلاعات
|
||||
{"تایید مشخصات گشت و ادامه"}
|
||||
</Button>
|
||||
</Box>
|
||||
<Divider sx={{ my: 2, width: "100%" }}>
|
||||
<Chip color="success" label="مشخصات گشت" />
|
||||
</Divider>
|
||||
{patrolResultStatus === 0 ? (
|
||||
<PatrolDetailInfo
|
||||
patrolData={patrolData}
|
||||
tabState={tabState}
|
||||
setTabState={setTabState}
|
||||
setValue={setValue}
|
||||
/>
|
||||
) : (
|
||||
<PatrolResultCodeErrors ResultCode={patrolResultStatus} />
|
||||
)}
|
||||
</Box>
|
||||
</DialogActions>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { Box, Button, Card, CardActions, CardContent, Chip, Divider, Slide, Stack, Typography } from "@mui/material";
|
||||
import { Box, Button, Card, CardActions, CardContent, Chip, Divider, Fade, Slide, Stack, Typography } from "@mui/material";
|
||||
import React, { useEffect } from "react";
|
||||
import dynamic from "next/dynamic";
|
||||
import MapLoading from "@/core/components/MapLayer/Loading";
|
||||
@@ -27,13 +27,13 @@ const MapItemViewBound = ({ patrolData, bound }) => {
|
||||
|
||||
useEffect(() => {
|
||||
if (bound.length !== 0) {
|
||||
map.fitBounds(bound, { paddingTopLeft: [16, 16], paddingBottomRight: [16, 130] });
|
||||
map.fitBounds(bound, { paddingTopLeft: [64, 64], paddingBottomRight: [64, 64] });
|
||||
}
|
||||
}, [bound]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{patrolData.stopPoints.map((stopPoint, index) => (
|
||||
{patrolData?.stopPoints && patrolData.stopPoints.map((stopPoint, index) => (
|
||||
<React.Fragment key={index}>
|
||||
<PatrolMapFeatures stopPoint={stopPoint} />
|
||||
</React.Fragment>
|
||||
@@ -42,96 +42,88 @@ const MapItemViewBound = ({ patrolData, bound }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const PatrolDetailInfo = ({ patrolData, tabState, setTabState, setValue }) => {
|
||||
const bound = patrolData.stopPoints.map((point) => [point.latitude, point.longitude]);
|
||||
|
||||
const SendPatrolInfo = () => {
|
||||
setValue("vehicle_runtime", patrolData.accOnDuration);
|
||||
setValue("fuel_consumption", patrolData.fuelConsumption);
|
||||
setValue("distance", patrolData.mileage);
|
||||
setValue("stop_points", patrolData.stopPoints);
|
||||
setTabState(tabState + 1);
|
||||
};
|
||||
const PatrolDetailInfo = ({ patrolData }) => {
|
||||
const bound = patrolData?.stopPoints ? patrolData?.stopPoints.map((point) => [point.latitude, point.longitude]) : []
|
||||
|
||||
return (
|
||||
<Slide in={true} sx={{ width: "100%" }}>
|
||||
<Card>
|
||||
<Fade in={patrolData?.has_vehicle_operation} sx={{ width: "100%" }}>
|
||||
<Card elevation={0}>
|
||||
<CardContent
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: { xs: "column", lg: "row" },
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
justifyContent: "space-around",
|
||||
gap: { xs: 2, lg: 0 },
|
||||
}}
|
||||
>
|
||||
<Stack sx={{ minWidth: { xs: "100%", lg: "300px" }, gap: 2 }}>
|
||||
<Stack sx={{ minWidth: { xs: "100%", md: "300px" }, gap: 2 }}>
|
||||
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
|
||||
<Chip size="small" label="مدت زمان روشن بودن خودرو" icon={<ElectricCarIcon />} />
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography sx={{ fontSize: "13px", fontWeight: 400 }}>
|
||||
{Math.floor(patrolData.accOnDuration / 60)} دقیقه
|
||||
{Math.floor(patrolData?.accOnDuration / 60)} دقیقه
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
|
||||
<Chip size="small" label="نام خودرو" icon={<DirectionsCarFilledIcon />} />
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography sx={{ fontSize: "13px", fontWeight: 400 }}>
|
||||
{patrolData.roadPatrolMachinesId.car_name}
|
||||
{patrolData?.roadPatrolMachinesId?.car_name}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
|
||||
<Chip size="small" label="کد خودرو" icon={<QrCode2Icon />} />
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography sx={{ fontSize: "13px", fontWeight: 400 }}>
|
||||
{patrolData.roadPatrolMachinesId.machine_code}
|
||||
{patrolData?.roadPatrolMachinesId?.machine_code}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
|
||||
<Chip size="small" label="پلاک خودرو" icon={<DirectionsCarFilledIcon />} />
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography sx={{ fontSize: "13px", fontWeight: 400 }}>
|
||||
{patrolData.roadPatrolMachinesId.plak_number}
|
||||
{patrolData?.roadPatrolMachinesId?.plak_number}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
|
||||
<Chip size="small" label="زمان شروع گشت" icon={<QueryBuilderIcon />} />
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography sx={{ fontSize: "13px", fontWeight: 400 }}>
|
||||
{moment(patrolData.start_time).locale("fa").format("HH:mm | YYYY/MM/DD")}
|
||||
{patrolData?.start_time !== '' && moment(patrolData?.start_time).locale("fa").format("HH:mm | YYYY/MM/DD")}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
|
||||
<Chip size="small" label="زمان پایان گشت" icon={<WatchLaterIcon />} />
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography sx={{ fontSize: "13px", fontWeight: 400 }}>
|
||||
{moment(patrolData.end_time).locale("fa").format("HH:mm | YYYY/MM/DD")}
|
||||
{patrolData?.end_time !== '' && moment(patrolData?.end_time).locale("fa").format("HH:mm | YYYY/MM/DD")}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
|
||||
<Chip size="small" label="مسافت" icon={<AddRoadIcon />} />
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography sx={{ fontSize: "13px", fontWeight: 400 }}>
|
||||
{(patrolData.mileage / 1000).toFixed(1)} کیلومتر
|
||||
{(patrolData?.mileage / 1000).toFixed(1)} کیلومتر
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
|
||||
<Chip size="small" label="میزان مصرف سوخت" icon={<LocalGasStationIcon />} />
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography sx={{ fontSize: "13px", fontWeight: 400 }}>
|
||||
{Math.round(patrolData.fuelConsumption * 10) / 10} لیتر
|
||||
{Math.round(patrolData?.fuelConsumption * 10) / 10} لیتر
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
|
||||
<Chip size="small" label="تعداد توقف در مسیر" icon={<ShareLocationIcon />} />
|
||||
<Divider sx={{ flex: 1, mx: 2 }} />
|
||||
<Typography sx={{ fontSize: "13px", fontWeight: 400 }}>
|
||||
{patrolData.stopPoints.length} مورد
|
||||
{patrolData?.stopPoints?.length} مورد
|
||||
</Typography>
|
||||
</Box>
|
||||
</Stack>
|
||||
<Divider orientation="vertical" flexItem />
|
||||
<Stack spacing={1} sx={{ height: "300px", width: { xs: "100%", lg: "350px" } }}>
|
||||
<Stack spacing={1} sx={{ height: "300px", width: { xs: "100%", md: "350px" } }}>
|
||||
<Box
|
||||
sx={{
|
||||
p: 1,
|
||||
@@ -149,28 +141,18 @@ const PatrolDetailInfo = ({ patrolData, tabState, setTabState, setValue }) => {
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<MapLayer position={bound}>
|
||||
<MapItemViewBound patrolData={patrolData} bound={bound} />
|
||||
</MapLayer>
|
||||
{bound.length > 0 && (
|
||||
<MapLayer position={bound}>
|
||||
<MapItemViewBound patrolData={patrolData} bound={bound} />
|
||||
</MapLayer>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
</Stack>
|
||||
</CardContent>
|
||||
<CardActions sx={{ alignItems: "center", justifyContent: "center" }}>
|
||||
<Box sx={{ display: "flex", gap: 1 }}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={SendPatrolInfo}
|
||||
endIcon={<KeyboardDoubleArrowLeftIcon />}
|
||||
sx={{ mt: 2 }}
|
||||
>
|
||||
تایید اطلاعات و رفتن به مرحله بعد
|
||||
</Button>
|
||||
</Box>
|
||||
</CardActions>
|
||||
|
||||
</Card>
|
||||
</Slide>
|
||||
</Fade>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
"use client";
|
||||
|
||||
import { Box, DialogContent, Tab, Tabs, useMediaQuery } from "@mui/material";
|
||||
import useRequest from "@/lib/hooks/useRequest";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import TaxiAlertIcon from "@mui/icons-material/TaxiAlert";
|
||||
import EngineeringIcon from "@mui/icons-material/Engineering";
|
||||
import HandymanIcon from "@mui/icons-material/Handyman";
|
||||
import VerifiedIcon from "@mui/icons-material/Verified";
|
||||
import PatrolTimeLine from "./PatrolTimeLine";
|
||||
import { Box, Tab, Tabs, useMediaQuery } from "@mui/material";
|
||||
import { useCallback, useEffect, useReducer, useState } from "react";
|
||||
import PatrolDetail from "./PatrolDetail";
|
||||
import SuperVisorsDetail from "./SuperVisorsDetail";
|
||||
import ActionsDuringPatrol from "./ActionsDurigPatrol";
|
||||
import { useForm } from "react-hook-form";
|
||||
import StyledForm from "@/core/components/StyledForm";
|
||||
import useRequest from "@/lib/hooks/useRequest";
|
||||
import CompeleteRequest from "./CompeleteRequest";
|
||||
|
||||
function TabPanel(props) {
|
||||
@@ -27,21 +24,35 @@ function TabPanel(props) {
|
||||
}
|
||||
|
||||
const defaultValues = {
|
||||
road_patrol_rahdaran_id: null,
|
||||
road_patrol_machines_id: null,
|
||||
has_vehicle_operation: false,
|
||||
road_patrol_rahdaran_id: [],
|
||||
roadPatrolMachinesId: null,
|
||||
start_time: "",
|
||||
end_time: "",
|
||||
stop_points: null,
|
||||
vehicle_runtime: "",
|
||||
fuel_consumption: "",
|
||||
distance: "",
|
||||
observed_items: null,
|
||||
stopPoints: null,
|
||||
accOnDuration: "",
|
||||
fuelConsumption: "",
|
||||
mileage: "",
|
||||
observed_items: [],
|
||||
phone_number: "",
|
||||
otp_token: "",
|
||||
resultCode: null,
|
||||
};
|
||||
|
||||
const reducer = (state, action) => {
|
||||
switch (action.type) {
|
||||
case 'changeData':
|
||||
return { ...state, ...action.data }
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
const PatrolForms = ({ mutate, setOpen }) => {
|
||||
const requestServer = useRequest({ notificationSuccess: true });
|
||||
const [allData, dispatch] = useReducer(reducer, defaultValues);
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down("md"));
|
||||
const [tabState, setTabState] = useState(0);
|
||||
@@ -57,62 +68,15 @@ const PatrolForms = ({ mutate, setOpen }) => {
|
||||
}
|
||||
}, [tabState]);
|
||||
|
||||
const {
|
||||
control,
|
||||
watch,
|
||||
getValues,
|
||||
register,
|
||||
handleSubmit,
|
||||
setValue,
|
||||
resetField,
|
||||
formState: { isSubmitting },
|
||||
} = useForm({
|
||||
defaultValues,
|
||||
mode: "onBlur",
|
||||
});
|
||||
|
||||
const onSubmit = async (data) => {
|
||||
console.log("data", data);
|
||||
// const formData = new FormData();
|
||||
// data.road_patrol_rahdaran_id.forEach((rahdar, index) => formData.append(`road_patrol_rahdaran_id[${index}]`, rahdar.id));
|
||||
// formData.append(`road_patrol_machines_id[0]`, data.road_patrol_machines_id.id)
|
||||
// data.stop_points.forEach((stop_point, index) => formData.append(`stop_points[${index}]`, stop_point))
|
||||
// data.observed_items.forEach((observed_item, index) => {
|
||||
// formData.append(`observed_items[${index}][instant_action]`, 1);
|
||||
// formData.append(`observed_items[${index}][local_name]`, "");
|
||||
// formData.append(`observed_items[${index}][start_point]`, observed_item.start_point);
|
||||
// formData.append(`observed_items[${index}][start_point]`, observed_item.end_point);
|
||||
// formData.append(`observed_items[${index}][amount]`, observed_item.amount);
|
||||
// formData.append(`observed_items[${index}][before_image]`, observed_item.before_image);
|
||||
// formData.append(`observed_items[${index}][after_image]`, observed_item.after_image);
|
||||
// observed_item.cmms_machines.forEach((machine) => formData.append(`observed_items[${index}][cmms_machines][]`, machine.id))
|
||||
// observed_item.rahdaran_id.forEach((rahdar) => formData.append(`observed_items[${index}][rahdaran_id][]`, rahdar.id))
|
||||
// formData.append(`observed_items[${index}][sub_item_id]`, observed_item.sub_item_id);
|
||||
// })
|
||||
// formData.append("start_time", data.start_time);
|
||||
// formData.append("end_time", data.end_time);
|
||||
// formData.append("vehicle_runtime", data.vehicle_runtime);
|
||||
// formData.append("fuel_consumption", +data.fuel_consumption);
|
||||
// formData.append("distance", data.distance);
|
||||
// formData.append("description", "");
|
||||
// formData.append("phone_number", data.phone_number);
|
||||
// formData.append("verification_code", data.verification_code);
|
||||
// if (data.phone_number !== "" && data.verification_code !== "") {
|
||||
// try {
|
||||
// await requestServer(CREATE_PATROL, "post", {
|
||||
// data: formData,
|
||||
// });
|
||||
// mutate();
|
||||
// setOpen(false);
|
||||
// } catch (error) {
|
||||
// }
|
||||
// } else {
|
||||
// console.log("error phone number")
|
||||
// }
|
||||
};
|
||||
const handlePrev = useCallback(() => {
|
||||
if (tabState == 0) {
|
||||
setOpen(false);
|
||||
}
|
||||
setTabState(s => s - 1)
|
||||
}, [tabState])
|
||||
|
||||
return (
|
||||
<StyledForm onSubmit={handleSubmit(onSubmit)} id="patrol_form">
|
||||
<>
|
||||
<Tabs
|
||||
allowScrollButtonsMobile
|
||||
value={tabState}
|
||||
@@ -128,52 +92,42 @@ const PatrolForms = ({ mutate, setOpen }) => {
|
||||
<Tab disabled={!(activeUpTo >= 0)} icon={<TaxiAlertIcon />} label="مشخصات گشت"></Tab>
|
||||
<Tab disabled={!(activeUpTo >= 1)} icon={<EngineeringIcon />} label="مشخصات راهداران"></Tab>
|
||||
<Tab disabled={!(activeUpTo >= 2)} icon={<HandymanIcon />} label="اقدامات حین گشت"></Tab>
|
||||
<Tab disabled={!(activeUpTo >= 3)} icon={<VerifiedIcon />} label="تکمیل درخواست"></Tab>
|
||||
<Tab disabled={!(activeUpTo >= 3)} icon={<VerifiedIcon />} label="بررسی نهایی و ثبت"></Tab>
|
||||
</Tabs>
|
||||
<DialogContent dividers sx={{ display: "flex" }}>
|
||||
<Box sx={{ flex: 1 }}>
|
||||
<TabPanel value={tabState} index={0}>
|
||||
<PatrolDetail
|
||||
control={control}
|
||||
setValue={setValue}
|
||||
watch={watch}
|
||||
tabState={tabState}
|
||||
setTabState={setTabState}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel value={tabState} index={1}>
|
||||
<SuperVisorsDetail
|
||||
control={control}
|
||||
setValue={setValue}
|
||||
watch={watch}
|
||||
tabState={tabState}
|
||||
setTabState={setTabState}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel value={tabState} index={2}>
|
||||
<ActionsDuringPatrol
|
||||
watch={watch}
|
||||
setValue={setValue}
|
||||
tabState={tabState}
|
||||
setTabState={setTabState}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel value={tabState} index={3}>
|
||||
<CompeleteRequest
|
||||
register={register}
|
||||
setValue={setValue}
|
||||
watch={watch}
|
||||
isSubmitting={isSubmitting}
|
||||
/>
|
||||
</TabPanel>
|
||||
</Box>
|
||||
{!isMobile && (
|
||||
<Box sx={{ display: "flex", alignItems: "center" }}>
|
||||
<PatrolTimeLine tabState={tabState} />
|
||||
</Box>
|
||||
)}
|
||||
</DialogContent>
|
||||
</StyledForm>
|
||||
|
||||
<TabPanel value={tabState} index={0}>
|
||||
<PatrolDetail
|
||||
allData={allData}
|
||||
setAllData={(data) => { dispatch({ type: 'changeData', data }) }}
|
||||
handlePrev={handlePrev}
|
||||
setTabState={setTabState}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel value={tabState} index={1}>
|
||||
<SuperVisorsDetail
|
||||
allData={allData}
|
||||
setAllData={(data) => { dispatch({ type: 'changeData', data }) }}
|
||||
handlePrev={handlePrev}
|
||||
setTabState={setTabState}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel value={tabState} index={2}>
|
||||
<ActionsDuringPatrol
|
||||
allData={allData}
|
||||
setAllData={(data) => { dispatch({ type: 'changeData', data }) }}
|
||||
handlePrev={handlePrev}
|
||||
setTabState={setTabState}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel value={tabState} index={3}>
|
||||
<CompeleteRequest
|
||||
allData={allData}
|
||||
handlePrev={handlePrev}
|
||||
mutate={mutate}
|
||||
setOpen={setOpen}
|
||||
/>
|
||||
</TabPanel>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default PatrolForms;
|
||||
|
||||
@@ -5,6 +5,7 @@ import React from "react";
|
||||
|
||||
const PatrolResultCodeErrors = ({ ResultCode }) => {
|
||||
const errorMessages = {
|
||||
[1]: "درحال دریافت عملکرد خودرو ...",
|
||||
[-1]: "نام کاربری یا کلمه عبور صحیح نمیباشد",
|
||||
[-2]: "ردیاب به خودرو انتخابی متصل نیست",
|
||||
[-3]: "کاربر دسترسی لازم به اطلاعات خودرو انتخابی را ندارد",
|
||||
@@ -14,8 +15,8 @@ const PatrolResultCodeErrors = ({ ResultCode }) => {
|
||||
const message = errorMessages[ResultCode] || "ابتدا اطلاعات بالا را تکمیل نمایید";
|
||||
|
||||
return (
|
||||
<Box sx={{ my: 5 }}>
|
||||
<Typography variant="h6" sx={{ letterSpacing: "2px", color: ResultCode ? "error.main" : "#606060" }}>
|
||||
<Box sx={{ my: 5, textAlign: 'center' }}>
|
||||
<Typography variant="h6" sx={{ letterSpacing: "2px", color: ResultCode && ResultCode != 1 ? "error.main" : "#606060" }}>
|
||||
{message}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
@@ -8,11 +8,13 @@ import React from "react";
|
||||
const SuperVisorInfo = ({ superVisor, deleteSuperVisor }) => {
|
||||
return (
|
||||
<Card
|
||||
elevation={3}
|
||||
elevation={0}
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
border: 1,
|
||||
borderColor: 'divider',
|
||||
px: 1,
|
||||
py: 1,
|
||||
}}
|
||||
|
||||
@@ -1,138 +1,136 @@
|
||||
"use client";
|
||||
|
||||
import { Box, Button, Chip, Divider, Grid, Stack, Typography } from "@mui/material";
|
||||
import SaveAltIcon from "@mui/icons-material/SaveAlt";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import RahdarCode from "@/core/components/RahdarCode";
|
||||
import SuperVisorInfo from "@/components/dashboard/roadPatrols/operator/Forms/CreatePatrol/SuperVisorInfo";
|
||||
import KeyboardDoubleArrowRightIcon from "@mui/icons-material/KeyboardDoubleArrowRight";
|
||||
import KeyboardDoubleArrowLeftIcon from "@mui/icons-material/KeyboardDoubleArrowLeft";
|
||||
import { Controller } from "react-hook-form";
|
||||
import RahdarCode from "@/core/components/RahdarCode";
|
||||
import StyledForm from "@/core/components/StyledForm";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import ExitToAppIcon from "@mui/icons-material/ExitToApp";
|
||||
import { Box, Button, Chip, DialogActions, DialogContent, Divider, Fade, Grid, Stack, Typography } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import * as yup from "yup";
|
||||
|
||||
const SuperVisorsDetail = ({ control, watch, setValue, tabState, setTabState }) => {
|
||||
const [SuperVisorList, setSuperVisorList] = useState([]);
|
||||
const [readyToRequest, setReadyToRequest] = useState(false);
|
||||
const schema = yup.object().shape({
|
||||
road_patrol_rahdaran_id: yup
|
||||
.object()
|
||||
.required("راهدار الزامی است."),
|
||||
});
|
||||
|
||||
const requestPatrolInfo = () => {
|
||||
setSuperVisorList((prev) => [...prev, watch("road_patrol_rahdaran_id")]);
|
||||
setReadyToRequest(false);
|
||||
setValue("road_patrol_rahdaran_id", null);
|
||||
const SuperVisorsDetail = ({ allData, setAllData, handlePrev, setTabState }) => {
|
||||
const [SuperVisorList, setSuperVisorList] = useState(allData.road_patrol_rahdaran_id);
|
||||
|
||||
const defaultValues = {
|
||||
road_patrol_rahdaran_id: null,
|
||||
};
|
||||
|
||||
const { control, handleSubmit, reset, setValue, formState: { isSubmitting, isValid } } = useForm({ defaultValues, resolver: yupResolver(schema), mode: 'onBlur' })
|
||||
|
||||
const requestPatrolInfo = (data) => {
|
||||
setSuperVisorList((prev) => [...prev, data.road_patrol_rahdaran_id]);
|
||||
reset()
|
||||
};
|
||||
|
||||
const deleteSuperVisor = (id) => {
|
||||
setSuperVisorList((prev) => prev.filter((superVisor) => superVisor.id !== id));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setReadyToRequest(watch("road_patrol_rahdaran_id") != null);
|
||||
}, [watch("road_patrol_rahdaran_id")]);
|
||||
|
||||
const SendSuperVisor = () => {
|
||||
setValue("road_patrol_rahdaran_id", SuperVisorList);
|
||||
setTabState(tabState + 1);
|
||||
};
|
||||
const handleNext = (data) => {
|
||||
setAllData({ road_patrol_rahdaran_id: data });
|
||||
setTabState(s => s + 1)
|
||||
}
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
my: 3,
|
||||
}}
|
||||
>
|
||||
<Grid container sx={{ display: "flex", alignItems: "center", justifyContent: "center" }}>
|
||||
<Grid
|
||||
item
|
||||
xs={6}
|
||||
sx={{ display: "flex", alignItems: "center", flexDirection: { xs: "column", lg: "row" }, gap: 2 }}
|
||||
>
|
||||
<Stack sx={{ minWidth: "250px" }}>
|
||||
<Controller
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
return (
|
||||
<RahdarCode
|
||||
rahdarsCode={field.value}
|
||||
setRahdarsCode={(value) => field.onChange(value)}
|
||||
error={error}
|
||||
multiple={false}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
name={"road_patrol_rahdaran_id"}
|
||||
/>
|
||||
</Stack>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={requestPatrolInfo}
|
||||
color="success"
|
||||
sx={{ textWrap: "nowrap", px: 3 }}
|
||||
disabled={!readyToRequest}
|
||||
endIcon={<SaveAltIcon />}
|
||||
>
|
||||
ثبت راهدار
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Divider sx={{ my: 2, width: "100%" }}>
|
||||
<Chip color="success" variant="outlined" label="لیست راهداران انتخاب شده" />
|
||||
</Divider>
|
||||
{SuperVisorList.length !== 0 ? (
|
||||
<>
|
||||
<Grid
|
||||
container
|
||||
spacing={2}
|
||||
sx={{
|
||||
p: 1,
|
||||
mt: 1,
|
||||
maxHeight: "300px",
|
||||
overflowY: "auto",
|
||||
}}
|
||||
>
|
||||
{SuperVisorList.map((superVisor) => (
|
||||
<Grid key={superVisor.id} item xs={12} sm={6} lg={4}>
|
||||
<SuperVisorInfo superVisor={superVisor} deleteSuperVisor={deleteSuperVisor} />
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
<>
|
||||
<DialogContent dividers sx={{ display: "flex" }}>
|
||||
<Box sx={{ flex: 1 }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
gap: 1,
|
||||
mt: 2,
|
||||
width: "100%",
|
||||
justifyContent: "center",
|
||||
flexDirection: "column",
|
||||
mt: 1,
|
||||
mb: 2
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="error"
|
||||
startIcon={<KeyboardDoubleArrowRightIcon />}
|
||||
sx={{ mt: 2 }}
|
||||
>
|
||||
بازگشت
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={SendSuperVisor}
|
||||
endIcon={<KeyboardDoubleArrowLeftIcon />}
|
||||
sx={{ mt: 2 }}
|
||||
>
|
||||
تایید اطلاعات و رفتن به مرحله بعد
|
||||
</Button>
|
||||
<StyledForm onSubmit={handleSubmit(requestPatrolInfo)}>
|
||||
<Stack direction={{ xs: "column", sm: 'row' }} justifyContent={'center'} spacing={2}>
|
||||
<Stack sx={{ minWidth: "250px" }}>
|
||||
<Controller
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
return (
|
||||
<RahdarCode
|
||||
rahdarsCode={field.value}
|
||||
setRahdarsCode={(value) => field.onChange(value)}
|
||||
error={error}
|
||||
multiple={false}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
name={"road_patrol_rahdaran_id"}
|
||||
/>
|
||||
</Stack>
|
||||
<Button
|
||||
variant="contained"
|
||||
type="submit"
|
||||
sx={{ textWrap: "nowrap", px: 3 }}
|
||||
disabled={isSubmitting || !isValid}
|
||||
>
|
||||
افزودن راهدار
|
||||
</Button>
|
||||
</Stack>
|
||||
</StyledForm>
|
||||
<Divider sx={{ my: 2, width: "100%" }}>
|
||||
<Chip variant="outlined" label="لیست راهداران" />
|
||||
</Divider>
|
||||
{SuperVisorList.length === 0 && (
|
||||
<Box sx={{ my: 4, width: "100%", textAlign: "center" }}>
|
||||
<Typography variant="h6" sx={{ letterSpacing: "2px", color: "#606060" }}>
|
||||
ابتدا اطلاعات بالا را تکمیل نمایید
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
<Fade in={SuperVisorList.length !== 0} sx={{ width: "100%" }}>
|
||||
<Grid
|
||||
container
|
||||
spacing={2}
|
||||
sx={{
|
||||
p: 1,
|
||||
mt: 2,
|
||||
minHeight: 150,
|
||||
maxHeight: 300,
|
||||
overflowY: "auto",
|
||||
}}
|
||||
>
|
||||
{SuperVisorList.length !== 0 && SuperVisorList.map((superVisor) => (
|
||||
<Grid key={superVisor.id} item xs={12} sm={6} lg={4}>
|
||||
<SuperVisorInfo superVisor={superVisor} deleteSuperVisor={deleteSuperVisor} />
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</Fade>
|
||||
</Box>
|
||||
</>
|
||||
) : (
|
||||
<Box sx={{ my: 5, width: "100%", textAlign: "center" }}>
|
||||
<Typography variant="h6" sx={{ letterSpacing: "2px", color: "#606060" }}>
|
||||
ابتدا اطلاعات بالا را تکمیل نمایید
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</DialogContent >
|
||||
<DialogActions sx={{ alignItems: "center", justifyContent: "center" }}>
|
||||
<Button
|
||||
onClick={handlePrev}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
size="large"
|
||||
startIcon={<ExitToAppIcon />}
|
||||
>
|
||||
{"صفحه قبل"}
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
size="large"
|
||||
disabled={SuperVisorList.length === 0}
|
||||
onClick={() => handleNext(SuperVisorList)}
|
||||
>
|
||||
{"تایید راهداران و ادامه"}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -5,8 +5,10 @@ import PatrolForms from "./PatrolForms";
|
||||
|
||||
const CreatePatrol = ({ open, setOpen, mutate }) => {
|
||||
return (
|
||||
<Dialog open={open} fullWidth maxWidth="lg">
|
||||
<PatrolForms setOpen={setOpen} mutate={mutate} />
|
||||
<Dialog open={open} fullWidth maxWidth="md">
|
||||
{open && (
|
||||
<PatrolForms setOpen={setOpen} mutate={mutate} />
|
||||
)}
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user