working on supervisor list

This commit is contained in:
2025-01-04 18:33:55 +03:30
parent e127e8758e
commit bc3db055b1
9 changed files with 398 additions and 189 deletions

View File

@@ -1,19 +1,6 @@
"use client";
import {
Box,
Button,
Card,
CardActions,
CardContent,
Chip,
Divider,
IconButton,
InputAdornment,
Slide,
Stack,
Typography
} from "@mui/material";
import {Box, Button, Chip, Divider, IconButton, InputAdornment, Stack} from "@mui/material";
import React, {useEffect, useState} from "react";
import CarCode from "@/core/components/CarCode";
import SearchIcon from '@mui/icons-material/Search';
@@ -24,46 +11,51 @@ import ClearIcon from "@mui/icons-material/Clear";
import moment from "jalali-moment";
import dynamic from "next/dynamic";
import MapLoading from "@/core/components/MapLayer/Loading";
import LocalGasStationIcon from '@mui/icons-material/LocalGasStation';
import DirectionsCarFilledIcon from '@mui/icons-material/DirectionsCarFilled';
import WatchLaterIcon from '@mui/icons-material/WatchLater';
import AddRoadIcon from '@mui/icons-material/AddRoad';
import ShareLocationIcon from '@mui/icons-material/ShareLocation';
import KeyboardDoubleArrowLeftIcon from "@mui/icons-material/KeyboardDoubleArrowLeft";
import KeyboardDoubleArrowRightIcon from "@mui/icons-material/KeyboardDoubleArrowRight";
import {Controller} from "react-hook-form";
import {GET_FMS_DATA} from "@/core/utils/routes";
import useRequest from "@/lib/hooks/useRequest";
import PatrolDetailInfo from "./PatrolDetailInfo";
import PatrolResultCodeErrors from "./PatrolResultCodeErrors";
const MapLayer = dynamic(() => import("@/core/components/MapLayer"), {
loading: () => <MapLoading/>,
ssr: false,
});
const PatrolDetail = ({tabState, setTabState}) => {
const [patrolFounded, setPatrolFounded] = useState(false);
const [carCode, setCarCode] = useState(null);
const [dateFrom, setDateFrom] = useState(null);
const [dateTo, setDateTo] = useState(null);
const PatrolDetail = ({control, watch, setValue, tabState, setTabState}) => {
const requestServer = useRequest({notificationSuccess: true});
const [patrolResultStatus, setPatrolResultStatus] = useState(null)
const [readyToRequest, setReadyToRequest] = useState(false);
const [data, setData] = useState({
machine_code: "12-213-21",
distance: "23",
time: "04:45",
stop: "2",
fuel_amount: "21"
})
const [patrolData, setPatrolData] = useState(null);
const requestPatrolInfo = () => {
setPatrolFounded(true)
setReadyToRequest(false)
const requestPatrolInfo = async () => {
const formData = new FormData();
formData.append("machineCode", watch("road_patrol_machines_id").machine_code);
formData.append("startDT", moment(watch("start_time")).format("YYYY-MM-DDTHH:mm"));
formData.append("endDT", moment(watch("end_time")).format("YYYY-MM-DDTHH:mm"));
await requestServer(GET_FMS_DATA, "post", {
data: formData,
}).then((response) => {
const data = response.data.data;
setPatrolData({
...data,
roadPatrolMachinesId: watch("road_patrol_machines_id"),
start_time: watch("start_time"),
end_time: watch("end_time")
});
setPatrolResultStatus(data.resultCode);
}).catch((error) => {
});
}
useEffect(() => {
if (carCode !== null && dateFrom !== null && dateTo !== null) {
setReadyToRequest(true);
} else {
setReadyToRequest(false);
}
}, [carCode, dateFrom, dateTo]);
const roadPatrolMachinesId = watch("road_patrol_machines_id");
const startTime = watch("start_time");
const endTime = watch("end_time");
const isReady = roadPatrolMachinesId !== null && startTime !== "" && endTime !== "";
setReadyToRequest(isReady);
}, [watch("road_patrol_machines_id"), watch("start_time"), watch("end_time")]);
return (
<Box
@@ -76,23 +68,35 @@ const PatrolDetail = ({tabState, setTabState}) => {
}}
>
<Box sx={{display: "flex", flexDirection: {xs: "column", lg: "row"}, gap: 2}}>
<Box sx={{minWidth: "200px"}}>
<CarCode carCode={carCode} setCarCode={setCarCode}/>
</Box>
<Stack sx={{minWidth: "200px"}}>
<Controller
control={control}
render={({field, fieldState: {error}}) => {
return (
<CarCode
carCode={field.value || []}
setCarCode={(value) => field.onChange(value || [])}
error={error}
/>
);
}}
name={"road_patrol_machines_id"}
/>
</Stack>
<Box sx={{display: "flex", gap: 2}}>
<LocalizationProvider
dateAdapter={AdapterDateFnsJalali}
localeText={faIR.components.MuiLocalizationProvider.defaultProps.localeText}
>
<MobileDateTimePicker value={dateFrom ? new Date(dateFrom) : null}
<MobileDateTimePicker value={watch("start_time") ? new Date(watch("start_time")) : null}
ampm={false}
name="تاریخ و ساعت شروع گشت"
closeOnSelect
maxDateTime={dateTo ? new Date(dateTo) : null}
onChange={(dateFrom) => {
const date = new Date(dateFrom);
maxDateTime={watch("end_time") ? new Date(watch("end_time")) : null}
onChange={(start_time) => {
const date = new Date(start_time);
const formattedDate = moment(date).locale("en").format("YYYY-MM-DD HH:mm");
setDateFrom(formattedDate);
setValue("start_time", formattedDate);
}}
slotProps={{
textField: {
@@ -105,7 +109,7 @@ const PatrolDetail = ({tabState, setTabState}) => {
size="small"
onClick={(event) => {
event.stopPropagation();
setDateFrom(null);
setValue("start_time", "");
}}
sx={{
color: "#bfbfbf",
@@ -123,15 +127,15 @@ const PatrolDetail = ({tabState, setTabState}) => {
},
}} label="تاریخ و ساعت شروع گشت"
/>
<MobileDateTimePicker value={dateTo ? new Date(dateTo) : null}
<MobileDateTimePicker value={watch("end_time") ? new Date(watch("end_time")) : null}
ampm={false}
name="تاریخ و ساعت پایان گشت"
closeOnSelect
minDateTime={dateFrom ? new Date(dateFrom) : null}
onChange={(dateTo) => {
const date = new Date(dateTo);
minDateTime={watch("start_time") ? new Date(watch("start_time")) : null}
onChange={(end_time) => {
const date = new Date(end_time);
const formattedDate = moment(date).locale("en").format("YYYY-MM-DD HH:mm");
setDateTo(formattedDate);
setValue("end_time", formattedDate);
}}
slotProps={{
textField: {
@@ -144,7 +148,7 @@ const PatrolDetail = ({tabState, setTabState}) => {
size="small"
onClick={(event) => {
event.stopPropagation();
setDateTo(null);
setValue("end_time", "");
}}
sx={{
color: "#bfbfbf",
@@ -170,99 +174,9 @@ const PatrolDetail = ({tabState, setTabState}) => {
<Divider sx={{my: 2, width: "100%"}}>
<Chip color="success" label="مشخصات گشت"/>
</Divider>
{patrolFounded ? <Slide in={patrolFounded} sx={{width: "100%"}}>
<Card>
<CardContent
sx={{
display: "flex",
flexDirection: {xs: "column", lg: "row"},
alignItems: "center",
justifyContent: "space-between",
px: 2,
gap: {xs: 2, lg: 0},
py: 2
}}>
<Stack sx={{minWidth: {xs: "100%", lg: "300px"}, gap: 2}}>
<Box sx={{display: "flex", alignItems: "center", justifyContent: "space-between"}}>
<Chip label="کد ماشین" icon={<DirectionsCarFilledIcon/>}/>
<Divider sx={{flex: 1, mx: 2}}/>
<Typography sx={{fontSize: "14px", fontWeight: 500, textDecoration: "underline"}}>
{data.machine_code}
</Typography>
</Box>
<Box sx={{display: "flex", alignItems: "center", justifyContent: "space-between"}}>
<Chip label="بازه زمانی" icon={<WatchLaterIcon/>}/>
<Divider sx={{flex: 1, mx: 2}}/>
<Typography sx={{fontSize: "14px", fontWeight: 500, textDecoration: "underline"}}>
{data.time}
</Typography>
</Box>
<Box sx={{display: "flex", alignItems: "center", justifyContent: "space-between"}}>
<Chip label="مسافت" icon={<AddRoadIcon/>}/>
<Divider sx={{flex: 1, mx: 2}}/>
<Typography sx={{fontSize: "14px", fontWeight: 500, textDecoration: "underline"}}>
{data.distance}
</Typography>
</Box>
<Box sx={{display: "flex", alignItems: "center", justifyContent: "space-between"}}>
<Chip label="توقف در مسیر" icon={<ShareLocationIcon/>}/>
<Divider sx={{flex: 1, mx: 2}}/>
<Typography sx={{fontSize: "14px", fontWeight: 500, textDecoration: "underline"}}>
{data.stop}
</Typography>
</Box>
<Box sx={{display: "flex", alignItems: "center", justifyContent: "space-between"}}>
<Chip label="میزان مصرف سوخت" icon={<LocalGasStationIcon/>}/>
<Divider sx={{flex: 1, mx: 2}}/>
<Typography sx={{fontSize: "14px", fontWeight: 500, textDecoration: "underline"}}>
{data.fuel_amount}
</Typography>
</Box>
</Stack>
<Divider orientation="vertical" flexItem/>
<Stack spacing={1} sx={{height: "300px", width: {xs: "100%", lg: "350px"}}}>
<Box
sx={{
p: 1,
border: "1px dashed",
borderColor: "divider",
borderRadius: 1,
height: "100%",
}}
>
<Box
sx={{
height: "100%",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<MapLayer>
</MapLayer>
</Box>
</Box>
</Stack>
</CardContent>
<CardActions sx={{alignItems: "center", justifyContent: "center"}}>
<Box sx={{display: "flex", gap: 1}}>
<Button variant="outlined" color="error"
startIcon={<KeyboardDoubleArrowRightIcon/>} sx={{mt: 2}}>
بازگشت
</Button>
<Button variant="contained" color="primary" onClick={() => setTabState(tabState + 1)}
endIcon={<KeyboardDoubleArrowLeftIcon/>} sx={{mt: 2}}>
تایید اطلاعات و رفتن به مرحله بعد
</Button>
</Box>
</CardActions>
</Card>
</Slide> :
<Box sx={{my: 5}}>
<Typography variant="h6" sx={{letterSpacing: "2px", color: "#606060"}}>
ابتدا اطلاعات بالا را تکمیل نمایید
</Typography>
</Box>}
{patrolResultStatus === 0 ?
<PatrolDetailInfo patrolData={patrolData} tabState={tabState} setTabState={setTabState}/> :
<PatrolResultCodeErrors ResultCode={patrolResultStatus}/>}
</Box>
);
};

View File

@@ -0,0 +1,147 @@
"use client";
import {Box, Button, Card, CardActions, CardContent, Chip, Divider, Slide, Stack, Typography} from "@mui/material";
import React from "react";
import dynamic from "next/dynamic";
import MapLoading from "@/core/components/MapLayer/Loading";
import LocalGasStationIcon from '@mui/icons-material/LocalGasStation';
import DirectionsCarFilledIcon from '@mui/icons-material/DirectionsCarFilled';
import WatchLaterIcon from '@mui/icons-material/WatchLater';
import QueryBuilderIcon from '@mui/icons-material/QueryBuilder';
import AddRoadIcon from '@mui/icons-material/AddRoad';
import ShareLocationIcon from '@mui/icons-material/ShareLocation';
import KeyboardDoubleArrowLeftIcon from "@mui/icons-material/KeyboardDoubleArrowLeft";
import QrCode2Icon from '@mui/icons-material/QrCode2';
import moment from "jalali-moment";
import PatrolMapFeatures from "./PatrolMapFeatures";
const MapLayer = dynamic(() => import("@/core/components/MapLayer"), {
loading: () => <MapLoading/>,
ssr: false,
});
const PatrolDetailInfo = ({patrolData, tabState, setTabState}) => {
const bound = patrolData.stopPoints.map(point => [point.latitude, point.longitude]);
return (
<Slide in={true} sx={{width: "100%"}}>
<Card>
<CardContent
sx={{
display: "flex",
flexDirection: {xs: "column", lg: "row"},
alignItems: "center",
justifyContent: "space-between",
gap: {xs: 2, lg: 0},
}}>
<Stack sx={{minWidth: {xs: "100%", lg: "300px"}, gap: 2}}>
<Box sx={{display: "flex", alignItems: "center", justifyContent: "space-between"}}>
<Chip size="small" label="مدت زمان روشن بودن خودرو" icon={<DirectionsCarFilledIcon/>}/>
<Divider sx={{flex: 1, mx: 2}}/>
<Typography sx={{fontSize: "13px", fontWeight: 400, textDecoration: "underline"}}>
{Math.floor(patrolData.accOnDuration / 60)} دقیقه
</Typography>
</Box>
<Box sx={{display: "flex", alignItems: "center", justifyContent: "space-between"}}>
<Chip size="small" label="نام خودرو" icon={<DirectionsCarFilledIcon/>}/>
<Divider sx={{flex: 1, mx: 2}}/>
<Typography sx={{fontSize: "13px", fontWeight: 400, textDecoration: "underline"}}>
{patrolData.roadPatrolMachinesId.car_name}
</Typography>
</Box>
<Box sx={{display: "flex", alignItems: "center", justifyContent: "space-between"}}>
<Chip size="small" label="کد خودرو" icon={<QrCode2Icon/>}/>
<Divider sx={{flex: 1, mx: 2}}/>
<Typography sx={{fontSize: "13px", fontWeight: 400, textDecoration: "underline"}}>
{patrolData.roadPatrolMachinesId.machine_code}
</Typography>
</Box>
<Box sx={{display: "flex", alignItems: "center", justifyContent: "space-between"}}>
<Chip size="small" label="پلاک خودرو" icon={<DirectionsCarFilledIcon/>}/>
<Divider sx={{flex: 1, mx: 2}}/>
<Typography sx={{fontSize: "13px", fontWeight: 400, textDecoration: "underline"}}>
{patrolData.roadPatrolMachinesId.plak_number}
</Typography>
</Box>
<Box sx={{display: "flex", alignItems: "center", justifyContent: "space-between"}}>
<Chip size="small" label="زمان شروع گشت" icon={<QueryBuilderIcon/>}/>
<Divider sx={{flex: 1, mx: 2}}/>
<Typography sx={{fontSize: "13px", fontWeight: 400, textDecoration: "underline"}}>
{moment(patrolData.start_time).locale("fa").format("HH:mm | YYYY/MM/DD")}
</Typography>
</Box>
<Box sx={{display: "flex", alignItems: "center", justifyContent: "space-between"}}>
<Chip size="small" label="زمان پایان گشت" icon={<WatchLaterIcon/>}/>
<Divider sx={{flex: 1, mx: 2}}/>
<Typography sx={{fontSize: "13px", fontWeight: 400, textDecoration: "underline"}}>
{moment(patrolData.end_time).locale("fa").format("HH:mm | YYYY/MM/DD")}
</Typography>
</Box>
<Box sx={{display: "flex", alignItems: "center", justifyContent: "space-between"}}>
<Chip size="small" label="مسافت" icon={<AddRoadIcon/>}/>
<Divider sx={{flex: 1, mx: 2}}/>
<Typography sx={{fontSize: "13px", fontWeight: 400, textDecoration: "underline"}}>
{(patrolData.mileage / 1000).toFixed(1)} کیلومتر
</Typography>
</Box>
<Box sx={{display: "flex", alignItems: "center", justifyContent: "space-between"}}>
<Chip size="small" label="میزان مصرف سوخت" icon={<LocalGasStationIcon/>}/>
<Divider sx={{flex: 1, mx: 2}}/>
<Typography sx={{fontSize: "13px", fontWeight: 400, textDecoration: "underline"}}>
{Math.round(patrolData.fuelConsumption * 10) / 10} لیتر
</Typography>
</Box>
<Box sx={{display: "flex", alignItems: "center", justifyContent: "space-between"}}>
<Chip size="small" label="تعداد توقف در مسیر" icon={<ShareLocationIcon/>}/>
<Divider sx={{flex: 1, mx: 2}}/>
<Typography sx={{fontSize: "13px", fontWeight: 400, textDecoration: "underline"}}>
{patrolData.stopPoints.length} مورد
</Typography>
</Box>
</Stack>
<Divider orientation="vertical" flexItem/>
<Stack spacing={1} sx={{height: "300px", width: {xs: "100%", lg: "350px"}}}>
<Box
sx={{
p: 1,
border: "1px dashed",
borderColor: "divider",
borderRadius: 1,
height: "100%",
}}
>
<Box
sx={{
height: "100%",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<MapLayer position={bound}>
{patrolData.stopPoints.map((stopPoint, index) => {
return (
<React.Fragment key={index}>
<PatrolMapFeatures stopPoint={stopPoint}/>
</React.Fragment>
)
})}
</MapLayer>
</Box>
</Box>
</Stack>
</CardContent>
<CardActions sx={{alignItems: "center", justifyContent: "center"}}>
<Box sx={{display: "flex", gap: 1}}>
<Button variant="contained" color="primary" onClick={() => setTabState(tabState + 1)}
endIcon={<KeyboardDoubleArrowLeftIcon/>} sx={{mt: 2}}>
تایید اطلاعات و رفتن به مرحله بعد
</Button>
</Box>
</CardActions>
</Card>
</Slide>
);
};
export default PatrolDetailInfo;

View File

@@ -3,16 +3,19 @@
import {Box, DialogContent, Tab, Tabs, useMediaQuery} from "@mui/material";
import {useTheme} from "@emotion/react";
import React, {useEffect, useState} from "react";
import TapAndPlayIcon from '@mui/icons-material/TapAndPlay';
import TaxiAlertIcon from '@mui/icons-material/TaxiAlert';
import EngineeringIcon from '@mui/icons-material/Engineering';
import HandymanIcon from '@mui/icons-material/Handyman';
import VerifiedIcon from '@mui/icons-material/Verified';
import PatrolTimeLine from "./PatrolTimeLine";
import PhoneValidation from "./PhoneValidation";
import PatrolDetail from "./PatrolDetail";
import SuperVisorsDetail from "./SuperVisorsDetail";
import ActionsDuringPatrol from "./ActionsDurigPatrol";
import {array, object, string} from "yup";
import {useForm} from "react-hook-form";
import {yupResolver} from "@hookform/resolvers/yup";
import StyledForm from "@/core/components/StyledForm";
import useRequest from "@/lib/hooks/useRequest";
function TabPanel(props) {
const {children, value, index} = props;
@@ -24,7 +27,32 @@ function TabPanel(props) {
);
}
const PatrolForms = () => {
const defaultValues = {
road_patrol_rahdaran_id: null,
road_patrol_machines_id: null,
start_time: "",
end_time: "",
stop_points: null,
vehicle_runtime: "",
fuel_consumption: "",
distance: "",
observed_items: null
};
const validationSchema = object({
road_patrol_rahdaran_id: array().required("حداقل یک راهدار باید وارد کنید!"),
road_patrol_machines_id: array().required("وارد کردن کد خودرو الزامیست!").min(1, "وارد کردن کد خودرو الزامیست!"),
start_time: string().required("لطفا زمان شروع گشت را انتخاب کنید!"),
end_time: string().required("لطفا زمان پایان گشت را انتخاب کنید!"),
stop_points: array().required("وجود نقاط توقف اجباری است!").min(1, "حداقل یک نقطه توقف باید وجود داشته باشد!"),
vehicle_runtime: string().required("وجود میزان زمان روشن بودن خودرو الزامیست!"),
fuel_consumption: string().required("وجود مقدار سوخت مصرفی الزامیست!"),
distance: string().required("وارد کردن مقدار الزامیست!"),
observed_items: array().required("وجود نقاط توقف اجباری است!").min(1, "حداقل یک نقطه توقف باید وجود داشته باشد!"),
});
const PatrolForms = ({mutate}) => {
const requestServer = useRequest({notificationSuccess: true});
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down("md"));
const [tabState, setTabState] = useState(0);
@@ -40,9 +68,45 @@ const PatrolForms = () => {
}
}, [tabState]);
const {
control,
watch,
getValues,
register,
handleSubmit,
setValue,
resetField,
formState: {errors, isSubmitting},
} = useForm({
defaultValues,
resolver: yupResolver(validationSchema),
mode: "onBlur"
});
const onSubmit = async (data) => {
console.log("data", data);
const formData = new FormData();
// formData.append("road_patrol_rahdaran_id", myData);
// formData.append("road_patrol_machines_id", myData);
// formData.append("start_time", moment(new Date(myData)).format("YYYY-MM-DD"));
// formData.append("end_time", moment(new Date(myData)).format("YYYY-MM-DD"));
// formData.append("stop_points", myData);
// formData.append("vehicle_runtime", myData);
// formData.append("fuel_consumption", myData);
// formData.append("distance", myData);
// formData.append("observed_items", myData);
// try {
// await requestServer(CREATE_PATROL, "post", {
// data: formData,
// });
// mutate();
// handleClose();
// } catch (error) {
// }
};
return (
<>
<StyledForm onSubmit={handleSubmit(onSubmit)}>
<Tabs
allowScrollButtonsMobile
value={tabState}
@@ -55,27 +119,36 @@ const PatrolForms = () => {
backgroundColor: "#efefef",
}}
>
<Tab disabled={!(activeUpTo >= 0)} icon={<TapAndPlayIcon/>} label="تایید هویت"></Tab>
<Tab disabled={!(activeUpTo >= 1)} icon={<TaxiAlertIcon/>} label="مشخصات گشت"></Tab>
<Tab disabled={!(activeUpTo >= 2)} icon={<EngineeringIcon/>} label="مشخصات راهداران"></Tab>
<Tab disabled={!(activeUpTo >= 3)} icon={<HandymanIcon/>} label="اقدامات حین گشت"></Tab>
<Tab disabled={!(activeUpTo >= 4)} icon={<VerifiedIcon/>} label="تکمیل درخواست"></Tab>
<Tab disabled={!(activeUpTo >= 0)} icon={<TaxiAlertIcon/>} label="مشخصات گشت"></Tab>
<Tab disabled={!(activeUpTo >= 1)} icon={<EngineeringIcon/>} label="مشخصات راهداران"></Tab>
<Tab disabled={!(activeUpTo >= 2)} icon={<HandymanIcon/>} label="اقدامات حین گشت"></Tab>
<Tab disabled={!(activeUpTo >= 3)} icon={<VerifiedIcon/>} label="تکمیل درخواست"></Tab>
</Tabs>
<DialogContent dividers sx={{display: "flex"}}>
<Box sx={{flex: 1}}>
<TabPanel value={tabState} index={0}>
<PhoneValidation tabState={tabState} setTabState={setTabState}/>
<PatrolDetail
control={control}
setValue={setValue}
watch={watch}
errors={errors}
tabState={tabState}
setTabState={setTabState}
/>
</TabPanel>
<TabPanel value={tabState} index={1}>
<PatrolDetail tabState={tabState} setTabState={setTabState}/>
<SuperVisorsDetail
control={control}
setValue={setValue}
watch={watch}
errors={errors}
tabState={tabState}
setTabState={setTabState}/>
</TabPanel>
<TabPanel value={tabState} index={2}>
<SuperVisorsDetail tabState={tabState} setTabState={setTabState}/>
</TabPanel>
<TabPanel value={tabState} index={3}>
<ActionsDuringPatrol tabState={tabState} setTabState={setTabState}/>
</TabPanel>
<TabPanel value={tabState} index={4}>
<TabPanel value={tabState} index={3}>
<>taiidie</>
</TabPanel>
</Box>
@@ -85,7 +158,7 @@ const PatrolForms = () => {
</Box>
)}
</DialogContent>
</>
</StyledForm>
);
};
export default PatrolForms;

View File

@@ -0,0 +1,38 @@
"use client";
import {Typography} from "@mui/material";
import React, {useRef} from "react";
import {Marker, Popup} from "react-leaflet";
import AzmayeshIcon from "@/assets/images/examine_marker.png";
const PatrolMapFeatures = ({stopPoint}) => {
const position = [stopPoint.latitude, stopPoint.longitude];
const mapPatrolMarker = useRef();
const createCustomIcon = (size, iconUrl) => {
return L.icon({
iconUrl: iconUrl,
iconSize: size,
iconAnchor: [size[0] / 2, size[1]],
popupAnchor: [0, -size[1]],
});
};
return (
<Marker ref={mapPatrolMarker}
icon={L.icon({
iconUrl: AzmayeshIcon.src,
iconSize: [35, 35],
iconAnchor: [35 / 2, 35],
popupAnchor: [0, -35],
})}
position={position}
>
<Popup>
<Typography variant="button">مدت زمان
توقف: {stopPoint.duration} ثانیه</Typography>
</Popup>
</Marker>
);
};
export default PatrolMapFeatures;

View File

@@ -0,0 +1,25 @@
"use client";
import {Box, Typography} from "@mui/material";
import React from "react";
const PatrolResultCodeErrors = ({ResultCode}) => {
const errorMessages = {
[-1]: "نام کاربری یا کلمه عبور صحیح نمیباشد",
[-2]: "ردیاب به خودرو انتخابی متصل نیست",
[-3]: "کاربر دسترسی لازم به اطلاعات خودرو انتخابی را ندارد",
[-4]: "خطای درخواست مکرر",
};
const message = errorMessages[ResultCode] || "ابتدا اطلاعات بالا را تکمیل نمایید";
return (
<Box sx={{my: 5}}>
<Typography variant="h6" sx={{letterSpacing: "2px", color: ResultCode ? "error.main" : "#606060"}}>
{message}
</Typography>
</Box>
);
};
export default PatrolResultCodeErrors;

View File

@@ -1,22 +1,22 @@
"use client";
import {Box, Button, Chip, Divider, Grid, Typography} from "@mui/material";
import {Box, Button, Chip, Divider, Grid, Stack, Typography} from "@mui/material";
import SaveAltIcon from '@mui/icons-material/SaveAlt';
import React, {useEffect, useState} from "react";
import RahdarCode from "@/core/components/RahdarCode";
import SuperVisorInfo from "@/components/dashboard/roadPatrols/operator/Forms/CreatePatrol/SuperVisorInfo";
import KeyboardDoubleArrowRightIcon from "@mui/icons-material/KeyboardDoubleArrowRight";
import KeyboardDoubleArrowLeftIcon from "@mui/icons-material/KeyboardDoubleArrowLeft";
import {Controller} from "react-hook-form";
const SuperVisorsDetail = ({tabState, setTabState}) => {
const SuperVisorsDetail = ({control, watch, setValue, tabState, setTabState}) => {
const [SuperVisorList, setSuperVisorList] = useState([]);
const [rahdarsCode, setRahdarsCode] = useState(null);
const [readyToRequest, setReadyToRequest] = useState(false);
const requestPatrolInfo = () => {
setSuperVisorList((prev) => [...prev, rahdarsCode]);
setSuperVisorList((prev) => [...prev, watch("road_patrol_rahdaran_id")]);
setReadyToRequest(false);
setRahdarsCode(null);
setValue("road_patrol_rahdaran_id", null);
}
const deleteSuperVisor = (id) => {
@@ -24,8 +24,8 @@ const SuperVisorsDetail = ({tabState, setTabState}) => {
};
useEffect(() => {
setReadyToRequest(rahdarsCode != null);
}, [rahdarsCode]);
setReadyToRequest(watch("road_patrol_rahdaran_id") != null);
}, [watch("road_patrol_rahdaran_id")]);
return (
<Box
@@ -40,7 +40,22 @@ const SuperVisorsDetail = ({tabState, setTabState}) => {
<Grid container sx={{display: "flex", alignItems: "center", justifyContent: "center"}}>
<Grid item xs={6}
sx={{display: "flex", alignItems: "center", flexDirection: {xs: "column", lg: "row"}, gap: 2}}>
<RahdarCode rahdarsCode={rahdarsCode} setRahdarsCode={setRahdarsCode} multiple={false}/>
<Stack sx={{minWidth: "250px"}}>
<Controller
control={control}
render={({field, fieldState: {error}}) => {
return (
<RahdarCode
rahdarsCode={field.value || []}
setRahdarsCode={(value) => field.onChange(value || [])}
error={error}
multiple={false}
/>
);
}}
name={"road_patrol_rahdaran_id"}
/>
</Stack>
<Button variant="contained" onClick={requestPatrolInfo}
color="success"
sx={{textWrap: "nowrap", px: 3}}

View File

@@ -1,15 +1,14 @@
"use client";
import {Dialog} from "@mui/material";
import PatrolForms from "@/components/dashboard/roadPatrols/operator/Forms/CreatePatrol/PatrolForms";
import PatrolForms from "./PatrolForms";
const CreatePatrol = ({open, setOpen, mutate, rowId}) => {
const CreatePatrol = ({open, setOpen, mutate}) => {
return (
<Dialog open={open} fullWidth maxWidth="lg">
<PatrolForms
setOpen={setOpen}
mutate={mutate}
rowId={rowId}
/>
</Dialog>
);

View File

@@ -1,10 +1,10 @@
import { Autocomplete, CircularProgress, TextField } from "@mui/material";
import { useEffect, useState } from "react";
import {Autocomplete, CircularProgress, TextField} from "@mui/material";
import {useEffect, useState} from "react";
import useRequest from "@/lib/hooks/useRequest";
import { debounce } from "@mui/material/utils";
import { GET_CAR_LIST_SEARCH } from "@/core/utils/routes";
import {debounce} from "@mui/material/utils";
import {GET_CAR_LIST_SEARCH} from "@/core/utils/routes";
const CarCode = ({ carCode, setCarCode, inputValueDefault = "", error, multiple = false }) => {
const CarCode = ({carCode, setCarCode, inputValueDefault = "", error, multiple = false}) => {
const [inputValue, setInputValue] = useState(inputValueDefault);
const [options, setOptions] = useState([]);
const [loading, setLoading] = useState(false);
@@ -18,11 +18,10 @@ const CarCode = ({ carCode, setCarCode, inputValueDefault = "", error, multiple
}
setLoading(true);
requestServer(`${GET_CAR_LIST_SEARCH}?machine_code=${query}`, "get", {
requestOptions: { signal: controller.signal },
requestOptions: {signal: controller.signal},
})
.then((response) => {
const combinedArray = [...carCode, ...response.data.data];
const uniqueArray = Array.from(new Map(combinedArray.map((item) => [item.id, item])).values());
setOptions(uniqueArray || []);
})
@@ -56,7 +55,7 @@ const CarCode = ({ carCode, setCarCode, inputValueDefault = "", error, multiple
options={options}
getOptionLabel={(option) => {
if (typeof option === "string") return option;
const { machine_code, car_name, plak_number } = option;
const {machine_code, car_name, plak_number} = option;
let label = `${machine_code || ""}`;
if (car_name) {
label += ` | ${car_name}`;
@@ -86,7 +85,7 @@ const CarCode = ({ carCode, setCarCode, inputValueDefault = "", error, multiple
...params.InputProps,
endAdornment: (
<>
{loading ? <CircularProgress size="25px" color="inherit" /> : null}
{loading ? <CircularProgress size="25px" color="inherit"/> : null}
{params.InputProps.endAdornment}
</>
),

View File

@@ -34,9 +34,8 @@ export const EXPORT_ROAD_PATROL_OPERATOR_LIST = "https://rms.witel.ir/v2/road_pa
export const GET_ROAD_PATROL_SUPERVISOR_LIST = api + "/api/v3/road_patrols/supervisor_index";
export const EXPORT_ROAD_PATROL_SUPERVISOR_LIST = "https://rms.witel.ir/v2/road_patrols/supervisor/cartable/report";
export const DELETE_ROAD_PATROL_SUPERVISOR = api + "/api/v3/road_patrols/delete";
export const EXPORT_ROAD_PATROL_SUPERVISOR_LIST = "https://rms.rmto.ir/v2/road_patrols/supervisor/cartable/report";
export const GET_OTP_TOKEN = "fake/api";
export const VERIFY_OTP = "fake/api";
export const CREATE_PATROL = api + "/api/v3/road_patrols/store";
export const GET_FMS_DATA = api + "/api/v3/fms_vehicle/get_activity";
// road items
export const GET_ROAD_ITEMS_SUPERVISOR_LIST = api + "/api/v3/road_items/supervisor_index";