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 GetItemInfo from "@/components/dashboard/roadItems/operator/Actions/Create/Forms/GetItemInfo";
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 GetItemsForm from "@/components/dashboard/roadItems/operator/Actions/Create/Forms/GetItemsForm"; import GetItemsForm from "@/components/dashboard/roadItems/operator/Actions/Create/Forms/GetItemsForm";
import GetSubItemsForm from "@/components/dashboard/roadItems/operator/Actions/Create/Forms/GetSubItemsForm"; 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 { format } from "date-fns";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { mixed, number, object, string } from "yup";
function TabPanel(props) { function TabPanel(props) {
const { children, value, index } = props; const { children, value, index } = props;
@@ -29,24 +29,7 @@ const validationSchema = object({
item_id: number().required("نوع آیتم را مشخص کنید!"), item_id: number().required("نوع آیتم را مشخص کنید!"),
sub_item_id: number().required("اقدام انجام شده را مشخص کنید!"), sub_item_id: number().required("اقدام انجام شده را مشخص کنید!"),
amount: string().required("وارد کردن مقدار الزامیست!"), amount: string().required("وارد کردن مقدار الزامیست!"),
cmms_machines: array() mission_id: object().required("ماموریت را مشخص کنید!"),
.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) { activity_time: string().test("activity-time-conditional", "لطفا زمان فعالیت را انتخاب کنید!", function (value) {
const { is_gasht } = this.options.context; // دسترسی به context const { is_gasht } = this.options.context; // دسترسی به context
if (is_gasht) { if (is_gasht) {
@@ -110,10 +93,9 @@ const CreateFormContent = ({ setOpen, onSubmit, is_gasht = false }) => {
start_point: "", start_point: "",
end_point: "", end_point: "",
...(!is_gasht && { ...(!is_gasht && {
mission_id: null,
activity_time: "", activity_time: "",
activity_date: "", activity_date: "",
cmms_machines: [],
rahdaran_id: [],
}), }),
}; };
@@ -139,8 +121,6 @@ const CreateFormContent = ({ setOpen, onSubmit, is_gasht = false }) => {
"activity_date", "activity_date",
"before_image", "before_image",
"after_image", "after_image",
"cmms_machines",
"rahdaran_id",
"start_point", "start_point",
"end_point", "end_point",
]; ];
@@ -195,20 +175,9 @@ const CreateFormContent = ({ setOpen, onSubmit, is_gasht = false }) => {
} }
if (!is_gasht) { 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[`activity_time`] = format(new Date(result.activity_time), "HH:mm");
result.mission_id = result.mission_id.id
} else { } else {
delete result.rahdaran_id;
delete result.cmms_machines;
delete result.activity_date; delete result.activity_date;
delete result.activity_time; delete result.activity_time;
} }

View File

@@ -1,173 +1,173 @@
import { FormControl, FormHelperText, Grid } from "@mui/material"; import { FormControl, FormHelperText, Grid } from "@mui/material";
import UploadSystem from "@/core/components/UploadSystem"; import UploadSystem from "@/core/components/UploadSystem";
import { Controller } from "react-hook-form"; import { Controller } from "react-hook-form";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
const ImageUpload = ({ control, setValue, errors, getValues, beforeImage = null, afterImage = null }) => { const ImageUpload = ({ control, setValue, errors, getValues, beforeImage = null, afterImage = null }) => {
const [beforeImg, setBeforeImg] = useState(beforeImage ? beforeImage : null); const [beforeImg, setBeforeImg] = useState(beforeImage ? beforeImage : null);
const [beforeFileType, setBeforeFileType] = useState(beforeImage ? "image/" : null); const [beforeFileType, setBeforeFileType] = useState(beforeImage ? "image/" : null);
const [beforeFileName, setBeforeFileName] = useState(null); const [beforeFileName, setBeforeFileName] = useState(null);
const [showBeforeImage, setShowBeforeImage] = useState(!beforeImage); const [showBeforeImage, setShowBeforeImage] = useState(!beforeImage);
const [afterImg, setAfterImg] = useState(afterImage ? afterImage : null); const [afterImg, setAfterImg] = useState(afterImage ? afterImage : null);
const [afterFileType, setAfterFileType] = useState(afterImage ? "image/" : null); const [afterFileType, setAfterFileType] = useState(afterImage ? "image/" : null);
const [afterFileName, setAfterFileName] = useState(null); const [afterFileName, setAfterFileName] = useState(null);
const [showAfterImage, setShowAfterImage] = useState(!afterImage); const [showAfterImage, setShowAfterImage] = useState(!afterImage);
useEffect(() => { useEffect(() => {
const beforeImage = getValues("before_image"); const beforeImage = getValues("before_image");
const afterImage = getValues("after_image"); const afterImage = getValues("after_image");
if (beforeImage) { if (beforeImage) {
setShowBeforeImage(false); setShowBeforeImage(false);
if (typeof beforeImage === "string") { if (typeof beforeImage === "string") {
setBeforeImg(beforeImage); setBeforeImg(beforeImage);
setBeforeFileType("image/"); setBeforeFileType("image/");
} else if (beforeImage instanceof File) { } else if (beforeImage instanceof File) {
setBeforeImg(URL.createObjectURL(beforeImage)); setBeforeImg(URL.createObjectURL(beforeImage));
setBeforeFileType(beforeImage.type); setBeforeFileType(beforeImage.type);
} }
} }
if (afterImage) { if (afterImage) {
setShowAfterImage(false); setShowAfterImage(false);
if (typeof afterImage === "string") { if (typeof afterImage === "string") {
setAfterImg(afterImage); setAfterImg(afterImage);
setAfterFileType("image/"); setAfterFileType("image/");
} else if (afterImage instanceof File) { } else if (afterImage instanceof File) {
setAfterImg(URL.createObjectURL(afterImage)); setAfterImg(URL.createObjectURL(afterImage));
setAfterFileType(afterImage.type); setAfterFileType(afterImage.type);
} }
} }
}, [getValues]); }, [getValues]);
const handleBeforeFileChange = (event) => { const handleBeforeFileChange = (event) => {
const uploadedFile = event.target?.files?.[0]; const uploadedFile = event.target?.files?.[0];
if (uploadedFile) { if (uploadedFile) {
const fileType = event.target?.files?.[0].type; const fileType = event.target?.files?.[0].type;
const fileName = event.target?.files?.[0].name; const fileName = event.target?.files?.[0].name;
setBeforeImg(URL.createObjectURL(uploadedFile)); setBeforeImg(URL.createObjectURL(uploadedFile));
setBeforeFileType(fileType); setBeforeFileType(fileType);
setBeforeFileName(fileName); setBeforeFileName(fileName);
setValue("before_image", uploadedFile); setValue("before_image", uploadedFile);
setShowBeforeImage(false); setShowBeforeImage(false);
} }
}; };
const handleAfterFileChange = (event) => { const handleAfterFileChange = (event) => {
const uploadedFile = event.target?.files?.[0]; const uploadedFile = event.target?.files?.[0];
if (uploadedFile) { if (uploadedFile) {
const fileType = event.target?.files?.[0].type; const fileType = event.target?.files?.[0].type;
const fileName = event.target?.files?.[0].name; const fileName = event.target?.files?.[0].name;
setAfterImg(URL.createObjectURL(uploadedFile)); setAfterImg(URL.createObjectURL(uploadedFile));
setAfterFileType(fileType); setAfterFileType(fileType);
setAfterFileName(fileName); setAfterFileName(fileName);
setValue("after_image", uploadedFile); setValue("after_image", uploadedFile);
setShowAfterImage(false); setShowAfterImage(false);
} }
}; };
return ( return (
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12} md={6}> <Grid item xs={12} md={6}>
<Controller <Controller
name="before_image" name="before_image"
control={control} control={control}
render={({ field: { value, onChange } }) => { render={({ field: { value, onChange } }) => {
return ( return (
<FormControl <FormControl
error={errors.before_image} error={errors.before_image}
sx={{ sx={{
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "center",
}} }}
> >
<FormHelperText <FormHelperText
sx={{ sx={{
fontSize: 12, fontSize: 12,
border: 1, border: 1,
borderBottom: 0, borderBottom: 0,
borderColor: "divider", borderColor: "divider",
px: 2, px: 2,
py: 0.5, py: 0.5,
borderRadius: 2, borderRadius: 2,
borderBottomRightRadius: 0, borderBottomRightRadius: 0,
borderBottomLeftRadius: 0, borderBottomLeftRadius: 0,
}} }}
id="before_image" id="before_image"
> >
عکس قبل از اقدام عکس قبل از اقدام
</FormHelperText> </FormHelperText>
<UploadSystem <UploadSystem
selectedImage={beforeImg} selectedImage={beforeImg}
handleUploadChange={handleBeforeFileChange} handleUploadChange={handleBeforeFileChange}
fileType={beforeFileType} fileType={beforeFileType}
fileName={beforeFileName} fileName={beforeFileName}
setSelectedImage={setBeforeImg} setSelectedImage={setBeforeImg}
imageSize={[250, 150]} imageSize={[250, 150]}
setShowAddIcon={setShowBeforeImage} setShowAddIcon={setShowBeforeImage}
showAddIcon={showBeforeImage} showAddIcon={showBeforeImage}
/> />
<FormHelperText id="before_image"> <FormHelperText id="before_image">
{errors.before_image ? errors.before_image.message : null} {errors.before_image ? errors.before_image.message : null}
</FormHelperText> </FormHelperText>
</FormControl> </FormControl>
); );
}} }}
/> />
</Grid> </Grid>
<Grid item xs={12} md={6}> <Grid item xs={12} md={6}>
<Controller <Controller
name="after_image" name="after_image"
control={control} control={control}
render={({ field: { value, onChange } }) => { render={({ field: { value, onChange } }) => {
return ( return (
<FormControl <FormControl
error={errors.before_image} error={errors.before_image}
sx={{ sx={{
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "center",
}} }}
> >
<FormHelperText <FormHelperText
sx={{ sx={{
fontSize: 12, fontSize: 12,
border: 1, border: 1,
borderBottom: 0, borderBottom: 0,
borderColor: "divider", borderColor: "divider",
px: 2, px: 2,
py: 0.5, py: 0.5,
borderRadius: 2, borderRadius: 2,
borderBottomRightRadius: 0, borderBottomRightRadius: 0,
borderBottomLeftRadius: 0, borderBottomLeftRadius: 0,
}} }}
id="before_image" id="before_image"
> >
عکس بعد از اقدام عکس بعد از اقدام
</FormHelperText> </FormHelperText>
<UploadSystem <UploadSystem
selectedImage={afterImg} selectedImage={afterImg}
handleUploadChange={handleAfterFileChange} handleUploadChange={handleAfterFileChange}
fileType={afterFileType} fileType={afterFileType}
fileName={afterFileName} fileName={afterFileName}
setSelectedImage={setAfterImg} setSelectedImage={setAfterImg}
imageSize={[250, 150]} imageSize={[250, 150]}
setShowAddIcon={setShowAfterImage} setShowAddIcon={setShowAfterImage}
showAddIcon={showAfterImage} showAddIcon={showAfterImage}
/> />
<FormHelperText id="after_image"> <FormHelperText id="after_image">
{errors.after_image ? errors.after_image.message : null} {errors.after_image ? errors.after_image.message : null}
</FormHelperText> </FormHelperText>
</FormControl> </FormControl>
); );
}} }}
/> />
</Grid> </Grid>
</Grid> </Grid>
); );
}; };
export default ImageUpload; 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 { Box, Chip, Divider, Grid, Typography } from "@mui/material";
import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile"; import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile";
import FileCopyIcon from "@mui/icons-material/FileCopy"; import FileCopyIcon from "@mui/icons-material/FileCopy";
const PreviousStatesInfo = ({ itemsList, subItemsList }) => { const PreviousStatesInfo = ({ itemsList, subItemsList }) => {
return ( return (
<Grid container spacing={2} sx={{ alignItems: "center", justifyContent: "space-around" }}> <Grid container spacing={2} sx={{ alignItems: "center", justifyContent: "space-around" }}>
<Grid item xs={12} sm={12} sx={{ display: "flex", alignItems: "center" }}> <Grid item xs={12} sm={12} sx={{ display: "flex", alignItems: "center" }}>
<Box sx={{ display: "flex", alignItems: "center" }}> <Box sx={{ display: "flex", alignItems: "center" }}>
<Chip <Chip
icon={<InsertDriveFileIcon />} icon={<InsertDriveFileIcon />}
label={ label={
<Typography variant="body2" sx={{ fontWeight: 600, color: "grey.700" }}> <Typography variant="body2" sx={{ fontWeight: 600, color: "grey.700" }}>
آیتم انتخاب شده آیتم انتخاب شده
</Typography> </Typography>
} }
/> />
</Box> </Box>
<Divider sx={{ flex: 1, mx: 2 }} /> <Divider sx={{ flex: 1, mx: 2 }} />
<Typography variant="body2" sx={{ fontWeight: 600, color: "grey.800" }}> <Typography variant="body2" sx={{ fontWeight: 600, color: "grey.800" }}>
{itemsList.name || "هیچ آیتمی انتخاب نشده است"} {itemsList.name || "هیچ آیتمی انتخاب نشده است"}
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} sm={12} sx={{ display: "flex", alignItems: "center" }}> <Grid item xs={12} sm={12} sx={{ display: "flex", alignItems: "center" }}>
<Box sx={{ display: "flex", alignItems: "center" }}> <Box sx={{ display: "flex", alignItems: "center" }}>
<Chip <Chip
icon={<FileCopyIcon />} icon={<FileCopyIcon />}
label={ label={
<Typography variant="body2" sx={{ fontWeight: 600, color: "grey.700" }}> <Typography variant="body2" sx={{ fontWeight: 600, color: "grey.700" }}>
اقدام انجام شده اقدام انجام شده
</Typography> </Typography>
} }
/> />
</Box> </Box>
<Divider sx={{ flex: 1, mx: 2 }} /> <Divider sx={{ flex: 1, mx: 2 }} />
<Typography variant="body2" sx={{ fontWeight: 600, color: "grey.800" }}> <Typography variant="body2" sx={{ fontWeight: 600, color: "grey.800" }}>
{subItemsList?.name || "هیچ اقدامی انتخاب نشده است"} {subItemsList?.name || "هیچ اقدامی انتخاب نشده است"}
</Typography> </Typography>
</Grid> </Grid>
</Grid> </Grid>
); );
}; };
export default PreviousStatesInfo; export default PreviousStatesInfo;

View File

@@ -1,124 +1,115 @@
import { Grid, Stack } from "@mui/material"; import MapInfoOneMarker from "@/core/components/MapInfoOneMarker";
import ImageUpload from "./ImageUpload"; import MapInfoTwoMarker from "@/core/components/MapInfoTwoMarker";
import MuiDatePicker from "@/core/components/MuiDatePicker"; import MuiDatePicker from "@/core/components/MuiDatePicker";
import MuiTimePicker from "@/core/components/MuiTimePicker"; import MuiTimePicker from "@/core/components/MuiTimePicker";
import MapInfoTwoMarker from "@/core/components/MapInfoTwoMarker"; import NumberField from "@/core/components/NumberField";
import MapInfoOneMarker from "@/core/components/MapInfoOneMarker"; import { Chip, Divider, FormHelperText, Grid, Stack, Typography } from "@mui/material";
import { Controller } from "react-hook-form"; import ImageUpload from "./ImageUpload";
import CarCode from "@/core/components/CarCode"; import MissionsDialog from "./MissionsDialog";
import RahdarCode from "@/core/components/RahdarCode"; import PreviousStatesInfo from "./PreviousStatesInfo";
import PreviousStatesInfo from "./PreviousStatesInfo"; import { Controller } from "react-hook-form";
import NumberField from "@/core/components/NumberField";
const GetItemInfo = ({ register, itemsList, subItemsList, control, setValue, errors, watch, getValues, is_gasht }) => {
const GetItemInfo = ({ register, itemsList, subItemsList, control, setValue, errors, watch, getValues, is_gasht }) => { return (
return ( <Stack spacing={3}>
<Stack spacing={3}> <Stack>
<Stack> <PreviousStatesInfo itemsList={itemsList} subItemsList={subItemsList} />
<PreviousStatesInfo itemsList={itemsList} subItemsList={subItemsList} /> </Stack>
</Stack> <Controller
<Stack> name="mission_id"
<NumberField control={control}
{...register("amount")} render={({ field: { onChange, value }, fieldState: { error } }) => {
label={`مقدار (${subItemsList.unit})`} return value ? (
error={!!errors.amount} <Stack spacing={1}>
value={watch("amount")} <Stack direction={"row"} alignItems={"center"} spacing={1} >
type="text" <Chip
size={"small"} label={
unit={subItemsList.unit} value
placeholder={`مقدار را وارد کنید`} ? `کد ماموریت: ${value.id}`
inputProps={{ : "ماموریت انتخاب نشده"
inputMode: "number", }
min: 0, />
pattern: "[0-9]*", <Divider sx={{ flex: 1 }} />
}} <MissionsDialog setMission={m => onChange(m)} mode={"edit"} />
onChange={(event) => { </Stack>
if (!isNaN(event.target.value)) { <FormHelperText error={!!error} >{error ? error.message : null}</FormHelperText>
setValue("amount", event.target.value); </Stack>
} else { ) : (
setValue("amount", watch("amount")); <Stack spacing={1}>
} <MissionsDialog setMission={m => onChange(m)} />
}} <FormHelperText error={!!error} >{error ? error.message : null}</FormHelperText>
helperText={errors.amount ? errors.amount.message : null} </Stack>
variant="outlined" )
fullWidth }}
/> />
</Stack> <Stack >
{!is_gasht && ( <NumberField
<Stack> {...register("amount")}
<Controller label={`مقدار (${subItemsList.unit})`}
control={control} error={!!errors.amount}
render={({ field, fieldState: { error } }) => { value={watch("amount")}
return ( type="text"
<CarCode size={"small"}
carCode={field.value || []} unit={subItemsList.unit}
setCarCode={(value) => field.onChange(value || [])} placeholder={`مقدار را وارد کنید`}
error={error} inputProps={{
multiple={true} inputMode: "number",
/> min: 0,
); pattern: "[0-9]*",
}} }}
name={"cmms_machines"} onChange={(event) => {
/> if (!isNaN(event.target.value)) {
</Stack> setValue("amount", event.target.value);
)} } else {
{!is_gasht && ( setValue("amount", watch("amount"));
<Stack> }
<Controller }}
control={control} helperText={errors.amount ? errors.amount.message : null}
render={({ field, fieldState: { error } }) => { variant="outlined"
return ( fullWidth
<RahdarCode />
rahdarsCode={field.value || []} </Stack >
setRahdarsCode={(value) => field.onChange(value || [])} {!is_gasht ? (
error={error} <Stack>
/> <Grid container spacing={2}>
); <Grid item xs={12} md={6}>
}} <MuiDatePicker
name={"rahdaran_id"} name="activity_date"
/> error={errors.activity_date ? errors.activity_date.message : null}
</Stack> value={watch("activity_date")}
)} placeholder={"تاریخ فعالیت را وارد کنید"}
<Stack> label={"تاریخ فعالیت"}
{subItemsList.needs_image ? ( setFieldValue={setValue}
<ImageUpload setValue={setValue} control={control} errors={errors} getValues={getValues} /> helperText={errors.activity_date ? errors.activity_date.message : null}
) : null} />
</Stack> </Grid>
{!is_gasht ? ( <Grid item xs={12} md={6}>
<Stack> <MuiTimePicker
<Grid container spacing={2}> value={watch("activity_time")}
<Grid item xs={12} md={6}> name="activity_time"
<MuiDatePicker error={errors.activity_time ? errors.activity_time.message : null}
name="activity_date" placeholder={"زمان فعالیت را وارد کنید"}
error={errors.activity_date ? errors.activity_date.message : null} label={"زمان فعالیت"}
value={watch("activity_date")} setFieldValue={setValue}
placeholder={"تاریخ فعالیت را وارد کنید"} helperText={errors.activity_time ? errors.activity_time.message : null}
label={"تاریخ فعالیت"} />
setFieldValue={setValue} </Grid>
helperText={errors.activity_date ? errors.activity_date.message : null} </Grid>
/> </Stack>
</Grid> ) : null}
<Grid item xs={12} md={6}> <Stack>
<MuiTimePicker {subItemsList.needs_image ? (
value={watch("activity_time")} <ImageUpload setValue={setValue} control={control} errors={errors} getValues={getValues} />
name="activity_time" ) : null}
error={errors.activity_time ? errors.activity_time.message : null} </Stack>
placeholder={"زمان فعالیت را وارد کنید"} <Stack>
label={"زمان فعالیت"} {subItemsList?.needs_end_point === 1 ? (
setFieldValue={setValue} <MapInfoTwoMarker setValue={setValue} errors={errors} />
helperText={errors.activity_time ? errors.activity_time.message : null} ) : (
/> <MapInfoOneMarker setValue={setValue} errors={errors} />
</Grid> )}
</Grid> </Stack>
</Stack> </Stack >
) : null} );
<Stack> };
{subItemsList?.needs_end_point === 1 ? ( export default GetItemInfo;
<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 === "" props.dependencyFieldValue.value === ""
? "empty" ? "empty"
: loadingSubItemsList : loadingSubItemsList
? "loading" ? "loading"
: props.filterParameters.value : props.filterParameters.value
} }
columnSelectOption={getColumnSelectOptions} 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"), accessorFn: (row) => moment(row.activity_date_time).locale("fa").format("HH:mm | yyyy/MM/DD"),
header: "تاریخ فعالیت", // Start Date 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 MapInfoOneMarker from "@/core/components/MapInfoOneMarker";
import MapInfoTwoMarker from "@/core/components/MapInfoTwoMarker";
import NumberField from "@/core/components/NumberField";
import StyledForm from "@/core/components/StyledForm"; import StyledForm from "@/core/components/StyledForm";
import React from "react";
import { yupResolver } from "@hookform/resolvers/yup"; 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({ const validationSchema = object({
amount: string().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, "حداقل یک کد راهدار باید وارد شود!"),
before_image: mixed() before_image: mixed()
.nullable() .nullable()
.test("before-image-required", "لطفا عکس قبل از اقدام را بارگذاری کنید!", function (value) { .test("before-image-required", "لطفا عکس قبل از اقدام را بارگذاری کنید!", function (value) {
@@ -124,42 +103,6 @@ const EditFormCreate = ({ defaultData, subItem, onSubmitBase, defaultValues, set
fullWidth fullWidth
/> />
</Stack> </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> <Stack>
{subItem.needs_end_point === 1 ? ( {subItem.needs_end_point === 1 ? (
<MapInfoTwoMarker <MapInfoTwoMarker

View File

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

View File

@@ -127,8 +127,8 @@ const SupervisorList = () => {
props.dependencyFieldValue?.value === "" props.dependencyFieldValue?.value === ""
? "empty" ? "empty"
: loadingEdaratList : loadingEdaratList
? "loading" ? "loading"
: props.filterParameters.value : props.filterParameters.value
} }
columnSelectOption={getColumnSelectOptions} columnSelectOption={getColumnSelectOptions}
/> />
@@ -227,8 +227,8 @@ const SupervisorList = () => {
props.dependencyFieldValue.value === "" props.dependencyFieldValue.value === ""
? "empty" ? "empty"
: loadingSubItemsList : loadingSubItemsList
? "loading" ? "loading"
: props.filterParameters.value : props.filterParameters.value
} }
columnSelectOption={getColumnSelectOptions} 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"), accessorFn: (row) => moment(row.activity_date_time).locale("fa").format("HH:mm | yyyy/MM/DD"),
header: "تاریخ فعالیت", // Start Date header: "تاریخ فعالیت", // Start Date

View File

@@ -1,5 +1,6 @@
import MuiDatePicker from "@/core/components/MuiDatePicker"; import MuiDatePicker from "@/core/components/MuiDatePicker";
import MuiTimePicker from "@/core/components/MuiTimePicker"; import MuiTimePicker from "@/core/components/MuiTimePicker";
import { makeDateTime } from "@/core/utils/makeDateTime";
import { Grid } from "@mui/material"; import { Grid } from "@mui/material";
import { Controller, useWatch } from "react-hook-form"; 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 { Box, Button, Chip, DialogActions, DialogContent, Divider, Stack, Typography } from "@mui/material";
import DriversDialog from "./DriversDialog"; import DriversDialog from "./DriversDialog";
import MachinesDialog from "./MachinesDialog";
import { useState } from "react"; import { useState } from "react";
import MachinesDialog from "./MachinesDialog";
const MachineAndDriver = ({ setTabState, allData, setAllData, handlePrev }) => { const MachineAndDriver = ({ setTabState, allData, setAllData, handlePrev }) => {
const [machine, setMachine] = useState(allData.machine); const [machine, setMachine] = useState(allData.machine);

View File

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