add mission to read item

This commit is contained in:
AmirHossein Mahmoodi
2025-09-02 13:48:31 +03:30
parent 0253b06018
commit 545e9de8ea
15 changed files with 539 additions and 568 deletions

View File

@@ -1,20 +1,20 @@
import React, { useState } from "react";
import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import { array, mixed, number, object, string } from "yup";
import { useTheme } from "@emotion/react";
import { Box, Button, DialogActions, DialogContent, Tab, Tabs, useMediaQuery } from "@mui/material";
import StyledForm from "@/core/components/StyledForm";
import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile";
import FileCopyIcon from "@mui/icons-material/FileCopy";
import InfoIcon from "@mui/icons-material/Info";
import ExitToAppIcon from "@mui/icons-material/ExitToApp";
import KeyboardDoubleArrowRightIcon from "@mui/icons-material/KeyboardDoubleArrowRight";
import BeenhereIcon from "@mui/icons-material/Beenhere";
import GetItemInfo from "@/components/dashboard/roadItems/operator/Actions/Create/Forms/GetItemInfo";
import GetItemsForm from "@/components/dashboard/roadItems/operator/Actions/Create/Forms/GetItemsForm";
import GetSubItemsForm from "@/components/dashboard/roadItems/operator/Actions/Create/Forms/GetSubItemsForm";
import GetItemInfo from "@/components/dashboard/roadItems/operator/Actions/Create/Forms/GetItemInfo";
import StyledForm from "@/core/components/StyledForm";
import { useTheme } from "@emotion/react";
import { yupResolver } from "@hookform/resolvers/yup";
import BeenhereIcon from "@mui/icons-material/Beenhere";
import ExitToAppIcon from "@mui/icons-material/ExitToApp";
import FileCopyIcon from "@mui/icons-material/FileCopy";
import InfoIcon from "@mui/icons-material/Info";
import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile";
import KeyboardDoubleArrowRightIcon from "@mui/icons-material/KeyboardDoubleArrowRight";
import { Box, Button, DialogActions, DialogContent, Tab, Tabs, useMediaQuery } from "@mui/material";
import { format } from "date-fns";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { mixed, number, object, string } from "yup";
function TabPanel(props) {
const { children, value, index } = props;
@@ -29,24 +29,7 @@ const validationSchema = object({
item_id: number().required("نوع آیتم را مشخص کنید!"),
sub_item_id: number().required("اقدام انجام شده را مشخص کنید!"),
amount: string().required("وارد کردن مقدار الزامیست!"),
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, "حداقل یک کد راهدار باید وارد شود!"), // پیام خطا برای زمانی که شرط تست برقرار باشد
mission_id: object().required("ماموریت را مشخص کنید!"),
activity_time: string().test("activity-time-conditional", "لطفا زمان فعالیت را انتخاب کنید!", function (value) {
const { is_gasht } = this.options.context; // دسترسی به context
if (is_gasht) {
@@ -110,10 +93,9 @@ const CreateFormContent = ({ setOpen, onSubmit, is_gasht = false }) => {
start_point: "",
end_point: "",
...(!is_gasht && {
mission_id: null,
activity_time: "",
activity_date: "",
cmms_machines: [],
rahdaran_id: [],
}),
};
@@ -139,8 +121,6 @@ const CreateFormContent = ({ setOpen, onSubmit, is_gasht = false }) => {
"activity_date",
"before_image",
"after_image",
"cmms_machines",
"rahdaran_id",
"start_point",
"end_point",
];
@@ -195,20 +175,9 @@ const CreateFormContent = ({ setOpen, onSubmit, is_gasht = false }) => {
}
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[`activity_time`] = format(new Date(result.activity_time), "HH:mm");
result.mission_id = result.mission_id.id
} else {
delete result.rahdaran_id;
delete result.cmms_machines;
delete result.activity_date;
delete result.activity_time;
}

View File

@@ -1,173 +1,173 @@
import { FormControl, FormHelperText, Grid } from "@mui/material";
import UploadSystem from "@/core/components/UploadSystem";
import { Controller } from "react-hook-form";
import React, { useEffect, useState } from "react";
const ImageUpload = ({ control, setValue, errors, getValues, beforeImage = null, afterImage = null }) => {
const [beforeImg, setBeforeImg] = useState(beforeImage ? beforeImage : null);
const [beforeFileType, setBeforeFileType] = useState(beforeImage ? "image/" : null);
const [beforeFileName, setBeforeFileName] = useState(null);
const [showBeforeImage, setShowBeforeImage] = useState(!beforeImage);
const [afterImg, setAfterImg] = useState(afterImage ? afterImage : null);
const [afterFileType, setAfterFileType] = useState(afterImage ? "image/" : null);
const [afterFileName, setAfterFileName] = useState(null);
const [showAfterImage, setShowAfterImage] = useState(!afterImage);
useEffect(() => {
const beforeImage = getValues("before_image");
const afterImage = getValues("after_image");
if (beforeImage) {
setShowBeforeImage(false);
if (typeof beforeImage === "string") {
setBeforeImg(beforeImage);
setBeforeFileType("image/");
} else if (beforeImage instanceof File) {
setBeforeImg(URL.createObjectURL(beforeImage));
setBeforeFileType(beforeImage.type);
}
}
if (afterImage) {
setShowAfterImage(false);
if (typeof afterImage === "string") {
setAfterImg(afterImage);
setAfterFileType("image/");
} else if (afterImage instanceof File) {
setAfterImg(URL.createObjectURL(afterImage));
setAfterFileType(afterImage.type);
}
}
}, [getValues]);
const handleBeforeFileChange = (event) => {
const uploadedFile = event.target?.files?.[0];
if (uploadedFile) {
const fileType = event.target?.files?.[0].type;
const fileName = event.target?.files?.[0].name;
setBeforeImg(URL.createObjectURL(uploadedFile));
setBeforeFileType(fileType);
setBeforeFileName(fileName);
setValue("before_image", uploadedFile);
setShowBeforeImage(false);
}
};
const handleAfterFileChange = (event) => {
const uploadedFile = event.target?.files?.[0];
if (uploadedFile) {
const fileType = event.target?.files?.[0].type;
const fileName = event.target?.files?.[0].name;
setAfterImg(URL.createObjectURL(uploadedFile));
setAfterFileType(fileType);
setAfterFileName(fileName);
setValue("after_image", uploadedFile);
setShowAfterImage(false);
}
};
return (
<Grid container spacing={2}>
<Grid item xs={12} md={6}>
<Controller
name="before_image"
control={control}
render={({ field: { value, onChange } }) => {
return (
<FormControl
error={errors.before_image}
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
}}
>
<FormHelperText
sx={{
fontSize: 12,
border: 1,
borderBottom: 0,
borderColor: "divider",
px: 2,
py: 0.5,
borderRadius: 2,
borderBottomRightRadius: 0,
borderBottomLeftRadius: 0,
}}
id="before_image"
>
عکس قبل از اقدام
</FormHelperText>
<UploadSystem
selectedImage={beforeImg}
handleUploadChange={handleBeforeFileChange}
fileType={beforeFileType}
fileName={beforeFileName}
setSelectedImage={setBeforeImg}
imageSize={[250, 150]}
setShowAddIcon={setShowBeforeImage}
showAddIcon={showBeforeImage}
/>
<FormHelperText id="before_image">
{errors.before_image ? errors.before_image.message : null}
</FormHelperText>
</FormControl>
);
}}
/>
</Grid>
<Grid item xs={12} md={6}>
<Controller
name="after_image"
control={control}
render={({ field: { value, onChange } }) => {
return (
<FormControl
error={errors.before_image}
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
}}
>
<FormHelperText
sx={{
fontSize: 12,
border: 1,
borderBottom: 0,
borderColor: "divider",
px: 2,
py: 0.5,
borderRadius: 2,
borderBottomRightRadius: 0,
borderBottomLeftRadius: 0,
}}
id="before_image"
>
عکس بعد از اقدام
</FormHelperText>
<UploadSystem
selectedImage={afterImg}
handleUploadChange={handleAfterFileChange}
fileType={afterFileType}
fileName={afterFileName}
setSelectedImage={setAfterImg}
imageSize={[250, 150]}
setShowAddIcon={setShowAfterImage}
showAddIcon={showAfterImage}
/>
<FormHelperText id="after_image">
{errors.after_image ? errors.after_image.message : null}
</FormHelperText>
</FormControl>
);
}}
/>
</Grid>
</Grid>
);
};
export default ImageUpload;
import { FormControl, FormHelperText, Grid } from "@mui/material";
import UploadSystem from "@/core/components/UploadSystem";
import { Controller } from "react-hook-form";
import React, { useEffect, useState } from "react";
const ImageUpload = ({ control, setValue, errors, getValues, beforeImage = null, afterImage = null }) => {
const [beforeImg, setBeforeImg] = useState(beforeImage ? beforeImage : null);
const [beforeFileType, setBeforeFileType] = useState(beforeImage ? "image/" : null);
const [beforeFileName, setBeforeFileName] = useState(null);
const [showBeforeImage, setShowBeforeImage] = useState(!beforeImage);
const [afterImg, setAfterImg] = useState(afterImage ? afterImage : null);
const [afterFileType, setAfterFileType] = useState(afterImage ? "image/" : null);
const [afterFileName, setAfterFileName] = useState(null);
const [showAfterImage, setShowAfterImage] = useState(!afterImage);
useEffect(() => {
const beforeImage = getValues("before_image");
const afterImage = getValues("after_image");
if (beforeImage) {
setShowBeforeImage(false);
if (typeof beforeImage === "string") {
setBeforeImg(beforeImage);
setBeforeFileType("image/");
} else if (beforeImage instanceof File) {
setBeforeImg(URL.createObjectURL(beforeImage));
setBeforeFileType(beforeImage.type);
}
}
if (afterImage) {
setShowAfterImage(false);
if (typeof afterImage === "string") {
setAfterImg(afterImage);
setAfterFileType("image/");
} else if (afterImage instanceof File) {
setAfterImg(URL.createObjectURL(afterImage));
setAfterFileType(afterImage.type);
}
}
}, [getValues]);
const handleBeforeFileChange = (event) => {
const uploadedFile = event.target?.files?.[0];
if (uploadedFile) {
const fileType = event.target?.files?.[0].type;
const fileName = event.target?.files?.[0].name;
setBeforeImg(URL.createObjectURL(uploadedFile));
setBeforeFileType(fileType);
setBeforeFileName(fileName);
setValue("before_image", uploadedFile);
setShowBeforeImage(false);
}
};
const handleAfterFileChange = (event) => {
const uploadedFile = event.target?.files?.[0];
if (uploadedFile) {
const fileType = event.target?.files?.[0].type;
const fileName = event.target?.files?.[0].name;
setAfterImg(URL.createObjectURL(uploadedFile));
setAfterFileType(fileType);
setAfterFileName(fileName);
setValue("after_image", uploadedFile);
setShowAfterImage(false);
}
};
return (
<Grid container spacing={2}>
<Grid item xs={12} md={6}>
<Controller
name="before_image"
control={control}
render={({ field: { value, onChange } }) => {
return (
<FormControl
error={errors.before_image}
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
}}
>
<FormHelperText
sx={{
fontSize: 12,
border: 1,
borderBottom: 0,
borderColor: "divider",
px: 2,
py: 0.5,
borderRadius: 2,
borderBottomRightRadius: 0,
borderBottomLeftRadius: 0,
}}
id="before_image"
>
عکس قبل از اقدام
</FormHelperText>
<UploadSystem
selectedImage={beforeImg}
handleUploadChange={handleBeforeFileChange}
fileType={beforeFileType}
fileName={beforeFileName}
setSelectedImage={setBeforeImg}
imageSize={[250, 150]}
setShowAddIcon={setShowBeforeImage}
showAddIcon={showBeforeImage}
/>
<FormHelperText id="before_image">
{errors.before_image ? errors.before_image.message : null}
</FormHelperText>
</FormControl>
);
}}
/>
</Grid>
<Grid item xs={12} md={6}>
<Controller
name="after_image"
control={control}
render={({ field: { value, onChange } }) => {
return (
<FormControl
error={errors.before_image}
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
}}
>
<FormHelperText
sx={{
fontSize: 12,
border: 1,
borderBottom: 0,
borderColor: "divider",
px: 2,
py: 0.5,
borderRadius: 2,
borderBottomRightRadius: 0,
borderBottomLeftRadius: 0,
}}
id="before_image"
>
عکس بعد از اقدام
</FormHelperText>
<UploadSystem
selectedImage={afterImg}
handleUploadChange={handleAfterFileChange}
fileType={afterFileType}
fileName={afterFileName}
setSelectedImage={setAfterImg}
imageSize={[250, 150]}
setShowAddIcon={setShowAfterImage}
showAddIcon={showAfterImage}
/>
<FormHelperText id="after_image">
{errors.after_image ? errors.after_image.message : null}
</FormHelperText>
</FormControl>
);
}}
/>
</Grid>
</Grid>
);
};
export default ImageUpload;

View File

@@ -0,0 +1,18 @@
import { Done } from "@mui/icons-material";
import { Button } from "@mui/material";
const Allocate = ({ row, setMission, setOpenDialog }) => {
const handleClick = () => {
setMission(row.original);
setOpenDialog(false);
};
return (
<>
<Button color="primary" sx={{ textTransform: "unset", alignSelf: "center" }} onClick={handleClick} startIcon={<Done />}>
انتخاب
</Button>
</>
);
};
export default Allocate;

View File

@@ -0,0 +1,6 @@
import Allocate from "./Allocate";
const RowActions = ({ row, setMission, setOpenDialog }) => {
return <Allocate row={row} setMission={setMission} setOpenDialog={setOpenDialog} />;
};
export default RowActions;

View File

@@ -0,0 +1,111 @@
import DataTableWithAuth from "@/core/components/DataTableWithAuth";
import { GET_ROAD_MISSIONS_OPERATOR_LIST } from "@/core/utils/routes";
import { Box } from "@mui/material";
import { useMemo } from "react";
import RowActions from "./RowActions";
import moment from "jalali-moment";
const MissionList = ({ setMission, setOpenDialog }) => {
const columns = useMemo(
() => [
{
accessorKey: "id",
header: "کد یکتا",
id: "id",
enableColumnFilter: true,
datatype: "text",
filterMode: "equals",
columnFilterModeOptions: ["equals", "contains"],
grow: false,
size: 100,
},
{
accessorKey: "explanation",
header: "موضوع",
id: "explanation",
enableColumnFilter: false,
datatype: "numeric",
filterMode: "equals",
grow: false,
size: 100,
},
{
accessorKey: "zone",
header: "محدوده",
id: "zone",
enableColumnFilter: true,
datatype: "numeric",
filterMode: "equals",
sortDescFirst: true,
grow: false,
size: 100,
columnSelectOption: () => {
return missionRegions.map((region) => ({
value: region.id,
label: region.name_fa,
}));
},
Cell: ({ row }) => row.original.zone_fa,
},
{
accessorFn: (row) =>
row.type == 1
? moment(row.start_date).locale("fa").format("HH:mm | yyyy/MM/DD")
: moment(row.start_date).locale("fa").format("yyyy/MM/DD"),
header: "تاریخ شروع",
id: "start_date",
enableColumnFilter: true,
datatype: "date",
filterMode: "between",
grow: false,
size: 100,
},
{
accessorFn: (row) =>
row.type == 1
? moment(row.end_date).locale("fa").format("HH:mm | yyyy/MM/DD")
: moment(row.end_date).locale("fa").format("yyyy/MM/DD"),
header: "تاریخ پایان",
id: "end_date",
enableColumnFilter: true,
datatype: "date",
filterMode: "between",
grow: false,
size: 100,
},
{
accessorKey: "end_point",
header: "مقصد",
id: "end_point",
enableColumnFilter: false,
datatype: "numeric",
filterMode: "equals",
grow: false,
size: 100,
},
],
[]
);
return (
<>
<Box sx={{ mt: 3, p: 1 }}>
<DataTableWithAuth
need_filter={true}
table_title="لیست ماموریت ها"
columns={columns}
sorting={[{ id: "id", desc: true }]}
table_url={GET_ROAD_MISSIONS_OPERATOR_LIST}
page_name={"roadItemsOperator"}
table_name={"roadItemsOperatorListMissionList"}
enableRowActions
positionActionsColumn={"first"}
RowActions={(props) => (
<RowActions {...props} setMission={setMission} setOpenDialog={setOpenDialog} />
)}
/>
</Box>
</>
);
};
export default MissionList;

View File

@@ -0,0 +1,40 @@
import { Close, Edit } from "@mui/icons-material";
import { Button, Dialog, IconButton } from "@mui/material";
import { useState } from "react";
import MissionList from "./MissionsList";
const MissionsDialog = ({ setMission, mode }) => {
const [open, setOpen] = useState(false);
return (
<>
{mode == "edit" ? (
<IconButton onClick={() => setOpen(true)}>
<Edit />
</IconButton>
) : (
<Button onClick={() => setOpen(true)} variant="contained" fullWidth>
ماموریت انتخاب کنید
</Button>
)}
<Dialog open={open} fullWidth maxWidth="sm">
<IconButton
aria-label="close"
onClick={() => setOpen(false)}
sx={(theme) => ({
position: "absolute",
right: 8,
top: 8,
zIndex: 50,
color: theme.palette.grey[500],
})}
>
<Close />
</IconButton>
{open && (
<MissionList setMission={setMission} setOpenDialog={setOpen} />
)}
</Dialog>
</>
);
};
export default MissionsDialog;

View File

@@ -1,43 +1,43 @@
import { Box, Chip, Divider, Grid, Typography } from "@mui/material";
import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile";
import FileCopyIcon from "@mui/icons-material/FileCopy";
const PreviousStatesInfo = ({ itemsList, subItemsList }) => {
return (
<Grid container spacing={2} sx={{ alignItems: "center", justifyContent: "space-around" }}>
<Grid item xs={12} sm={12} sx={{ display: "flex", alignItems: "center" }}>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Chip
icon={<InsertDriveFileIcon />}
label={
<Typography variant="body2" sx={{ fontWeight: 600, color: "grey.700" }}>
آیتم انتخاب شده
</Typography>
}
/>
</Box>
<Divider sx={{ flex: 1, mx: 2 }} />
<Typography variant="body2" sx={{ fontWeight: 600, color: "grey.800" }}>
{itemsList.name || "هیچ آیتمی انتخاب نشده است"}
</Typography>
</Grid>
<Grid item xs={12} sm={12} sx={{ display: "flex", alignItems: "center" }}>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Chip
icon={<FileCopyIcon />}
label={
<Typography variant="body2" sx={{ fontWeight: 600, color: "grey.700" }}>
اقدام انجام شده
</Typography>
}
/>
</Box>
<Divider sx={{ flex: 1, mx: 2 }} />
<Typography variant="body2" sx={{ fontWeight: 600, color: "grey.800" }}>
{subItemsList?.name || "هیچ اقدامی انتخاب نشده است"}
</Typography>
</Grid>
</Grid>
);
};
export default PreviousStatesInfo;
import { Box, Chip, Divider, Grid, Typography } from "@mui/material";
import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile";
import FileCopyIcon from "@mui/icons-material/FileCopy";
const PreviousStatesInfo = ({ itemsList, subItemsList }) => {
return (
<Grid container spacing={2} sx={{ alignItems: "center", justifyContent: "space-around" }}>
<Grid item xs={12} sm={12} sx={{ display: "flex", alignItems: "center" }}>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Chip
icon={<InsertDriveFileIcon />}
label={
<Typography variant="body2" sx={{ fontWeight: 600, color: "grey.700" }}>
آیتم انتخاب شده
</Typography>
}
/>
</Box>
<Divider sx={{ flex: 1, mx: 2 }} />
<Typography variant="body2" sx={{ fontWeight: 600, color: "grey.800" }}>
{itemsList.name || "هیچ آیتمی انتخاب نشده است"}
</Typography>
</Grid>
<Grid item xs={12} sm={12} sx={{ display: "flex", alignItems: "center" }}>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Chip
icon={<FileCopyIcon />}
label={
<Typography variant="body2" sx={{ fontWeight: 600, color: "grey.700" }}>
اقدام انجام شده
</Typography>
}
/>
</Box>
<Divider sx={{ flex: 1, mx: 2 }} />
<Typography variant="body2" sx={{ fontWeight: 600, color: "grey.800" }}>
{subItemsList?.name || "هیچ اقدامی انتخاب نشده است"}
</Typography>
</Grid>
</Grid>
);
};
export default PreviousStatesInfo;

View File

@@ -1,124 +1,115 @@
import { Grid, Stack } from "@mui/material";
import ImageUpload from "./ImageUpload";
import MuiDatePicker from "@/core/components/MuiDatePicker";
import MuiTimePicker from "@/core/components/MuiTimePicker";
import MapInfoTwoMarker from "@/core/components/MapInfoTwoMarker";
import MapInfoOneMarker from "@/core/components/MapInfoOneMarker";
import { Controller } from "react-hook-form";
import CarCode from "@/core/components/CarCode";
import RahdarCode from "@/core/components/RahdarCode";
import PreviousStatesInfo from "./PreviousStatesInfo";
import NumberField from "@/core/components/NumberField";
const GetItemInfo = ({ register, itemsList, subItemsList, control, setValue, errors, watch, getValues, is_gasht }) => {
return (
<Stack spacing={3}>
<Stack>
<PreviousStatesInfo itemsList={itemsList} subItemsList={subItemsList} />
</Stack>
<Stack>
<NumberField
{...register("amount")}
label={`مقدار (${subItemsList.unit})`}
error={!!errors.amount}
value={watch("amount")}
type="text"
size={"small"}
unit={subItemsList.unit}
placeholder={`مقدار را وارد کنید`}
inputProps={{
inputMode: "number",
min: 0,
pattern: "[0-9]*",
}}
onChange={(event) => {
if (!isNaN(event.target.value)) {
setValue("amount", event.target.value);
} else {
setValue("amount", watch("amount"));
}
}}
helperText={errors.amount ? errors.amount.message : null}
variant="outlined"
fullWidth
/>
</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} />
) : null}
</Stack>
{!is_gasht ? (
<Stack>
<Grid container spacing={2}>
<Grid item xs={12} md={6}>
<MuiDatePicker
name="activity_date"
error={errors.activity_date ? errors.activity_date.message : null}
value={watch("activity_date")}
placeholder={"تاریخ فعالیت را وارد کنید"}
label={"تاریخ فعالیت"}
setFieldValue={setValue}
helperText={errors.activity_date ? errors.activity_date.message : null}
/>
</Grid>
<Grid item xs={12} md={6}>
<MuiTimePicker
value={watch("activity_time")}
name="activity_time"
error={errors.activity_time ? errors.activity_time.message : null}
placeholder={"زمان فعالیت را وارد کنید"}
label={"زمان فعالیت"}
setFieldValue={setValue}
helperText={errors.activity_time ? errors.activity_time.message : null}
/>
</Grid>
</Grid>
</Stack>
) : null}
<Stack>
{subItemsList?.needs_end_point === 1 ? (
<MapInfoTwoMarker setValue={setValue} errors={errors} />
) : (
<MapInfoOneMarker setValue={setValue} errors={errors} />
)}
</Stack>
</Stack>
);
};
export default GetItemInfo;
import MapInfoOneMarker from "@/core/components/MapInfoOneMarker";
import MapInfoTwoMarker from "@/core/components/MapInfoTwoMarker";
import MuiDatePicker from "@/core/components/MuiDatePicker";
import MuiTimePicker from "@/core/components/MuiTimePicker";
import NumberField from "@/core/components/NumberField";
import { Chip, Divider, FormHelperText, Grid, Stack, Typography } from "@mui/material";
import ImageUpload from "./ImageUpload";
import MissionsDialog from "./MissionsDialog";
import PreviousStatesInfo from "./PreviousStatesInfo";
import { Controller } from "react-hook-form";
const GetItemInfo = ({ register, itemsList, subItemsList, control, setValue, errors, watch, getValues, is_gasht }) => {
return (
<Stack spacing={3}>
<Stack>
<PreviousStatesInfo itemsList={itemsList} subItemsList={subItemsList} />
</Stack>
<Controller
name="mission_id"
control={control}
render={({ field: { onChange, value }, fieldState: { error } }) => {
return value ? (
<Stack spacing={1}>
<Stack direction={"row"} alignItems={"center"} spacing={1} >
<Chip
label={
value
? `کد ماموریت: ${value.id}`
: "ماموریت انتخاب نشده"
}
/>
<Divider sx={{ flex: 1 }} />
<MissionsDialog setMission={m => onChange(m)} mode={"edit"} />
</Stack>
<FormHelperText error={!!error} >{error ? error.message : null}</FormHelperText>
</Stack>
) : (
<Stack spacing={1}>
<MissionsDialog setMission={m => onChange(m)} />
<FormHelperText error={!!error} >{error ? error.message : null}</FormHelperText>
</Stack>
)
}}
/>
<Stack >
<NumberField
{...register("amount")}
label={`مقدار (${subItemsList.unit})`}
error={!!errors.amount}
value={watch("amount")}
type="text"
size={"small"}
unit={subItemsList.unit}
placeholder={`مقدار را وارد کنید`}
inputProps={{
inputMode: "number",
min: 0,
pattern: "[0-9]*",
}}
onChange={(event) => {
if (!isNaN(event.target.value)) {
setValue("amount", event.target.value);
} else {
setValue("amount", watch("amount"));
}
}}
helperText={errors.amount ? errors.amount.message : null}
variant="outlined"
fullWidth
/>
</Stack >
{!is_gasht ? (
<Stack>
<Grid container spacing={2}>
<Grid item xs={12} md={6}>
<MuiDatePicker
name="activity_date"
error={errors.activity_date ? errors.activity_date.message : null}
value={watch("activity_date")}
placeholder={"تاریخ فعالیت را وارد کنید"}
label={"تاریخ فعالیت"}
setFieldValue={setValue}
helperText={errors.activity_date ? errors.activity_date.message : null}
/>
</Grid>
<Grid item xs={12} md={6}>
<MuiTimePicker
value={watch("activity_time")}
name="activity_time"
error={errors.activity_time ? errors.activity_time.message : null}
placeholder={"زمان فعالیت را وارد کنید"}
label={"زمان فعالیت"}
setFieldValue={setValue}
helperText={errors.activity_time ? errors.activity_time.message : null}
/>
</Grid>
</Grid>
</Stack>
) : null}
<Stack>
{subItemsList.needs_image ? (
<ImageUpload setValue={setValue} control={control} errors={errors} getValues={getValues} />
) : null}
</Stack>
<Stack>
{subItemsList?.needs_end_point === 1 ? (
<MapInfoTwoMarker setValue={setValue} errors={errors} />
) : (
<MapInfoOneMarker setValue={setValue} errors={errors} />
)}
</Stack>
</Stack >
);
};
export default GetItemInfo;

View File

@@ -129,8 +129,8 @@ const OperatorList = () => {
props.dependencyFieldValue.value === ""
? "empty"
: loadingSubItemsList
? "loading"
: props.filterParameters.value
? "loading"
: props.filterParameters.value
}
columnSelectOption={getColumnSelectOptions}
/>
@@ -219,60 +219,6 @@ const OperatorList = () => {
);
},
},
{
header: "خودرو ها",
id: "cmmsMachines__machine_code",
enableColumnFilter: true,
datatype: "text",
filterMode: "contains",
enableSorting: false,
columnFilterModeOptions: ["equals", "contains"],
grow: false,
size: 100,
muiTableBodyCellProps: {
sx: {
borderLeft: "1px solid #e1e1e1",
py: 0,
"&:first-of-type": {
borderLeft: "unset",
},
},
},
Cell: ({ renderedCellValue, row }) => {
return (
<Stack alignItems={"center"} justifyContent={"center"}>
<MachinesCodeDialog rowId={row.original.id} />
</Stack>
);
},
},
{
header: "راهداران",
id: "rahdaran__code",
enableColumnFilter: true,
enableSorting: false,
datatype: "text",
filterMode: "contains",
columnFilterModeOptions: ["equals", "contains"],
grow: false,
size: 100,
muiTableBodyCellProps: {
sx: {
borderLeft: "1px solid #e1e1e1",
py: 0,
"&:first-of-type": {
borderLeft: "unset",
},
},
},
Cell: ({ renderedCellValue, row }) => {
return (
<Stack alignItems={"center"} justifyContent={"center"}>
<RahdaranDialog rowId={row.original.id} />
</Stack>
);
},
},
{
accessorFn: (row) => moment(row.activity_date_time).locale("fa").format("HH:mm | yyyy/MM/DD"),
header: "تاریخ فعالیت", // Start Date

View File

@@ -1,36 +1,15 @@
import { Button, DialogActions, DialogContent, Stack } from "@mui/material";
import ImageUpload from "@/components/dashboard/roadItems/operator/Actions/Create/Forms/ImageUpload";
import NumberField from "@/core/components/NumberField";
import { Controller, useForm } from "react-hook-form";
import CarCode from "@/core/components/CarCode";
import RahdarCode from "@/core/components/RahdarCode";
import MapInfoTwoMarker from "@/core/components/MapInfoTwoMarker";
import MapInfoOneMarker from "@/core/components/MapInfoOneMarker";
import MapInfoTwoMarker from "@/core/components/MapInfoTwoMarker";
import NumberField from "@/core/components/NumberField";
import StyledForm from "@/core/components/StyledForm";
import React from "react";
import { yupResolver } from "@hookform/resolvers/yup";
import { array, mixed, object, string } from "yup";
import { Button, DialogActions, DialogContent, Stack } from "@mui/material";
import { useForm } from "react-hook-form";
import { mixed, object, string } from "yup";
import ImageUpload from "../../Actions/ObservedGashtCreate/RowActions/ImageUpload";
const validationSchema = object({
amount: string().required("وارد کردن مقدار الزامیست!"),
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) {
@@ -124,42 +103,6 @@ const EditFormCreate = ({ defaultData, subItem, onSubmitBase, defaultValues, set
fullWidth
/>
</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

View File

@@ -8,7 +8,7 @@ const Toolbar = ({ table, filterData, mutate }) => {
<Stack direction={"row"} spacing={1}>
<PrintExcel table={table} filterData={filterData} />
<OperatorCreate mutate={mutate} />
<ObservedGashtCreate mutate={mutate} />
{/* <ObservedGashtCreate mutate={mutate} /> */}
</Stack>
);
};

View File

@@ -127,8 +127,8 @@ const SupervisorList = () => {
props.dependencyFieldValue?.value === ""
? "empty"
: loadingEdaratList
? "loading"
: props.filterParameters.value
? "loading"
: props.filterParameters.value
}
columnSelectOption={getColumnSelectOptions}
/>
@@ -227,8 +227,8 @@ const SupervisorList = () => {
props.dependencyFieldValue.value === ""
? "empty"
: loadingSubItemsList
? "loading"
: props.filterParameters.value
? "loading"
: props.filterParameters.value
}
columnSelectOption={getColumnSelectOptions}
/>
@@ -316,60 +316,6 @@ const SupervisorList = () => {
);
},
},
{
header: "خودرو ها",
id: "cmmsMachines__machine_code",
enableColumnFilter: true,
datatype: "text",
filterMode: "contains",
enableSorting: false,
columnFilterModeOptions: ["equals", "contains"],
grow: false,
size: 100,
muiTableBodyCellProps: {
sx: {
borderLeft: "1px solid #e1e1e1",
py: 0,
"&:first-of-type": {
borderLeft: "unset",
},
},
},
Cell: ({ renderedCellValue, row }) => {
return (
<Stack alignItems={"center"} justifyContent={"center"}>
<MachinesCodeDialog rowId={row.original.id} />
</Stack>
);
},
},
{
header: "راهداران",
id: "rahdaran__code",
enableColumnFilter: true,
enableSorting: false,
datatype: "text",
filterMode: "contains",
columnFilterModeOptions: ["equals", "contains"],
grow: false,
size: 100,
muiTableBodyCellProps: {
sx: {
borderLeft: "1px solid #e1e1e1",
py: 0,
"&:first-of-type": {
borderLeft: "unset",
},
},
},
Cell: ({ renderedCellValue, row }) => {
return (
<Stack alignItems={"center"} justifyContent={"center"}>
<RahdaranDialog rowId={row.original.id} />
</Stack>
);
},
},
{
accessorFn: (row) => moment(row.activity_date_time).locale("fa").format("HH:mm | yyyy/MM/DD"),
header: "تاریخ فعالیت", // Start Date

View File

@@ -1,5 +1,6 @@
import MuiDatePicker from "@/core/components/MuiDatePicker";
import MuiTimePicker from "@/core/components/MuiTimePicker";
import { makeDateTime } from "@/core/utils/makeDateTime";
import { Grid } from "@mui/material";
import { Controller, useWatch } from "react-hook-form";

View File

@@ -1,7 +1,7 @@
import { Box, Button, Chip, DialogActions, DialogContent, Divider, Stack, Typography } from "@mui/material";
import DriversDialog from "./DriversDialog";
import MachinesDialog from "./MachinesDialog";
import { useState } from "react";
import MachinesDialog from "./MachinesDialog";
const MachineAndDriver = ({ setTabState, allData, setAllData, handlePrev }) => {
const [machine, setMachine] = useState(allData.machine);

View File

@@ -1,5 +1,5 @@
export const missionCategoryTypes = [
{ id: 1, name_fa: "فعالیت روزانه" },
{ id: 2, name_fa: "گشت راهداری" },
{ id: 3, name_fa: "واکنش سریع" },
// { id: 3, name_fa: "واکنش سریع" },
];