Feature/amiriis missions
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
import MapLayer from "@/core/components/MapLayer";
|
||||
import { Close, RemoveRedEye } from "@mui/icons-material";
|
||||
import { Box, Dialog, DialogContent, DialogTitle, IconButton, Tooltip, Typography } from "@mui/material";
|
||||
import { useMemo, useState } from "react";
|
||||
import ShowBound from "../showBound";
|
||||
import L from "leaflet";
|
||||
|
||||
const ShowArea = ({ area }) => {
|
||||
const bound = useMemo(() => L.polygon([...area]), [area]);
|
||||
const [openAreaDialog, setOpenAreaDialog] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip title="محدوده">
|
||||
<IconButton color="primary" onClick={() => setOpenAreaDialog(true)}>
|
||||
<RemoveRedEye />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Dialog
|
||||
open={openAreaDialog}
|
||||
onClose={() => setOpenAreaDialog(false)}
|
||||
PaperProps={{
|
||||
sx: {
|
||||
transition: "all .3s",
|
||||
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
|
||||
borderRadius: 2,
|
||||
padding: 1,
|
||||
},
|
||||
}}
|
||||
maxWidth="sm"
|
||||
fullWidth
|
||||
dir="rtl"
|
||||
>
|
||||
<DialogTitle sx={{ display: "flex", justifyContent: "space-between", padding: "16px 24px" }}>
|
||||
<Typography variant="body1" sx={{ fontWeight: "bold", fontSize: "large" }}>
|
||||
محدوده
|
||||
</Typography>
|
||||
<IconButton onClick={() => setOpenAreaDialog(false)} size="small">
|
||||
<Close />
|
||||
</IconButton>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<Box sx={{ flex: 1 }}>
|
||||
<Box sx={{ width: "100%", height: "400px" }}>
|
||||
<MapLayer style={{ borderRadius: "4px" }}>
|
||||
<ShowBound bound={bound} />
|
||||
</MapLayer>
|
||||
</Box>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default ShowArea;
|
||||
@@ -0,0 +1,29 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
import { FeatureGroup, useMap } from "react-leaflet";
|
||||
|
||||
const ShowBound = ({ bound }) => {
|
||||
const map = useMap();
|
||||
const featureRef = useRef(null);
|
||||
|
||||
const safeFitBounds = (layer) => {
|
||||
if (!layer || !map) return;
|
||||
try {
|
||||
const latLngs = layer.getLatLngs();
|
||||
map.fitBounds(latLngs, {
|
||||
paddingTopLeft: [20, 20],
|
||||
paddingBottomRight: [20, 20],
|
||||
});
|
||||
} catch (e) {
|
||||
console.warn("fitBounds failed:", e);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
bound?.editing?.disable();
|
||||
featureRef.current.addLayer(bound);
|
||||
safeFitBounds(bound);
|
||||
}, []);
|
||||
|
||||
return <FeatureGroup ref={featureRef} />;
|
||||
};
|
||||
export default ShowBound;
|
||||
125
src/components/dashboard/roadMissions/control/ControlList.jsx
Normal file
125
src/components/dashboard/roadMissions/control/ControlList.jsx
Normal file
@@ -0,0 +1,125 @@
|
||||
"use client";
|
||||
import DataTableWithAuth from "@/core/components/DataTableWithAuth";
|
||||
import { GET_ROAD_MISSIONS_CONTROL_LIST } from "@/core/utils/routes";
|
||||
import { Box, Stack } from "@mui/material";
|
||||
import moment from "jalali-moment";
|
||||
import { useMemo } from "react";
|
||||
import ShowArea from "./Actions/showArea";
|
||||
import RowActions from "./RowActions";
|
||||
|
||||
const ControlList = () => {
|
||||
const typeOptions = [
|
||||
{ value: 1, label: "روزانه" },
|
||||
{ value: 2, label: "ساعتی" },
|
||||
];
|
||||
|
||||
const columns = useMemo(
|
||||
() => [
|
||||
{
|
||||
accessorKey: "id",
|
||||
header: "کد یکتا",
|
||||
id: "id",
|
||||
enableColumnFilter: true,
|
||||
datatype: "text",
|
||||
filterMode: "equals",
|
||||
columnFilterModeOptions: ["equals", "contains"],
|
||||
grow: false,
|
||||
size: 100,
|
||||
},
|
||||
{
|
||||
accessorKey: "type",
|
||||
header: "نوع",
|
||||
id: "type",
|
||||
enableColumnFilter: true,
|
||||
datatype: "numeric",
|
||||
filterMode: "equals",
|
||||
sortDescFirst: true,
|
||||
grow: false,
|
||||
size: 100,
|
||||
columnSelectOption: () => {
|
||||
return typeOptions.map((type) => ({
|
||||
value: type.value,
|
||||
label: type.label,
|
||||
}));
|
||||
},
|
||||
Cell: ({ row }) => row.original.type_fa,
|
||||
},
|
||||
{
|
||||
accessorFn: (row) => moment(row.start_date).locale("fa").format("HH:mm | yyyy/MM/DD"),
|
||||
header: "تاریخ شروع",
|
||||
id: "start_date",
|
||||
enableColumnFilter: true,
|
||||
datatype: "date",
|
||||
filterMode: "between",
|
||||
grow: false,
|
||||
size: 100,
|
||||
},
|
||||
{
|
||||
accessorFn: (row) => moment(row.end_date).locale("fa").format("HH:mm | 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,
|
||||
},
|
||||
{
|
||||
header: "محدوده",
|
||||
id: "area",
|
||||
enableColumnFilter: false,
|
||||
datatype: "numeric",
|
||||
filterMode: "equals",
|
||||
grow: false,
|
||||
size: 100,
|
||||
muiTableBodyCellProps: {
|
||||
sx: {
|
||||
borderLeft: "1px solid #e1e1e1",
|
||||
py: 0,
|
||||
"&:first-of-type": {
|
||||
borderLeft: "unset",
|
||||
},
|
||||
},
|
||||
},
|
||||
Cell: ({ row }) =>
|
||||
row.original.area ? (
|
||||
<Stack alignItems={"center"} justifyContent={"center"}>
|
||||
<ShowArea area={row.original.area} />
|
||||
</Stack>
|
||||
) : (
|
||||
"-"
|
||||
),
|
||||
},
|
||||
],
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box sx={{ p: 1, border: 1, borderColor: "divider", borderRadius: 1 }}>
|
||||
<DataTableWithAuth
|
||||
need_filter={true}
|
||||
columns={columns}
|
||||
sorting={[{ id: "id", desc: true }]}
|
||||
table_url={GET_ROAD_MISSIONS_CONTROL_LIST}
|
||||
page_name={"roadMissionsControl"}
|
||||
table_name={"roadMissionsControlList"}
|
||||
enableRowActions
|
||||
positionActionsColumn={"first"}
|
||||
RowActions={RowActions}
|
||||
/>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default ControlList;
|
||||
@@ -0,0 +1,42 @@
|
||||
import { FINISH_MISSION } from "@/core/utils/routes";
|
||||
import useRequest from "@/lib/hooks/useRequest";
|
||||
import { Button, DialogActions, DialogContent, Stack, Typography } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
|
||||
const FinishMissionContent = ({ rowId, mutate, setOpenFinishMissionDialog }) => {
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const requestServer = useRequest({ notificationSuccess: true });
|
||||
const handleClick = () => {
|
||||
setSubmitting(true);
|
||||
requestServer(`${FINISH_MISSION}/${rowId}`, "post", {
|
||||
hasSidebarUpdate: true,
|
||||
})
|
||||
.then(() => {
|
||||
mutate();
|
||||
setOpenFinishMissionDialog(false);
|
||||
setSubmitting(false);
|
||||
})
|
||||
.catch(() => {
|
||||
setSubmitting(false);
|
||||
});
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<DialogContent>
|
||||
<Stack alignItems="center" spacing={2}>
|
||||
<Typography mt={2}>آیا از ورود خودرو و پایان ماموریت اطمینان دارید؟</Typography>
|
||||
</Stack>
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ justifyContent: "center", paddingBottom: 2, width: "100%" }}>
|
||||
<Button onClick={() => setOpenFinishMissionDialog(false)} variant="outlined" color="secondary">
|
||||
خیر !
|
||||
</Button>
|
||||
<Button onClick={handleClick} variant="contained" color="primary" disabled={submitting}>
|
||||
{submitting ? "درحال ثبت..." : "بله اطمینان دارم"}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default FinishMissionContent;
|
||||
@@ -0,0 +1,36 @@
|
||||
import { Login } from "@mui/icons-material";
|
||||
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
import FinishMissionContent from "./FinishMissionContent";
|
||||
const FinishMission = ({ rowId, mutate }) => {
|
||||
const [openFinishMissionDialog, setOpenFinishMissionDialog] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip title="ورود">
|
||||
<IconButton color="primary" onClick={() => setOpenFinishMissionDialog(true)}>
|
||||
<Login />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Dialog
|
||||
open={openFinishMissionDialog}
|
||||
onClose={() => setOpenFinishMissionDialog(false)}
|
||||
PaperProps={{
|
||||
sx: {
|
||||
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
|
||||
},
|
||||
}}
|
||||
dir="rtl"
|
||||
maxWidth={"md"}
|
||||
>
|
||||
<DialogTitle>ورود و پایان ماموریت</DialogTitle>
|
||||
<FinishMissionContent
|
||||
rowId={rowId}
|
||||
mutate={mutate}
|
||||
setOpenFinishMissionDialog={setOpenFinishMissionDialog}
|
||||
/>
|
||||
</Dialog>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default FinishMission;
|
||||
@@ -0,0 +1,42 @@
|
||||
import { START_MISSION } from "@/core/utils/routes";
|
||||
import useRequest from "@/lib/hooks/useRequest";
|
||||
import { Button, DialogActions, DialogContent, Stack, Typography } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
|
||||
const StartMissionContent = ({ rowId, mutate, setOpenStartMissionDialog }) => {
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const requestServer = useRequest({ notificationSuccess: true });
|
||||
const handleClick = () => {
|
||||
setSubmitting(true);
|
||||
requestServer(`${START_MISSION}/${rowId}`, "post", {
|
||||
hasSidebarUpdate: true,
|
||||
})
|
||||
.then(() => {
|
||||
mutate();
|
||||
setOpenStartMissionDialog(false);
|
||||
setSubmitting(false);
|
||||
})
|
||||
.catch(() => {
|
||||
setSubmitting(false);
|
||||
});
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<DialogContent>
|
||||
<Stack alignItems="center" spacing={2}>
|
||||
<Typography mt={2}>آیا از خروج خودرو و شروع ماموریت اطمینان دارید؟</Typography>
|
||||
</Stack>
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ justifyContent: "center", paddingBottom: 2, width: "100%" }}>
|
||||
<Button onClick={() => setOpenStartMissionDialog(false)} variant="outlined" color="secondary">
|
||||
خیر !
|
||||
</Button>
|
||||
<Button onClick={handleClick} variant="contained" color="primary" disabled={submitting}>
|
||||
{submitting ? "درحال ثبت..." : "بله اطمینان دارم"}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default StartMissionContent;
|
||||
@@ -0,0 +1,36 @@
|
||||
import { Logout } from "@mui/icons-material";
|
||||
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
import StartMissionContent from "./StartMissionContent";
|
||||
const StartMission = ({ rowId, mutate }) => {
|
||||
const [openStartMissionDialog, setOpenStartMissionDialog] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip title="خروج">
|
||||
<IconButton color="primary" onClick={() => setOpenStartMissionDialog(true)}>
|
||||
<Logout />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Dialog
|
||||
open={openStartMissionDialog}
|
||||
onClose={() => setOpenStartMissionDialog(false)}
|
||||
PaperProps={{
|
||||
sx: {
|
||||
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
|
||||
},
|
||||
}}
|
||||
dir="rtl"
|
||||
maxWidth={"md"}
|
||||
>
|
||||
<DialogTitle>خروج و شروع ماموریت</DialogTitle>
|
||||
<StartMissionContent
|
||||
rowId={rowId}
|
||||
mutate={mutate}
|
||||
setOpenStartMissionDialog={setOpenStartMissionDialog}
|
||||
/>
|
||||
</Dialog>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default StartMission;
|
||||
@@ -0,0 +1,13 @@
|
||||
import { Box } from "@mui/material";
|
||||
import FinishMission from "./FinishMission";
|
||||
import StartMission from "./StartMission";
|
||||
|
||||
const RowActions = ({ row, mutate }) => {
|
||||
return (
|
||||
<Box sx={{ display: "flex", gap: 1 }}>
|
||||
{row.original.state_id == 2 && <StartMission rowId={row.getValue("id")} mutate={mutate} />}
|
||||
{row.original.state_id == 3 && <FinishMission rowId={row.getValue("id")} mutate={mutate} />}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
export default RowActions;
|
||||
13
src/components/dashboard/roadMissions/control/index.jsx
Normal file
13
src/components/dashboard/roadMissions/control/index.jsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import PageTitle from "@/core/components/PageTitle";
|
||||
import { Stack } from "@mui/material";
|
||||
import ControlList from "./ControlList";
|
||||
|
||||
const ControlPage = () => {
|
||||
return (
|
||||
<Stack spacing={1}>
|
||||
<PageTitle title={"کارتابل کنترل"} />
|
||||
<ControlList />
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
export default ControlPage;
|
||||
Reference in New Issue
Block a user