7 Commits

Author SHA1 Message Date
0435654762 Merge pull request 'feature/moddle_point' (#12) from feature/moddle_point into develop
Reviewed-on: #12
2026-06-22 11:48:26 +00:00
f94374958d build and format 2026-06-22 15:15:04 +03:30
a26f07d2ad 2 middle point 2026-06-22 15:14:02 +03:30
d1b74585d7 build & format 2026-06-22 15:04:47 +03:30
6115e0ded2 refactored violations, add controller and edit
replaced text explanation with select fields
2026-06-22 14:56:02 +03:30
40f80fac3a refactored explanation field on create flow
road missions operator cartable
2026-06-22 12:03:39 +03:30
188c7c45af base select options 2026-06-21 15:03:20 +03:30
18 changed files with 282 additions and 69 deletions

View File

@@ -11,7 +11,7 @@ import { useEffect, useRef, useState } from "react";
import DataBox from "./DataBox"; import DataBox from "./DataBox";
import AlarmText from "./AlarmText"; import AlarmText from "./AlarmText";
const MAX_WAYPOINTS = 1; const MAX_WAYPOINTS = 2;
const Routing = ({ setArea, setLocations, locations, area }) => { const Routing = ({ setArea, setLocations, locations, area }) => {
const mapPrevSourceMarker = useRef(); const mapPrevSourceMarker = useRef();

View File

@@ -0,0 +1,34 @@
import useRoadItemGetItems from "@/lib/hooks/useRoadItemGetItems";
import { Controller } from "react-hook-form";
import SelectBox from "@/core/components/SelectBox";
const ItemSelectField = ({ control, setValue }) => {
const { itemsList, loadingItemsList, errorItemsList } = useRoadItemGetItems();
function getItemName(val) {
return itemsList.find((item) => item.id === val)?.name;
}
return (
<Controller
control={control}
name={"item_id"}
render={({ field, fieldState: { error } }) => (
<SelectBox
value={field.value}
label="موضوع"
selectors={itemsList}
isLoading={loadingItemsList}
schema={{ name: "name", value: "id" }}
error={errorItemsList}
helperText={error?.message}
onChange={(value) => {
field.onChange(value);
setValue("explanation", getItemName(value));
setValue("sub_item_id", "");
}}
/>
)}
/>
);
};
export default ItemSelectField;

View File

@@ -0,0 +1,37 @@
import useRoadItemGetSubItems from "@/lib/hooks/useRoadItemGetISubtems";
import { Controller } from "react-hook-form";
import SelectBox from "@/core/components/SelectBox";
const SubItemSelectField = ({ control, watch, setValue, getValues }) => {
const itemId = watch("item_id");
const { subItemsList, loadingSubItemsList, errorSubItemsList } = useRoadItemGetSubItems(itemId);
function createExplanation(val) {
const currentExplanation = getValues("explanation");
const selectedItem = subItemsList.find((item) => item.id === val)?.name;
return `${currentExplanation}-${selectedItem}`;
}
return (
<Controller
control={control}
name={"sub_item_id"}
render={({ field, fieldState: { error } }) => (
<SelectBox
value={field.value}
label="اقدام انجام شده"
selectors={subItemsList}
isLoading={loadingSubItemsList}
schema={{ name: "name", value: "id" }}
error={errorSubItemsList}
helperText={error?.message}
onChange={(val) => {
field.onChange(val);
setValue("explanation", createExplanation(val));
}}
/>
)}
/>
);
};
export default SubItemSelectField;

View File

@@ -9,12 +9,15 @@ import { ExitToApp } from "@mui/icons-material";
import { Box, Button, DialogActions, DialogContent, Grid, Stack } from "@mui/material"; import { Box, Button, DialogActions, DialogContent, Grid, Stack } from "@mui/material";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import { array, object, string } from "yup"; import { array, object, string } from "yup";
import ItemSelectField from "./ItemSelectField";
import SubItemSelectField from "./SubItemSelectField";
const validationSchema = object({ const validationSchema = object({
explanation: string().required("موضوع را مشخص کنید!"),
end_point: string().required("مقصد را مشخص کنید!"), end_point: string().required("مقصد را مشخص کنید!"),
region: string().required("محور ماموریت را مشخص کنید!"), region: string().required("محور ماموریت را مشخص کنید!"),
category_id: string().required("نوع ماموریت را مشخص کنید!"), category_id: string().required("نوع ماموریت را مشخص کنید!"),
item_id: string().required("موضوع را مشخص کنید!"),
sub_item_id: string().required("اقدام انجام شده را مشخص کنید!"),
requested_machines: array().min(1, "نوع خودرو را مشخص کنید!").required("نوع خودرو را مشخص کنید!"), requested_machines: array().min(1, "نوع خودرو را مشخص کنید!").required("نوع خودرو را مشخص کنید!"),
road_observed_id: string().when("category_id", { road_observed_id: string().when("category_id", {
is: "3", is: "3",
@@ -25,6 +28,8 @@ const validationSchema = object({
const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => { const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => {
const defaultValues = { const defaultValues = {
item_id: allData.item_id,
sub_item_id: allData.sub_item_id,
explanation: allData.explanation, explanation: allData.explanation,
end_point: allData.end_point, end_point: allData.end_point,
region: allData.region, region: allData.region,
@@ -33,7 +38,7 @@ const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => {
road_observed_id: allData.road_observed_id, road_observed_id: allData.road_observed_id,
}; };
const { control, handleSubmit } = useForm({ const { control, handleSubmit, watch, setValue, getValues } = useForm({
defaultValues, defaultValues,
resolver: yupResolver(validationSchema), resolver: yupResolver(validationSchema),
mode: "all", mode: "all",
@@ -51,24 +56,14 @@ const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => {
<Stack> <Stack>
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12} sm={6}> <Grid item xs={12} sm={6}>
<Controller <ItemSelectField control={control} watch={watch} setValue={setValue} />
</Grid>
<Grid item xs={12} sm={6}>
<SubItemSelectField
control={control} control={control}
name={"explanation"} watch={watch}
render={({ field, fieldState: { error } }) => ( setValue={setValue}
<PersianTextField getValues={getValues}
value={field.value}
variant="outlined"
name="explanation"
onChange={field.onChange}
label="موضوع"
placeholder={"موضوع را وارد کنید"}
fullWidth
size="small"
error={error}
helperText={error?.message}
InputLabelProps={{ shrink: true }}
/>
)}
/> />
</Grid> </Grid>
<Grid item xs={12} sm={6}> <Grid item xs={12} sm={6}>

View File

@@ -44,6 +44,8 @@ const Create = ({ mutate }) => {
start_date: result.start_date, start_date: result.start_date,
end_date: result.end_date, end_date: result.end_date,
}), }),
item_id: result.item_id,
sub_item_id: result.sub_item_id,
}, },
hasSidebarUpdate: true, hasSidebarUpdate: true,
}) })
@@ -93,6 +95,8 @@ const Create = ({ mutate }) => {
defaultValues={{ defaultValues={{
explanation: "", explanation: "",
category_id: "", category_id: "",
item_id: null,
sub_item_id: null,
road_observed_id: "", road_observed_id: "",
rahdaran: [], rahdaran: [],
requested_machines: [], requested_machines: [],

View File

@@ -11,7 +11,7 @@ import { useEffect, useRef, useState } from "react";
import DataBox from "./DataBox"; import DataBox from "./DataBox";
import AlarmText from "./AlarmText"; import AlarmText from "./AlarmText";
const MAX_WAYPOINTS = 1; const MAX_WAYPOINTS = 2;
const Routing = ({ setArea, setLocations, locations, area }) => { const Routing = ({ setArea, setLocations, locations, area }) => {
const mapPrevSourceMarker = useRef(); const mapPrevSourceMarker = useRef();

View File

@@ -0,0 +1,34 @@
import useRoadItemGetItems from "@/lib/hooks/useRoadItemGetItems";
import { Controller } from "react-hook-form";
import SelectBox from "@/core/components/SelectBox";
const ItemSelectField = ({ control, setValue }) => {
const { itemsList, loadingItemsList, errorItemsList } = useRoadItemGetItems();
function getItemName(val) {
return itemsList.find((item) => item.id === val)?.name;
}
return (
<Controller
control={control}
name={"item_id"}
render={({ field, fieldState: { error } }) => (
<SelectBox
value={field.value}
label="موضوع"
selectors={itemsList}
isLoading={loadingItemsList}
schema={{ name: "name", value: "id" }}
error={errorItemsList}
helperText={error?.message}
onChange={(value) => {
field.onChange(value);
setValue("explanation", getItemName(value));
setValue("sub_item_id", "");
}}
/>
)}
/>
);
};
export default ItemSelectField;

View File

@@ -0,0 +1,37 @@
import useRoadItemGetSubItems from "@/lib/hooks/useRoadItemGetISubtems";
import { Controller } from "react-hook-form";
import SelectBox from "@/core/components/SelectBox";
const SubItemSelectField = ({ control, watch, setValue, getValues }) => {
const itemId = watch("item_id");
const { subItemsList, loadingSubItemsList, errorSubItemsList } = useRoadItemGetSubItems(itemId);
function createExplanation(val) {
const currentExplanation = getValues("explanation");
const selectedItem = subItemsList.find((item) => item.id === val)?.name;
return `${currentExplanation}-${selectedItem}`;
}
return (
<Controller
control={control}
name={"sub_item_id"}
render={({ field, fieldState: { error } }) => (
<SelectBox
value={field.value}
label="اقدام انجام شده"
selectors={subItemsList}
isLoading={loadingSubItemsList}
schema={{ name: "name", value: "id" }}
error={errorSubItemsList}
helperText={error?.message}
onChange={(val) => {
field.onChange(val);
setValue("explanation", createExplanation(val));
}}
/>
)}
/>
);
};
export default SubItemSelectField;

View File

@@ -8,10 +8,12 @@ import { ExitToApp } from "@mui/icons-material";
import { Box, Button, DialogActions, DialogContent, Grid, Stack } from "@mui/material"; import { Box, Button, DialogActions, DialogContent, Grid, Stack } from "@mui/material";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import { object, string } from "yup"; import { object, string } from "yup";
import FastReactCode from "./FastReactCode"; import ItemSelectField from "./ItemSelectField";
import SubItemSelectField from "./SubItemSelectField";
const validationSchema = object({ const validationSchema = object({
explanation: string().required("موضوع را مشخص کنید!"), item_id: string().required("موضوع را مشخص کنید!"),
sub_item_id: string().required("اقدام انجام شده را مشخص کنید!"),
end_point: string().required("مقصد را مشخص کنید!"), end_point: string().required("مقصد را مشخص کنید!"),
region: string().required("محور ماموریت را مشخص کنید!"), region: string().required("محور ماموریت را مشخص کنید!"),
category_id: string().required("نوع ماموریت را مشخص کنید!"), category_id: string().required("نوع ماموریت را مشخص کنید!"),
@@ -24,6 +26,8 @@ const validationSchema = object({
const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => { const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => {
const defaultValues = { const defaultValues = {
item_id: allData.item_id,
sub_item_id: allData.sub_item_id,
explanation: allData.explanation, explanation: allData.explanation,
end_point: allData.end_point, end_point: allData.end_point,
region: allData.region, region: allData.region,
@@ -31,7 +35,7 @@ const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => {
road_observed_id: allData.road_observed_id, road_observed_id: allData.road_observed_id,
}; };
const { control, handleSubmit } = useForm({ const { control, handleSubmit, watch, setValue, getValues } = useForm({
defaultValues, defaultValues,
resolver: yupResolver(validationSchema), resolver: yupResolver(validationSchema),
mode: "all", mode: "all",
@@ -49,24 +53,14 @@ const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => {
<Stack> <Stack>
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12} sm={6}> <Grid item xs={12} sm={6}>
<Controller <ItemSelectField control={control} watch={watch} setValue={setValue} />
</Grid>
<Grid item xs={12} sm={6}>
<SubItemSelectField
control={control} control={control}
name={"explanation"} watch={watch}
render={({ field, fieldState: { error } }) => ( setValue={setValue}
<PersianTextField getValues={getValues}
value={field.value}
variant="outlined"
name="explanation"
onChange={field.onChange}
label="موضوع"
placeholder={"موضوع را وارد کنید"}
fullWidth
size="small"
error={error}
helperText={error?.message}
InputLabelProps={{ shrink: true }}
/>
)}
/> />
</Grid> </Grid>
<Grid item xs={12} sm={6}> <Grid item xs={12} sm={6}>

View File

@@ -1,12 +1,11 @@
import { AccessTime, Engineering, InsertDriveFile, Person, Verified, Map } from "@mui/icons-material"; import { Engineering, InsertDriveFile, Map, Person, Verified } from "@mui/icons-material";
import { Box, Tab, Tabs } from "@mui/material"; import { Box, Tab, Tabs } from "@mui/material";
import { useReducer, useState } from "react"; import { useReducer, useState } from "react";
import GetDateTime from "./GetDateTime"; import Area from "./Area";
import GetItemInfo from "./GetItemInfo"; import GetItemInfo from "./GetItemInfo";
import MachineAndDriver from "./MachineAndDriver"; import MachineAndDriver from "./MachineAndDriver";
import Rahdaran from "./Rahdaran"; import Rahdaran from "./Rahdaran";
import Verify from "./Verify"; import Verify from "./Verify";
import Area from "./Area";
function TabPanel(props) { function TabPanel(props) {
const { children, value, index } = props; const { children, value, index } = props;

View File

@@ -26,6 +26,8 @@ const MissionCorrection = ({ row, mutate, baseMutate }) => {
end_point: result.end_point, end_point: result.end_point,
driver: result.driver.id, driver: result.driver.id,
encoded_route: result.area, encoded_route: result.area,
item_id: result.item_id,
sub_item_id: result.sub_item_id,
}, },
hasSidebarUpdate: true, hasSidebarUpdate: true,
}) })

View File

@@ -11,7 +11,7 @@ import { useEffect, useRef, useState } from "react";
import DataBox from "./DataBox"; import DataBox from "./DataBox";
import AlarmText from "./AlarmText"; import AlarmText from "./AlarmText";
const MAX_WAYPOINTS = 1; const MAX_WAYPOINTS = 2;
const Routing = ({ setArea, setLocations, locations, area }) => { const Routing = ({ setArea, setLocations, locations, area }) => {
const mapPrevSourceMarker = useRef(); const mapPrevSourceMarker = useRef();

View File

@@ -0,0 +1,34 @@
import useRoadItemGetItems from "@/lib/hooks/useRoadItemGetItems";
import { Controller } from "react-hook-form";
import SelectBox from "@/core/components/SelectBox";
const ItemSelectField = ({ control, setValue }) => {
const { itemsList, loadingItemsList, errorItemsList } = useRoadItemGetItems();
function getItemName(val) {
return itemsList.find((item) => item.id === val)?.name;
}
return (
<Controller
control={control}
name={"item_id"}
render={({ field, fieldState: { error } }) => (
<SelectBox
value={field.value}
label="موضوع"
selectors={itemsList}
isLoading={loadingItemsList}
schema={{ name: "name", value: "id" }}
error={errorItemsList}
helperText={error?.message}
onChange={(value) => {
field.onChange(value);
setValue("explanation", getItemName(value));
setValue("sub_item_id", "");
}}
/>
)}
/>
);
};
export default ItemSelectField;

View File

@@ -0,0 +1,37 @@
import useRoadItemGetSubItems from "@/lib/hooks/useRoadItemGetISubtems";
import { Controller } from "react-hook-form";
import SelectBox from "@/core/components/SelectBox";
const SubItemSelectField = ({ control, watch, setValue, getValues }) => {
const itemId = watch("item_id");
const { subItemsList, loadingSubItemsList, errorSubItemsList } = useRoadItemGetSubItems(itemId);
function createExplanation(val) {
const currentExplanation = getValues("explanation");
const selectedItem = subItemsList.find((item) => item.id === val)?.name;
return `${currentExplanation}-${selectedItem}`;
}
return (
<Controller
control={control}
name={"sub_item_id"}
render={({ field, fieldState: { error } }) => (
<SelectBox
value={field.value}
label="اقدام انجام شده"
selectors={subItemsList}
isLoading={loadingSubItemsList}
schema={{ name: "name", value: "id" }}
error={errorSubItemsList}
helperText={error?.message}
onChange={(val) => {
field.onChange(val);
setValue("explanation", createExplanation(val));
}}
/>
)}
/>
);
};
export default SubItemSelectField;

View File

@@ -1,3 +1,4 @@
import LtrTextField from "@/core/components/LtrTextField";
import PersianTextField from "@/core/components/PersianTextField"; import PersianTextField from "@/core/components/PersianTextField";
import SelectBox from "@/core/components/SelectBox"; import SelectBox from "@/core/components/SelectBox";
import StyledForm from "@/core/components/StyledForm"; import StyledForm from "@/core/components/StyledForm";
@@ -8,7 +9,8 @@ import { ExitToApp } from "@mui/icons-material";
import { Box, Button, DialogActions, DialogContent, Grid, Stack } from "@mui/material"; import { Box, Button, DialogActions, DialogContent, Grid, Stack } from "@mui/material";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import { object, string } from "yup"; import { object, string } from "yup";
import LtrTextField from "@/core/components/LtrTextField"; import ItemSelectField from "./ItemSelectField";
import SubItemSelectField from "./SubItemSelectField";
const validationSchema = object({ const validationSchema = object({
explanation: string().required("موضوع را مشخص کنید!"), explanation: string().required("موضوع را مشخص کنید!"),
@@ -24,6 +26,8 @@ const validationSchema = object({
const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => { const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => {
const defaultValues = { const defaultValues = {
item_id: allData.item_id,
sub_item_id: allData.sub_item_id,
explanation: allData.explanation, explanation: allData.explanation,
end_point: allData.end_point, end_point: allData.end_point,
region: allData.region, region: allData.region,
@@ -31,7 +35,7 @@ const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => {
road_observed_id: allData.road_observed_id, road_observed_id: allData.road_observed_id,
}; };
const { control, handleSubmit } = useForm({ const { control, handleSubmit, watch, setValue, getValues } = useForm({
defaultValues, defaultValues,
resolver: yupResolver(validationSchema), resolver: yupResolver(validationSchema),
mode: "all", mode: "all",
@@ -49,24 +53,14 @@ const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => {
<Stack> <Stack>
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12} sm={6}> <Grid item xs={12} sm={6}>
<Controller <ItemSelectField control={control} watch={watch} setValue={setValue} />
</Grid>
<Grid item xs={12} sm={6}>
<SubItemSelectField
control={control} control={control}
name={"explanation"} watch={watch}
render={({ field, fieldState: { error } }) => ( setValue={setValue}
<PersianTextField getValues={getValues}
value={field.value}
variant="outlined"
name="explanation"
onChange={field.onChange}
label="موضوع"
placeholder={"موضوع را وارد کنید"}
fullWidth
size="small"
error={error}
helperText={error?.message}
InputLabelProps={{ shrink: true }}
/>
)}
/> />
</Grid> </Grid>
<Grid item xs={12} sm={6}> <Grid item xs={12} sm={6}>
@@ -126,7 +120,7 @@ const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => {
}} }}
/> />
</Grid> </Grid>
<Grid item xs={12} sm={12}> <Grid item xs={6} sm={6}>
<Stack> <Stack>
<Controller <Controller
control={control} control={control}

View File

@@ -93,10 +93,12 @@ const Verify = ({ allData, handlePrev, submitForm, submitting }) => {
<Stack direction={"row"} alignItems={"center"} spacing={1}> <Stack direction={"row"} alignItems={"center"} spacing={1}>
<Typography variant="body2">خودرو</Typography> <Typography variant="body2">خودرو</Typography>
<Divider sx={{ flex: 1 }} /> <Divider sx={{ flex: 1 }} />
<Chip {allData.machine && (
size="small" <Chip
label={`${allData.machine.machine_code} | ${allData.machine.car_name}`} size="small"
/> label={`${allData.machine.machine_code} | ${allData.machine.car_name}`}
/>
)}
</Stack> </Stack>
{/* <Stack direction={"row"} alignItems={"center"} spacing={1}> {/* <Stack direction={"row"} alignItems={"center"} spacing={1}>
<Typography variant="body2">راننده</Typography> <Typography variant="body2">راننده</Typography>

View File

@@ -9,6 +9,8 @@ const DialogAdd = ({ mutate, setOpen, oldBound, rahdaran, machine, row }) => {
const requestServer = useRequest({ notificationSuccess: true }); const requestServer = useRequest({ notificationSuccess: true });
const submitForm = async (result) => { const submitForm = async (result) => {
console.log("result: ", result);
setSubmitting(true); setSubmitting(true);
await requestServer(`${REQUEST_MISSION_CONTINUE_MISSION}/${row.original.id}`, "post", { await requestServer(`${REQUEST_MISSION_CONTINUE_MISSION}/${row.original.id}`, "post", {
data: { data: {
@@ -29,6 +31,8 @@ const DialogAdd = ({ mutate, setOpen, oldBound, rahdaran, machine, row }) => {
end_point: result.end_point, end_point: result.end_point,
category_id: result.category_id, category_id: result.category_id,
explanation: result.explanation, explanation: result.explanation,
item_id: result.item_id,
sub_item_id: result.sub_item_id,
...(result.category_id == 3 ...(result.category_id == 3
? { ? {
road_observed_id: result.road_observed_id, road_observed_id: result.road_observed_id,
@@ -51,6 +55,8 @@ const DialogAdd = ({ mutate, setOpen, oldBound, rahdaran, machine, row }) => {
<CreateForm <CreateForm
defaultValues={{ defaultValues={{
explanation: "", explanation: "",
item_id: "",
sub_item_id: "",
category_id: "", category_id: "",
rahdaran: rahdaran.filter((r) => !r.is_driver), rahdaran: rahdaran.filter((r) => !r.is_driver),
bound_type: "polyline", bound_type: "polyline",

View File

@@ -51,6 +51,8 @@ const EditController = ({ row, mutate, openEditDialog, setOpenEditDialog }) => {
await requestServer(`${UPDATE_REQUEST_MISSION}/${row.original.id}`, "post", { await requestServer(`${UPDATE_REQUEST_MISSION}/${row.original.id}`, "post", {
data: { data: {
explanation: result.explanation, explanation: result.explanation,
item_id: result.item_id,
sub_item_id: result.sub_item_id,
category_id: result.category_id, category_id: result.category_id,
...(result.category_id == 3 ...(result.category_id == 3
@@ -101,6 +103,8 @@ const EditController = ({ row, mutate, openEditDialog, setOpenEditDialog }) => {
<CreateForm <CreateForm
defaultValues={{ defaultValues={{
explanation: row.original.explanation, explanation: row.original.explanation,
item_id: row.original.item_id,
sub_item_id: row.original.sub_item_id,
category_id: row.original.category_id, category_id: row.original.category_id,
road_observed_id: row.original.category_id == 3 ? (row.original.road_observed?.[0]?.id ?? "") : "", road_observed_id: row.original.category_id == 3 ? (row.original.road_observed?.[0]?.id ?? "") : "",