diff --git a/src/app/(withAuth)/dashboard/road-safety/reports/map/page.js b/src/app/(withAuth)/dashboard/road-safety/reports/map/page.js
new file mode 100644
index 0000000..b272e5e
--- /dev/null
+++ b/src/app/(withAuth)/dashboard/road-safety/reports/map/page.js
@@ -0,0 +1,9 @@
+import RoadSafetyReportMap from "@/components/dashboard/roadSafety/reports/map";
+export const metadata = {
+ title: "پراکندگی بر روی نقشه نگهداری حریم",
+};
+
+const Page = () => {
+ return ;
+};
+export default Page;
diff --git a/src/app/(withAuth)/dashboard/road-safety/report/page.js b/src/app/(withAuth)/dashboard/road-safety/reports/page.js
similarity index 97%
rename from src/app/(withAuth)/dashboard/road-safety/report/page.js
rename to src/app/(withAuth)/dashboard/road-safety/reports/page.js
index 26681da..54df8d0 100644
--- a/src/app/(withAuth)/dashboard/road-safety/report/page.js
+++ b/src/app/(withAuth)/dashboard/road-safety/reports/page.js
@@ -1,4 +1,4 @@
-import ReportPage from "@/components/dashboard/roadSafety/report";
+import ReportPage from "@/components/dashboard/roadSafety/reports/reportPage";
import WithPermission from "@/core/middlewares/withPermission";
export const metadata = {
title: "کارتابل گزارش نگهداری حریم",
diff --git a/src/components/dashboard/fastReact/complaintList/ComplaintListTable.jsx b/src/components/dashboard/fastReact/complaintList/ComplaintListTable.jsx
index 4ca8402..ac16216 100644
--- a/src/components/dashboard/fastReact/complaintList/ComplaintListTable.jsx
+++ b/src/components/dashboard/fastReact/complaintList/ComplaintListTable.jsx
@@ -237,10 +237,7 @@ const ComplaintListTable = ({ open, setOpen, mutate }) => {
size: 100,
},
{
- accessorFn: (row) =>
- moment(row.StartTime_DateTime, "M/D/YYYY h:mm:ss A")
- .locale("fa")
- .format("HH:mm | yyyy/MM/DD"),
+ accessorFn: (row) => moment(row.StartTime_DateTime).locale("fa").format("HH:mm | yyyy/MM/DD"),
header: "تاریخ ثبت",
id: "StartTime_DateTime",
enableColumnFilter: false,
diff --git a/src/components/dashboard/fastReact/operator/OperatorList.jsx b/src/components/dashboard/fastReact/operator/OperatorList.jsx
index 925d89e..9de64f1 100644
--- a/src/components/dashboard/fastReact/operator/OperatorList.jsx
+++ b/src/components/dashboard/fastReact/operator/OperatorList.jsx
@@ -149,10 +149,7 @@ const OperatorList = () => {
size: 100,
},
{
- accessorFn: (row) =>
- moment(row.StartTime_DateTime, "M/D/YYYY h:mm:ss A")
- .locale("fa")
- .format("HH:mm | yyyy/MM/DD"),
+ accessorFn: (row) => moment(row.StartTime_DateTime).locale("fa").format("HH:mm | yyyy/MM/DD"),
header: "تاریخ ثبت",
id: "StartTime_DateTime",
enableColumnFilter: false,
diff --git a/src/components/dashboard/fastReact/supervisor/SupervisorList.jsx b/src/components/dashboard/fastReact/supervisor/SupervisorList.jsx
index b10eade..d543a18 100644
--- a/src/components/dashboard/fastReact/supervisor/SupervisorList.jsx
+++ b/src/components/dashboard/fastReact/supervisor/SupervisorList.jsx
@@ -250,10 +250,7 @@ const SupervisorList = () => {
size: 100,
},
{
- accessorFn: (row) =>
- moment(row.StartTime_DateTime, "M/D/YYYY h:mm:ss A")
- .locale("fa")
- .format("HH:mm | yyyy/MM/DD"),
+ accessorFn: (row) => moment(row.StartTime_DateTime).locale("fa").format("HH:mm | yyyy/MM/DD"),
header: "تاریخ ثبت",
id: "StartTime_DateTime",
enableColumnFilter: false,
diff --git a/src/components/dashboard/roadSafety/operator/OperatorList.jsx b/src/components/dashboard/roadSafety/operator/OperatorList.jsx
index c59e81b..facec54 100644
--- a/src/components/dashboard/roadSafety/operator/OperatorList.jsx
+++ b/src/components/dashboard/roadSafety/operator/OperatorList.jsx
@@ -396,15 +396,13 @@ const OperatorList = () => {
},
{
accessorFn: (row) =>
- row.action_picture_document_upload_date ? (
- moment(row.action_picture_document_upload_date)
- .locale("fa")
- .format("HH:mm | yyyy/MM/DD")
+ row.action_date ? (
+ moment(row.action_date).locale("fa").format("HH:mm | yyyy/MM/DD")
) : (
<>->
),
- header: "تاریخ ثبت اقدام",
- id: "action_picture_document_upload_date",
+ header: "تاریخ اقدام",
+ id: "action_date",
enableColumnFilter: true,
datatype: "date",
filterMode: "between",
diff --git a/src/components/dashboard/roadSafety/reports/map/ClusterSwitch/index.jsx b/src/components/dashboard/roadSafety/reports/map/ClusterSwitch/index.jsx
new file mode 100644
index 0000000..e8fac87
--- /dev/null
+++ b/src/components/dashboard/roadSafety/reports/map/ClusterSwitch/index.jsx
@@ -0,0 +1,25 @@
+import DoneIcon from "@mui/icons-material/Done";
+import { Chip, Tooltip, Zoom } from "@mui/material";
+
+const ClusterSwitch = ({ isCluster, setCluster, disabled, max }) => {
+ return (
+
+
+ setCluster((c) => !c)}
+ sx={{ borderRadius: 1 }}
+ icon={
+
+
+
+ }
+ />
+
+
+ );
+};
+export default ClusterSwitch;
diff --git a/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/ActionDate.jsx b/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/ActionDate.jsx
new file mode 100644
index 0000000..431c7ac
--- /dev/null
+++ b/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/ActionDate.jsx
@@ -0,0 +1,32 @@
+import MuiDatePicker from "@/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker";
+import { Box } from "@mui/material";
+
+const ActionDate = ({ value, onChange, error }) => {
+ return (
+
+ {
+ onChange([formattedDate, value[1]]);
+ }}
+ maxDate={value[1]}
+ placeholder={`از تاریخ`}
+ />
+ {
+ onChange([value[0], formattedDate]);
+ }}
+ minDate={value[0]}
+ placeholder={`تا تاریخ`}
+ helperText={error ? error.message : null}
+ error={Boolean(error)}
+ />
+
+ );
+};
+export default ActionDate;
diff --git a/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/ActivityDateTimeFilter.jsx b/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/ActivityDateTimeFilter.jsx
new file mode 100644
index 0000000..143c0cd
--- /dev/null
+++ b/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/ActivityDateTimeFilter.jsx
@@ -0,0 +1,32 @@
+import MuiDatePicker from "@/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker";
+import { Box } from "@mui/material";
+
+const ActivityDateTimeFilter = ({ value, onChange, error }) => {
+ return (
+
+ {
+ onChange([formattedDate, value[1]]);
+ }}
+ maxDate={value[1]}
+ placeholder={`از تاریخ`}
+ />
+ {
+ onChange([value[0], formattedDate]);
+ }}
+ minDate={value[0]}
+ placeholder={`تا تاریخ`}
+ helperText={error ? error.message : null}
+ error={Boolean(error)}
+ />
+
+ );
+};
+export default ActivityDateTimeFilter;
diff --git a/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/AxisTypeFilter.jsx b/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/AxisTypeFilter.jsx
new file mode 100644
index 0000000..037a6a2
--- /dev/null
+++ b/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/AxisTypeFilter.jsx
@@ -0,0 +1,37 @@
+import { FormControl, InputLabel, MenuItem, OutlinedInput, Select } from "@mui/material";
+
+const AxisTypeFilter = ({ value, onChange }) => {
+ const axisOptions = [
+ { value: "", label: "همه محور ها" },
+ { value: 1, label: "آزادراه" },
+ { value: 2, label: "بزرگراه" },
+ { value: 3, label: "اصلی" },
+ { value: 4, label: "فرعی" },
+ { value: 5, label: "روستایی" },
+ ];
+
+ return (
+
+
+ نوع محور
+
+ }
+ size="small"
+ onChange={(e) => onChange(e.target.value)}
+ displayEmpty
+ >
+ {axisOptions.map((option) => (
+
+ ))}
+
+
+ );
+};
+export default AxisTypeFilter;
diff --git a/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/CreatedAtFilter.jsx b/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/CreatedAtFilter.jsx
new file mode 100644
index 0000000..1bcffba
--- /dev/null
+++ b/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/CreatedAtFilter.jsx
@@ -0,0 +1,32 @@
+import MuiDatePicker from "@/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker";
+import { Box } from "@mui/material";
+
+const CreatedAtFilter = ({ value, onChange, error }) => {
+ return (
+
+ {
+ onChange([formattedDate, value[1]]);
+ }}
+ maxDate={value[1]}
+ placeholder={`از تاریخ`}
+ />
+ {
+ onChange([value[0], formattedDate]);
+ }}
+ minDate={value[0]}
+ placeholder={`تا تاریخ`}
+ helperText={error ? error.message : null}
+ error={Boolean(error)}
+ />
+
+ );
+};
+export default CreatedAtFilter;
diff --git a/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/EdarehShahriFilter.jsx b/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/EdarehShahriFilter.jsx
new file mode 100644
index 0000000..eb08e27
--- /dev/null
+++ b/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/EdarehShahriFilter.jsx
@@ -0,0 +1,65 @@
+"use client";
+import useEdaratLists from "@/lib/hooks/useEdaratLists";
+import { FormControl, InputLabel, MenuItem, OutlinedInput, Select } from "@mui/material";
+import { useEffect, useMemo, useState } from "react";
+import { useWatch } from "react-hook-form";
+
+const EdarehShahriFilter = ({ control, value, onChange }) => {
+ const dependencyField = useWatch({ control, name: "province_id" });
+ return ;
+};
+
+const EdarehShahriController = ({ value, onChange, dependencyField }) => {
+ const { edaratList, loadingEdaratList, errorEdaratList } = useEdaratLists(dependencyField);
+ const [prevDependency, setPrevDependency] = useState(dependencyField);
+
+ const columnSelectOption = useMemo(() => {
+ if (dependencyField === "") {
+ return [{ value: "empty", label: "ابتدا استان را انتخاب کنید" }];
+ }
+ if (loadingEdaratList) {
+ return [{ value: "loading", label: "در حال بارگذاری..." }];
+ }
+ if (errorEdaratList) {
+ return [{ value: "error", label: "خطا در بارگذاری" }];
+ }
+ return [
+ { value: "", label: "کل ادارات" },
+ ...edaratList.map((edare) => ({
+ value: edare.id,
+ label: edare.name_fa,
+ })),
+ ];
+ }, [edaratList, loadingEdaratList, errorEdaratList]);
+
+ useEffect(() => {
+ if (prevDependency === dependencyField) return;
+ onChange("");
+ setPrevDependency(dependencyField);
+ }, [dependencyField]);
+
+ return (
+
+
+ اداره
+
+ }
+ size="small"
+ onChange={(e) => onChange(e.target.value)}
+ displayEmpty
+ >
+ {columnSelectOption.map((option) => (
+
+ ))}
+
+
+ );
+};
+export default EdarehShahriFilter;
diff --git a/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/InfoFilter.jsx b/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/InfoFilter.jsx
new file mode 100644
index 0000000..605c0af
--- /dev/null
+++ b/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/InfoFilter.jsx
@@ -0,0 +1,47 @@
+import useSafetyAndPrivacyGetItems from "@/lib/hooks/useSafetyAndPrivacyGetItems";
+import { FormControl, InputLabel, MenuItem, OutlinedInput, Select } from "@mui/material";
+import { useMemo } from "react";
+
+const InfoFilter = ({ value, onChange }) => {
+ const { itemsList, loadingItemsList, errorItemsList } = useSafetyAndPrivacyGetItems();
+ const columnSelectOption = useMemo(() => {
+ if (loadingItemsList) {
+ return [{ value: "loading", label: "در حال بارگذاری..." }];
+ }
+ if (errorItemsList) {
+ return [{ value: "error", label: "خطا در بارگذاری" }];
+ }
+ return [
+ { value: "", label: "همه موارد" },
+ ...itemsList.map((item) => ({
+ value: item.id,
+ label: item.name,
+ })),
+ ];
+ }, [itemsList, loadingItemsList, errorItemsList]);
+
+ return (
+
+
+ مورد مشاهده شده
+
+ }
+ size="small"
+ onChange={(e) => onChange(e.target.value)}
+ displayEmpty
+ >
+ {columnSelectOption.map((option) => (
+
+ ))}
+
+
+ );
+};
+export default InfoFilter;
diff --git a/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/JudiciaryDocumentUploadDateFilter.jsx b/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/JudiciaryDocumentUploadDateFilter.jsx
new file mode 100644
index 0000000..24a6b2f
--- /dev/null
+++ b/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/JudiciaryDocumentUploadDateFilter.jsx
@@ -0,0 +1,32 @@
+import MuiDatePicker from "@/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker";
+import { Box } from "@mui/material";
+
+const JudiciaryDocumentUploadDateFilter = ({ value, onChange, error }) => {
+ return (
+
+ {
+ onChange([formattedDate, value[1]]);
+ }}
+ maxDate={value[1]}
+ placeholder={`از تاریخ`}
+ />
+ {
+ onChange([value[0], formattedDate]);
+ }}
+ minDate={value[0]}
+ placeholder={`تا تاریخ`}
+ helperText={error ? error.message : null}
+ error={Boolean(error)}
+ />
+
+ );
+};
+export default JudiciaryDocumentUploadDateFilter;
diff --git a/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/ProvinceFilter.jsx b/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/ProvinceFilter.jsx
new file mode 100644
index 0000000..4de3f9e
--- /dev/null
+++ b/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/ProvinceFilter.jsx
@@ -0,0 +1,47 @@
+import useProvinces from "@/lib/hooks/useProvince";
+import { FormControl, InputLabel, MenuItem, OutlinedInput, Select } from "@mui/material";
+import { useMemo } from "react";
+
+const ProvinceFilter = ({ value, onChange }) => {
+ const { provinces, errorProvinces, loadingProvinces } = useProvinces();
+ const columnSelectOption = useMemo(() => {
+ if (loadingProvinces) {
+ return [{ value: "loading", label: "در حال بارگذاری..." }];
+ }
+ if (errorProvinces) {
+ return [{ value: "error", label: "خطا در بارگذاری" }];
+ }
+ return [
+ { value: "", label: "کل کشور" },
+ ...provinces.map((province) => ({
+ value: province.id,
+ label: province.name_fa,
+ })),
+ ];
+ }, [provinces, errorProvinces, loadingProvinces]);
+
+ return (
+
+
+ استان
+
+ }
+ size="small"
+ onChange={(e) => onChange(e.target.value)}
+ displayEmpty
+ >
+ {columnSelectOption.map((option) => (
+
+ ))}
+
+
+ );
+};
+export default ProvinceFilter;
diff --git a/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/StepFilter.jsx b/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/StepFilter.jsx
new file mode 100644
index 0000000..b6eca29
--- /dev/null
+++ b/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/StepFilter.jsx
@@ -0,0 +1,35 @@
+import { FormControl, InputLabel, MenuItem, OutlinedInput, Select } from "@mui/material";
+
+const StepFilter = ({ value, onChange }) => {
+ const statusOptions = [
+ { value: "", label: "همه وضعیت ها" },
+ { value: 1, label: "گام اول (شناسایی)" },
+ { value: 2, label: "گام دوم (مستندات قضایی)" },
+ { value: 3, label: "گام سوم (برخورد)" },
+ ];
+
+ return (
+
+
+ وضعیت
+
+ }
+ size="small"
+ onChange={(e) => onChange(e.target.value)}
+ displayEmpty
+ >
+ {statusOptions.map((option) => (
+
+ ))}
+
+
+ );
+};
+export default StepFilter;
diff --git a/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/index.jsx b/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/index.jsx
new file mode 100644
index 0000000..1a39633
--- /dev/null
+++ b/src/components/dashboard/roadSafety/reports/map/Filter/Drawer/index.jsx
@@ -0,0 +1,166 @@
+import ScrollBox from "@/core/components/ScrollBox";
+import { yupResolver } from "@hookform/resolvers/yup";
+import CancelIcon from "@mui/icons-material/Cancel";
+import FilterAltIcon from "@mui/icons-material/FilterAlt";
+import { Box, Button, IconButton, Typography } from "@mui/material";
+import { Controller, useForm } from "react-hook-form";
+import * as Yup from "yup";
+import ActivityDateTimeFilter from "./ActivityDateTimeFilter";
+import AxisTypeFilter from "./AxisTypeFilter";
+import EdarehShahriFilter from "./EdarehShahriFilter";
+import InfoFilter from "./InfoFilter";
+import ProvinceFilter from "./ProvinceFilter";
+import StepFilter from "./StepFilter";
+import CreatedAtFilter from "./CreatedAtFilter";
+import JudiciaryDocumentUploadDateFilter from "./JudiciaryDocumentUploadDateFilter";
+import ActionPictureDocumentUploadDateFilter from "./ActionDate";
+import ActionDate from "./ActionDate";
+
+const validationSchema = Yup.object({
+ activity_date_time: Yup.array()
+ .of(Yup.string().nullable())
+ .test({
+ test(value, ctx) {
+ const [start, end] = value || ["", ""];
+ if ((start && !end) || (!start && end)) {
+ return ctx.createError({ message: "این بخش را تکمیل نمایید" });
+ }
+ return true;
+ },
+ }),
+});
+
+const headerSx = {
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "space-between",
+ px: 2,
+ py: 1,
+ backgroundColor: "#155175",
+ boxShadow: "rgba(0, 0, 0, 0.19) 0px 10px 20px, rgba(0, 0, 0, 0.23) 0px 6px 6px",
+ maxWidth: "450px",
+};
+
+const headerTitleSx = { display: "flex", alignItems: "center" };
+const headerIconSx = { color: "#fff", mr: 1 };
+const iconButtonSx = { color: "#fff" };
+
+const formContainerSx = { px: 2, py: 3 };
+const footerSx = { display: "flex", justifyContent: "center", alignItems: "center", pb: 2 };
+
+const submitButtonSx = {
+ px: 8,
+ boxShadow: "rgba(0, 0, 0, 0.23) 0px 6px 6px, rgba(0, 0, 0, 0.19) 10px 0px 20px",
+ backgroundColor: "primary2",
+ ":hover": { backgroundColor: "primary2" },
+};
+
+const FilterDrawer = ({ defaultValues, setFilterData, closeDrawer }) => {
+ const {
+ control,
+ handleSubmit,
+ formState: { isDirty },
+ } = useForm({
+ defaultValues,
+ resolver: yupResolver(validationSchema),
+ mode: "onBlur",
+ });
+
+ const onSubmit = (data) => {
+ setFilterData(data);
+ closeDrawer();
+ };
+
+ return (
+ <>
+
+
+
+
+ فیلتر
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+export default FilterDrawer;
diff --git a/src/components/dashboard/roadSafety/reports/map/Filter/index.jsx b/src/components/dashboard/roadSafety/reports/map/Filter/index.jsx
new file mode 100644
index 0000000..c12a511
--- /dev/null
+++ b/src/components/dashboard/roadSafety/reports/map/Filter/index.jsx
@@ -0,0 +1,44 @@
+"use client";
+import { Box, Button, Drawer } from "@mui/material";
+import FilterListIcon from "@mui/icons-material/FilterList";
+import { useCallback, useState } from "react";
+import FilterDrawer from "./Drawer";
+
+const drawerSx = {
+ overflowY: "hidden",
+ display: "flex",
+ flexDirection: "column",
+ height: "100%",
+ zIndex: "1300",
+};
+
+const boxSx = {
+ width: { xs: 300, sm: 450 },
+};
+
+const Filter = ({ filterData, setFilterData }) => {
+ const [open, setOpen] = useState(false);
+
+ const openDrawer = useCallback(() => setOpen(true), []);
+ const closeDrawer = useCallback(() => setOpen(false), []);
+
+ return (
+ <>
+ }>
+ فیلتر
+
+
+
+ {open && (
+
+ )}
+
+
+ >
+ );
+};
+export default Filter;
diff --git a/src/components/dashboard/roadSafety/reports/map/Legend/index.jsx b/src/components/dashboard/roadSafety/reports/map/Legend/index.jsx
new file mode 100644
index 0000000..91bc710
--- /dev/null
+++ b/src/components/dashboard/roadSafety/reports/map/Legend/index.jsx
@@ -0,0 +1,48 @@
+import { Box, Stack, Typography } from "@mui/material";
+
+const Legend = () => {
+ return (
+
+
+ theme.palette.warning.main,
+ background: (theme) => theme.palette.warning.light,
+ }}
+ />
+ گام اول (شناسایی)
+
+
+ theme.palette.error.main,
+ background: (theme) => theme.palette.error.light,
+ }}
+ />
+ گام دوم (مستندات قضایی)
+
+
+ theme.palette.success.main,
+ background: (theme) => theme.palette.success.light,
+ }}
+ />
+ گام سوم (برخورد)
+
+
+ );
+};
+export default Legend;
diff --git a/src/components/dashboard/roadSafety/reports/map/PointsOnMap/DialogInfoItem/ContentInfoItem.jsx b/src/components/dashboard/roadSafety/reports/map/PointsOnMap/DialogInfoItem/ContentInfoItem.jsx
new file mode 100644
index 0000000..bcfc03d
--- /dev/null
+++ b/src/components/dashboard/roadSafety/reports/map/PointsOnMap/DialogInfoItem/ContentInfoItem.jsx
@@ -0,0 +1,94 @@
+import { Box, Chip, Divider, Stack, Typography } from "@mui/material";
+import moment from "jalali-moment";
+import Image from "next/image";
+
+const ContentInfoItem = ({ data }) => {
+ return (
+
+
+
+
+ {data.id !== "" && data.id}
+
+
+
+
+
+ {data.province_fa !== "" && data.province_fa}
+
+
+
+
+
+
+ {data.edare_shahri_name !== "" && data.edare_shahri_name}
+
+
+
+
+
+
+ {data.info_fa !== "" && data.info_fa}
+
+
+
+
+
+
+ {data.axis_type_name !== "" && data.axis_type_name}
+
+
+
+
+
+
+ {data.step_fa !== "" && data.step_fa}
+
+
+
+
+
+
+ {data.activity_date_time &&
+ moment(data.activity_date_time).locale("fa").format("HH:mm | yyyy/MM/DD")}
+
+
+ {data.step == 3 && (
+
+
+
+
+ {data.action_date && moment(data.action_date).locale("fa").format("HH:mm | yyyy/MM/DD")}
+
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+export default ContentInfoItem;
diff --git a/src/components/dashboard/roadSafety/reports/map/PointsOnMap/DialogInfoItem/index.jsx b/src/components/dashboard/roadSafety/reports/map/PointsOnMap/DialogInfoItem/index.jsx
new file mode 100644
index 0000000..3107c53
--- /dev/null
+++ b/src/components/dashboard/roadSafety/reports/map/PointsOnMap/DialogInfoItem/index.jsx
@@ -0,0 +1,51 @@
+import DialogLoading from "@/core/components/DialogLoading";
+import { GET_ROAD_SAFETY_DETAILS } from "@/core/utils/routes";
+import useRequest from "@/lib/hooks/useRequest";
+import { Button, DialogActions, DialogContent, DialogTitle } from "@mui/material";
+import { useEffect, useState } from "react";
+import ContentInfoItem from "./ContentInfoItem";
+
+const DialogInfoItem = ({ selectedId, closeDialog }) => {
+ const request = useRequest();
+ const [loading, setLoading] = useState(true);
+ const [data, setData] = useState(null);
+
+ useEffect(() => {
+ const controller = new AbortController();
+
+ const fetchItem = async () => {
+ setLoading(true);
+ setData(null);
+ try {
+ const response = await request(`${GET_ROAD_SAFETY_DETAILS}/${selectedId}`, "get", {
+ signal: controller.signal,
+ });
+ setData(response.data.data);
+ } catch (error) {
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ fetchItem();
+
+ return () => {
+ controller.abort();
+ };
+ }, [selectedId]);
+
+ return (
+ <>
+ جزئیات فعالیت
+
+ {loading ? : data && }
+
+
+
+
+ >
+ );
+};
+export default DialogInfoItem;
diff --git a/src/components/dashboard/roadSafety/reports/map/PointsOnMap/index.jsx b/src/components/dashboard/roadSafety/reports/map/PointsOnMap/index.jsx
new file mode 100644
index 0000000..b965bda
--- /dev/null
+++ b/src/components/dashboard/roadSafety/reports/map/PointsOnMap/index.jsx
@@ -0,0 +1,71 @@
+import { Dialog, useTheme } from "@mui/material";
+import { useCallback, useEffect, useMemo, useState } from "react";
+import { CircleMarker, useMap } from "react-leaflet";
+import MarkerClusterGroup from "react-leaflet-markercluster";
+import DialogInfoItem from "./DialogInfoItem";
+
+const PointsOnMap = ({ data, isCluster }) => {
+ const map = useMap();
+ const theme = useTheme();
+ const [selectedId, setSelectedId] = useState(null);
+ const [open, setOpen] = useState(false);
+
+ const openDialog = useCallback(() => setOpen(true), []);
+ const closeDialog = useCallback(() => setOpen(false), []);
+
+ const getMarkerColor = (status) => {
+ if (status === 1) return theme.palette.warning.main;
+ if (status === 2) return theme.palette.error.main;
+ return theme.palette.success.main;
+ };
+
+ const markers = useMemo(() => {
+ return data.map(({ id, lat, lon, step }) => (
+ {
+ openDialog();
+ setSelectedId(id);
+ },
+ }}
+ key={id}
+ center={L.latLng(lat, lon)}
+ radius={8}
+ color={getMarkerColor(step)}
+ />
+ ));
+ }, [data, theme]);
+
+ useEffect(() => {
+ if (data.length === 0) return;
+ const bounds = L.latLngBounds(data.map(({ lat, lon }) => L.latLng(lat, lon)));
+ map.flyToBounds(bounds, { duration: 0.7 });
+ }, [data]);
+
+ const createClusterCustomIcon = (cluster) => {
+ const count = cluster.getChildCount();
+ return L.divIcon({
+ html: `${count}
`,
+ className: "custom-marker-cluster",
+ iconSize: L.point(40, 40, true),
+ });
+ };
+
+ if (data.length === 0) return null;
+
+ return (
+ <>
+ {isCluster ? (
+
+ {markers}
+
+ ) : (
+ markers
+ )}
+
+ >
+ );
+};
+export default PointsOnMap;
diff --git a/src/components/dashboard/roadSafety/reports/map/index.jsx b/src/components/dashboard/roadSafety/reports/map/index.jsx
new file mode 100644
index 0000000..907f90b
--- /dev/null
+++ b/src/components/dashboard/roadSafety/reports/map/index.jsx
@@ -0,0 +1,160 @@
+"use client";
+import LoadingHardPage from "@/core/components/LoadingHardPage";
+import MapLoading from "@/core/components/MapLayer/Loading";
+import { GET_ROAD_SAFETY_REPORT_MAP } from "@/core/utils/routes";
+import useRequest from "@/lib/hooks/useRequest";
+import { Box, Stack } from "@mui/material";
+import dynamic from "next/dynamic";
+import { useCallback, useEffect, useState } from "react";
+import ClusterSwitch from "./ClusterSwitch";
+import Filter from "./Filter";
+import Legend from "./Legend";
+import PointsOnMap from "./PointsOnMap";
+const MapLayer = dynamic(() => import("@/core/components/MapLayer"), {
+ loading: () => ,
+ ssr: false,
+});
+
+const defaultValues = {
+ province_id: "",
+ edarat_id: "",
+ info_id: "",
+ axis_type_id: "",
+ step: "",
+ created_at: ["", ""],
+ activity_date_time: ["", ""],
+ judiciary_document_upload_date: ["", ""],
+ action_date: ["", ""],
+};
+
+const MAX_POINTS = 1000;
+
+const containerStyles = {
+ width: "100%",
+ height: "100%",
+ p: 1,
+ border: "1px dashed",
+ borderColor: "divider",
+ borderRadius: 1,
+};
+
+const controlBarStyles = {
+ p: 1,
+ background: "#fff",
+};
+
+const RoadSafetyReportMap = () => {
+ const requestServer = useRequest();
+ const [filterData, setFilterData] = useState(defaultValues);
+ const [isCluster, setCluster] = useState(false);
+ const [data, setData] = useState([]);
+ const [isLoading, setLoading] = useState(true);
+
+ const buildQueryParams = useCallback(() => {
+ const params = new URLSearchParams();
+ const {
+ province_id,
+ edarat_id,
+ info_id,
+ axis_type_id,
+ step,
+ created_at,
+ activity_date_time,
+ judiciary_document_upload_date,
+ action_date,
+ } = filterData;
+
+ const filterArray = [];
+
+ if (province_id) filterArray.push({ id: "province_id", fn: "equals", datatype: "numeric", value: province_id });
+ if (edarat_id) filterArray.push({ id: "edarat_id", fn: "equals", datatype: "numeric", value: edarat_id });
+ if (info_id) filterArray.push({ id: "info_id", fn: "equals", datatype: "numeric", value: info_id });
+ if (axis_type_id)
+ filterArray.push({ id: "axis_type_id", fn: "equals", datatype: "numeric", value: axis_type_id });
+ if (step) filterArray.push({ id: "step", fn: "equals", datatype: "numeric", value: step });
+ if (created_at[0]) filterArray.push({ id: "created_at", fn: "between", datatype: "date", value: created_at });
+ if (activity_date_time[0])
+ filterArray.push({ id: "activity_date_time", fn: "between", datatype: "date", value: activity_date_time });
+ if (judiciary_document_upload_date[0])
+ filterArray.push({
+ id: "judiciary_document_upload_date",
+ fn: "between",
+ datatype: "date",
+ value: judiciary_document_upload_date,
+ });
+ if (action_date[0])
+ filterArray.push({ id: "action_date", fn: "between", datatype: "date", value: action_date });
+
+ console.log(filterArray);
+
+ params.set("filters", JSON.stringify(filterArray || []));
+ return params.toString();
+ }, [filterData]);
+
+ useEffect(() => {
+ console.log("gasgsa");
+
+ const fetchData = async () => {
+ try {
+ setLoading(true);
+ const query = buildQueryParams();
+ console.log("amir");
+
+ const response = await requestServer(`${GET_ROAD_SAFETY_REPORT_MAP}?${query}`);
+ const fetchedData = response?.data?.data || [];
+
+ if (fetchedData.length > MAX_POINTS) {
+ setCluster(true);
+ }
+ setData(fetchedData);
+ } catch (error) {
+ console.log(error);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ fetchData();
+ }, [filterData, buildQueryParams]);
+
+ console.log("sfa");
+
+ return (
+
+
+
+
+ MAX_POINTS}
+ max={MAX_POINTS}
+ />
+
+
+
+
+
+
+
+
+
+
+ {isLoading && (
+
+
+
+ )}
+
+
+
+
+ );
+};
+export default RoadSafetyReportMap;
diff --git a/src/components/dashboard/roadSafety/report/ExcelPrint/index.jsx b/src/components/dashboard/roadSafety/reports/reportPage/ExcelPrint/index.jsx
similarity index 100%
rename from src/components/dashboard/roadSafety/report/ExcelPrint/index.jsx
rename to src/components/dashboard/roadSafety/reports/reportPage/ExcelPrint/index.jsx
diff --git a/src/components/dashboard/roadSafety/report/ReportLists.jsx b/src/components/dashboard/roadSafety/reports/reportPage/ReportLists.jsx
similarity index 100%
rename from src/components/dashboard/roadSafety/report/ReportLists.jsx
rename to src/components/dashboard/roadSafety/reports/reportPage/ReportLists.jsx
diff --git a/src/components/dashboard/roadSafety/report/Search/FromDateController.jsx b/src/components/dashboard/roadSafety/reports/reportPage/Search/FromDateController.jsx
similarity index 100%
rename from src/components/dashboard/roadSafety/report/Search/FromDateController.jsx
rename to src/components/dashboard/roadSafety/reports/reportPage/Search/FromDateController.jsx
diff --git a/src/components/dashboard/roadSafety/report/Search/SearchReportField.jsx b/src/components/dashboard/roadSafety/reports/reportPage/Search/SearchReportField.jsx
similarity index 100%
rename from src/components/dashboard/roadSafety/report/Search/SearchReportField.jsx
rename to src/components/dashboard/roadSafety/reports/reportPage/Search/SearchReportField.jsx
diff --git a/src/components/dashboard/roadSafety/report/Search/SelectAxisType.jsx b/src/components/dashboard/roadSafety/reports/reportPage/Search/SelectAxisType.jsx
similarity index 100%
rename from src/components/dashboard/roadSafety/report/Search/SelectAxisType.jsx
rename to src/components/dashboard/roadSafety/reports/reportPage/Search/SelectAxisType.jsx
diff --git a/src/components/dashboard/roadSafety/report/Search/SelectProvince.jsx b/src/components/dashboard/roadSafety/reports/reportPage/Search/SelectProvince.jsx
similarity index 100%
rename from src/components/dashboard/roadSafety/report/Search/SelectProvince.jsx
rename to src/components/dashboard/roadSafety/reports/reportPage/Search/SelectProvince.jsx
diff --git a/src/components/dashboard/roadSafety/report/Search/ToDateController.jsx b/src/components/dashboard/roadSafety/reports/reportPage/Search/ToDateController.jsx
similarity index 100%
rename from src/components/dashboard/roadSafety/report/Search/ToDateController.jsx
rename to src/components/dashboard/roadSafety/reports/reportPage/Search/ToDateController.jsx
diff --git a/src/components/dashboard/roadSafety/report/Search/index.jsx b/src/components/dashboard/roadSafety/reports/reportPage/Search/index.jsx
similarity index 100%
rename from src/components/dashboard/roadSafety/report/Search/index.jsx
rename to src/components/dashboard/roadSafety/reports/reportPage/Search/index.jsx
diff --git a/src/components/dashboard/roadSafety/report/Toolbar.jsx b/src/components/dashboard/roadSafety/reports/reportPage/Toolbar.jsx
similarity index 100%
rename from src/components/dashboard/roadSafety/report/Toolbar.jsx
rename to src/components/dashboard/roadSafety/reports/reportPage/Toolbar.jsx
diff --git a/src/components/dashboard/roadSafety/report/index.jsx b/src/components/dashboard/roadSafety/reports/reportPage/index.jsx
similarity index 100%
rename from src/components/dashboard/roadSafety/report/index.jsx
rename to src/components/dashboard/roadSafety/reports/reportPage/index.jsx
diff --git a/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarSubitems.jsx b/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarSubitems.jsx
index 755b34c..ba0cd5f 100644
--- a/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarSubitems.jsx
+++ b/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarSubitems.jsx
@@ -34,7 +34,10 @@ const SidebarSubitems = ({ subitem, dispatch }) => {
{subitem.badges.map((badge, i) => (
diff --git a/src/core/utils/pageMenu.js b/src/core/utils/pageMenu.js
index 2ce4083..a4e1d31 100644
--- a/src/core/utils/pageMenu.js
+++ b/src/core/utils/pageMenu.js
@@ -301,6 +301,10 @@ export const pageMenu = [
type: "menu",
icon: ,
hasSubitems: true,
+ badges: [
+ { key: "safetyAndPrivacy.step_one", color: "warning" },
+ { key: "safetyAndPrivacy.step_two", color: "error" },
+ ],
Subitems: [
{
id: "safetyAndPrivacyManagmentOparationCartable",
@@ -319,7 +323,7 @@ export const pageMenu = [
id: "safetyAndPrivacyManagmentMap",
label: "پراکندگی بر روی نقشه",
type: "page",
- route: process.env.NEXT_PUBLIC_API_URL + "/v2/map?type=safety_and_privacy",
+ route: "/dashboard/road-safety/reports/map",
icon: ,
permissions: [
"show-safety-and-privacy-operator-cartable",
@@ -331,7 +335,7 @@ export const pageMenu = [
id: "safetyAndPrivacyManagmentReport",
label: "گزارش ها",
type: "page",
- route: "/dashboard/road-safety/report",
+ route: "/dashboard/road-safety/reports",
icon: ,
permissions: [
"show-safety-and-privacy-operator-cartable",
@@ -355,7 +359,7 @@ export const pageMenu = [
type: "menu",
icon: ,
hasSubitems: true,
- badges: [{ key: "roadObserved.supervise_cnt" }, { key: "roadObserved.complaint_cnt" }],
+ badges: [{ key: "roadObserved.supervise_cnt" }, { key: "roadObserved.complaint_cnt", color: "info" }],
Subitems: [
{
id: "roadObservationsManagmentSupervisorCartable",
@@ -372,7 +376,7 @@ export const pageMenu = [
type: "menu",
icon: ,
hasSubitems: true,
- badges: [{ key: "roadObserved.operation_cnt" }, { key: "roadObserved.complaint_cnt" }],
+ badges: [{ key: "roadObserved.operation_cnt" }, { key: "roadObserved.complaint_cnt", color: "info" }],
Subitems: [
{
id: "roadObservationsManagmentOparationCartable",
diff --git a/src/core/utils/routes.js b/src/core/utils/routes.js
index 4953100..b91186b 100644
--- a/src/core/utils/routes.js
+++ b/src/core/utils/routes.js
@@ -140,6 +140,8 @@ export const UPDATE_SAFETY_AND_PRIVACY = api + "/api/v3/safety_and_privacy";
export const EXPORT_OPERATOR_ROAD_SAFETY = api + "/api/v3/safety_and_privacy/excel_report";
export const GET_ROAD_SAFETY_PROVINCE_ACTIVITY_REPORT = api + "/api/v3/safety_and_privacy_report/country_activity";
export const GET_ROAD_SAFETY_CITY_ACTIVITY_REPORT = api + "/api/v3/safety_and_privacy_report/province_activity";
+export const GET_ROAD_SAFETY_REPORT_MAP = api + "/api/v3/safety_and_privacy/map";
+export const GET_ROAD_SAFETY_DETAILS = api + "/api/v3/safety_and_privacy";
// permission table
export const GET_PERMISSION_TABLE_LIST = api + "/api/v3/permissions";