diff --git a/src/app/(withAuth)/dashboard/road-items/reports/items-report/page.js b/src/app/(withAuth)/dashboard/road-items/reports/items-report/page.js
new file mode 100644
index 0000000..ab991b0
--- /dev/null
+++ b/src/app/(withAuth)/dashboard/road-items/reports/items-report/page.js
@@ -0,0 +1,18 @@
+import WithPermission from "@/core/middlewares/withPermission";
+import ReportPage from "@/components/dashboard/roadItems/reports/ItemsReports";
+
+const Page = () => {
+ return (
+
+
+
+ );
+};
+
+export default Page;
diff --git a/src/app/(withAuth)/dashboard/road-items/reports/sub-items-report/page.js b/src/app/(withAuth)/dashboard/road-items/reports/sub-items-report/page.js
new file mode 100644
index 0000000..d605501
--- /dev/null
+++ b/src/app/(withAuth)/dashboard/road-items/reports/sub-items-report/page.js
@@ -0,0 +1,17 @@
+import WithPermission from "@/core/middlewares/withPermission";
+import SubItemsReports from "@/components/dashboard/roadItems/reports/SubItemsReports";
+const Page = () => {
+ return (
+
+
+
+ );
+};
+
+export default Page;
diff --git a/src/app/(withAuth)/dashboard/road-patrols/reports/page.js b/src/app/(withAuth)/dashboard/road-patrols/reports/page.js
new file mode 100644
index 0000000..5f6cfcf
--- /dev/null
+++ b/src/app/(withAuth)/dashboard/road-patrols/reports/page.js
@@ -0,0 +1,18 @@
+import WithPermission from "@/core/middlewares/withPermission";
+import ReportPage from "@/components/dashboard/roadPatrols/reports";
+
+const Page = () => {
+ return (
+
+
+
+ );
+};
+
+export default Page;
diff --git a/src/app/(withAuth)/dashboard/road-patrols/supervisor/page.js b/src/app/(withAuth)/dashboard/road-patrols/supervisor/page.js
index 4093c15..1ef92e4 100644
--- a/src/app/(withAuth)/dashboard/road-patrols/supervisor/page.js
+++ b/src/app/(withAuth)/dashboard/road-patrols/supervisor/page.js
@@ -3,7 +3,9 @@ import SupervisorPage from "@/components/dashboard/roadPatrols/supervisor";
import ActivityCodeLog from "@/core/components/ActivityCodeLog";
const Page = () => {
return (
-
+
diff --git a/src/components/dashboard/roadItems/operator/Actions/Create/Forms/CreateFormContent.jsx b/src/components/dashboard/roadItems/operator/Actions/Create/Forms/CreateFormContent.jsx
index cf29fec..7b9b9a5 100644
--- a/src/components/dashboard/roadItems/operator/Actions/Create/Forms/CreateFormContent.jsx
+++ b/src/components/dashboard/roadItems/operator/Actions/Create/Forms/CreateFormContent.jsx
@@ -14,6 +14,7 @@ import BeenhereIcon from "@mui/icons-material/Beenhere";
import GetItemsForm from "@/components/dashboard/roadItems/operator/Actions/Create/Forms/GetItemsForm";
import GetSubItemsForm from "@/components/dashboard/roadItems/operator/Actions/Create/Forms/GetSubItemsForm";
import GetItemInfo from "@/components/dashboard/roadItems/operator/Actions/Create/Forms/GetItemInfo";
+import { format } from "date-fns";
function TabPanel(props) {
const { children, value, index } = props;
@@ -28,7 +29,7 @@ const validationSchema = object({
item_id: number().required("نوع آیتم را مشخص کنید!"),
sub_item_id: number().required("موضوع مشاهده شده را مشخص کنید!"),
amount: string().required("وارد کردن مقدار الزامیست!"),
- cmms_machines: array().required("وارد کردن کد خودرو الزامیست!"),
+ cmms_machines: array().required("وارد کردن کد خودرو الزامیست!").min(1, "حداقل یک کد خودرو باید وارد شود!"),
rahdaran_id: array().required("وارد کردن کد راهداران الزامیست!").min(1, "حداقل یک کد راهدار باید وارد شود!"), // بررسی حداقل یک آیتم,
activity_time: string().test("activity-time-conditional", "لطفا زمان فعالیت را انتخاب کنید!", function (value) {
const { is_gasht } = this.options.context; // دسترسی به context
@@ -184,6 +185,8 @@ const CreateFormContent = ({ setOpen, onSubmit, is_gasht = false }) => {
});
delete result.cmms_machines;
+ result[`activity_time`] = format(new Date(result.activity_time), "HH:mm");
+
await onSubmit({
result,
data: {
@@ -194,7 +197,6 @@ const CreateFormContent = ({ setOpen, onSubmit, is_gasht = false }) => {
},
});
};
- console.log(errors);
return (
diff --git a/src/components/dashboard/roadItems/operator/Actions/Create/Forms/GetItemInfo.jsx b/src/components/dashboard/roadItems/operator/Actions/Create/Forms/GetItemInfo.jsx
index a802b89..a80f4af 100644
--- a/src/components/dashboard/roadItems/operator/Actions/Create/Forms/GetItemInfo.jsx
+++ b/src/components/dashboard/roadItems/operator/Actions/Create/Forms/GetItemInfo.jsx
@@ -12,7 +12,7 @@ import NumberField from "@/core/components/NumberField";
const GetItemInfo = ({ register, itemsList, subItemsList, control, setValue, errors, watch, getValues, is_gasht }) => {
return (
-
+
@@ -25,6 +25,7 @@ const GetItemInfo = ({ register, itemsList, subItemsList, control, setValue, err
type="text"
size={"small"}
unit={subItemsList.unit}
+ placeholder={`مقدار را وارد کنید`}
inputProps={{
inputMode: "number",
min: 0,
@@ -86,7 +87,8 @@ const GetItemInfo = ({ register, itemsList, subItemsList, control, setValue, err
name="activity_date"
error={errors.activity_date ? errors.activity_date.message : null}
value={watch("activity_date")}
- placeholder={"تاریخ شروع فعالیت"}
+ placeholder={"تاریخ فعالیت را وارد کنید"}
+ label={"تاریخ فعالیت"}
setFieldValue={setValue}
helperText={errors.activity_date ? errors.activity_date.message : null}
/>
@@ -96,7 +98,8 @@ const GetItemInfo = ({ register, itemsList, subItemsList, control, setValue, err
value={watch("activity_time")}
name="activity_time"
error={errors.activity_time ? errors.activity_time.message : null}
- placeholder={"زمان فعالیت"}
+ placeholder={"زمان فعالیت را وارد کنید"}
+ label={"زمان فعالیت"}
setFieldValue={setValue}
helperText={errors.activity_time ? errors.activity_time.message : null}
/>
diff --git a/src/components/dashboard/roadItems/operator/Actions/Create/Forms/GetSubItemsForm.jsx b/src/components/dashboard/roadItems/operator/Actions/Create/Forms/GetSubItemsForm.jsx
index 2a60079..8d9098a 100644
--- a/src/components/dashboard/roadItems/operator/Actions/Create/Forms/GetSubItemsForm.jsx
+++ b/src/components/dashboard/roadItems/operator/Actions/Create/Forms/GetSubItemsForm.jsx
@@ -16,7 +16,7 @@ const GetSubItemsForm = ({ setValue, watch, setSubItemsList, tabState, setTabSta
) : (
{subItemsList.map((item) => (
-
+
{item.name}
diff --git a/src/components/dashboard/roadItems/operator/Actions/Create/Forms/ImageUpload.jsx b/src/components/dashboard/roadItems/operator/Actions/Create/Forms/ImageUpload.jsx
index a545b4d..17a9904 100644
--- a/src/components/dashboard/roadItems/operator/Actions/Create/Forms/ImageUpload.jsx
+++ b/src/components/dashboard/roadItems/operator/Actions/Create/Forms/ImageUpload.jsx
@@ -84,7 +84,20 @@ const ImageUpload = ({ control, setValue, errors, getValues, beforeImage = null,
justifyContent: "center",
}}
>
-
+
عکس قبل از اقدام
-
+
عکس بعد از اقدام
{
+ const [tabState, setTabState] = useState(0);
return (
-
diff --git a/src/components/dashboard/roadItems/operator/OperatorList.jsx b/src/components/dashboard/roadItems/operator/OperatorList.jsx
index 9f818e8..5fcc7e4 100644
--- a/src/components/dashboard/roadItems/operator/OperatorList.jsx
+++ b/src/components/dashboard/roadItems/operator/OperatorList.jsx
@@ -6,7 +6,7 @@ import useRoadItemGetSubItems from "@/lib/hooks/useRoadItemGetISubtems";
import useRoadItemGetItems from "@/lib/hooks/useRoadItemGetItems";
import { Box, Stack, Typography } from "@mui/material";
import moment from "jalali-moment";
-import { useMemo } from "react";
+import { useEffect, useMemo, useState } from "react";
import RowActions from "./RowActions";
import ImageDialog from "./RowActions/ImageForm";
import LocationForm from "./RowActions/LocationForm";
@@ -35,9 +35,9 @@ const OperatorList = () => {
size: 100,
},
{
- accessorKey: "item_fa",
+ accessorKey: "item",
header: "آیتم فعالیت",
- id: "item_fa",
+ id: "item",
enableColumnFilter: true,
datatype: "numeric",
filterMode: "equals",
@@ -46,7 +46,7 @@ const OperatorList = () => {
ColumnSelectComponent: (props) => {
const { itemsList, loadingItemsList, errorItemsList } = useRoadItemGetItems();
- const getColumnSelectOptions = () => {
+ const getColumnSelectOptions = useMemo(() => {
if (loadingItemsList) {
return [{ value: "loading", label: "در حال بارگذاری..." }];
}
@@ -60,27 +60,35 @@ const OperatorList = () => {
label: item.name,
})),
];
- };
+ }, [itemsList, loadingItemsList, errorItemsList]);
- const columnSelectOption = getColumnSelectOptions();
-
- return ;
+ return (
+
+ );
+ },
+ Cell: ({ row }) => {
+ return row.original.item_fa;
},
},
{
- accessorKey: "sub_item_fa",
+ accessorKey: "sub_item",
header: "موضوع مشاهده شده",
- id: "sub_item_fa",
+ id: "sub_item",
enableColumnFilter: true,
datatype: "numeric",
filterMode: "equals",
- dependencyId: "item_fa",
+ dependencyId: "item",
ColumnSelectComponent: (props) => {
const { subItemsList, loadingSubItemsList, errorSubItemsList } = useRoadItemGetSubItems(
props.dependencyFieldValue.value
);
+ const [prevDependency, setPrevDependency] = useState(props.dependencyFieldValue.value);
- const getColumnSelectOptions = () => {
+ const getColumnSelectOptions = useMemo(() => {
if (props.dependencyFieldValue.value === "") {
return [{ value: "empty", label: "ابتدا آیتم فعالیت را انتخاب کنید" }];
}
@@ -93,15 +101,33 @@ const OperatorList = () => {
return [
{ value: "", label: props.column.header },
...subItemsList.map((item) => ({
- value: item.id,
+ value: item.sub_item,
label: item.name,
})),
];
- };
+ }, [subItemsList, loadingSubItemsList, errorSubItemsList]);
- const columnSelectOption = getColumnSelectOptions();
-
- return ;
+ useEffect(() => {
+ if (prevDependency === props.dependencyFieldValue.value) return;
+ props.handleChange({ ...props.filterParameters, value: "" });
+ setPrevDependency(props.dependencyFieldValue.value);
+ }, [props.dependencyFieldValue.value]);
+ return (
+
+ );
+ },
+ Cell: ({ row }) => {
+ return row.original.sub_item_fa;
},
},
{
@@ -109,6 +135,7 @@ const OperatorList = () => {
header: "مقدار", // Value
id: "value",
enableColumnFilter: false,
+ enableSorting: false,
datatype: "text",
filterMode: "equals",
columnFilterModeOptions: ["equals", "contains"],
@@ -225,10 +252,12 @@ const OperatorList = () => {
{
accessorKey: "rahdaran",
header: "راهداران",
- id: "rahdaran",
- enableColumnFilter: false,
+ id: "rahdaran__code",
+ enableColumnFilter: true,
enableSorting: false,
- datatype: "array",
+ datatype: "text",
+ filterMode: "contains",
+ columnFilterModeOptions: ["equals", "contains"],
grow: false,
size: 100,
muiTableBodyCellProps: {
@@ -254,8 +283,7 @@ const OperatorList = () => {
id: "activity_date_time",
enableColumnFilter: true,
datatype: "date",
- filterMode: "equals",
- columnFilterModeOptions: ["equals", "contains"],
+ filterMode: "between",
grow: false,
size: 100,
},
@@ -265,8 +293,7 @@ const OperatorList = () => {
id: "created_at",
enableColumnFilter: true,
datatype: "date",
- filterMode: "equals",
- columnFilterModeOptions: ["equals", "contains"],
+ filterMode: "between",
grow: false,
size: 100,
},
diff --git a/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormCreate.jsx b/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormCreate.jsx
index f4d3280..c0266ad 100644
--- a/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormCreate.jsx
+++ b/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormCreate.jsx
@@ -13,7 +13,7 @@ import { array, mixed, object, string } from "yup";
const validationSchema = object({
amount: string().required("وارد کردن مقدار الزامیست!"),
- cmms_machines: array().required("وارد کردن کد خودرو الزامیست!"),
+ cmms_machines: array().required("وارد کردن کد خودرو الزامیست!").min(1, "حداقل یک کد خودرو باید وارد شود!"),
rahdaran_id: array().required("وارد کردن کد راهداران الزامیست!").min(1, "حداقل یک کد راهدار باید وارد شود!"),
before_image: mixed()
.nullable()
diff --git a/src/components/dashboard/roadItems/operator/Toolbar.jsx b/src/components/dashboard/roadItems/operator/Toolbar.jsx
index d8c6fad..4990a23 100644
--- a/src/components/dashboard/roadItems/operator/Toolbar.jsx
+++ b/src/components/dashboard/roadItems/operator/Toolbar.jsx
@@ -6,7 +6,7 @@ import ObservedGashtCreate from "./Actions/ObservedGashtCreate";
const Toolbar = ({ table, filterData, mutate }) => {
return (
-
+ {/**/}
diff --git a/src/components/dashboard/roadItems/reports/ExcelPrint/index.jsx b/src/components/dashboard/roadItems/reports/ExcelPrint/index.jsx
new file mode 100644
index 0000000..eb86d27
--- /dev/null
+++ b/src/components/dashboard/roadItems/reports/ExcelPrint/index.jsx
@@ -0,0 +1,70 @@
+"use client";
+import { Button, CircularProgress, IconButton, useMediaQuery } from "@mui/material";
+import { useMemo, useState } from "react";
+import moment from "jalali-moment";
+import FileSaver from "file-saver";
+import DescriptionIcon from "@mui/icons-material/Description";
+import useRequest from "@/lib/hooks/useRequest";
+import { EXPORT_ROAD_ITEMS_OPERATOR_LIST } from "@/core/utils/routes";
+import { useTheme } from "@emotion/react";
+
+const PrintExcel = ({ table, filterData }) => {
+ const theme = useTheme();
+ const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
+ const [loading, setLoading] = useState(false);
+ const requestServer = useRequest({ notificationSuccess: true });
+ const activeFilters = Object.entries(filterData).reduce((acc, [key, filter]) => {
+ if (filter.value) {
+ // Check if there's an active filter
+ acc.push({ id: key, value: filter.value });
+ }
+ return acc;
+ }, []);
+
+ const filterParams = useMemo(() => {
+ const params = new URLSearchParams();
+ activeFilters.length > 0 &&
+ activeFilters.map((filter, index) => {
+ params.set(`${filter.id}`, filter.value);
+ });
+ return params;
+ }, [activeFilters]);
+
+ const clickHandler = () => {
+ setLoading(true);
+ requestServer(`${EXPORT_ROAD_ITEMS_OPERATOR_LIST}?${filterParams}`, "get", {
+ requestOptions: { responseType: "blob" },
+ })
+ .then((response) => {
+ const filename = `خروجی کارتابل گزارشات فعالیت روزانه تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`;
+ FileSaver.saveAs(response.data, filename);
+ })
+ .catch(() => {})
+ .finally(() => {
+ setLoading(false);
+ });
+ };
+
+ return (
+ <>
+ {isMobile ? (
+
+
+
+ ) : (
+ : }
+ onClick={clickHandler}
+ >
+ خروجی اکسل
+
+ )}
+ >
+ );
+};
+export default PrintExcel;
diff --git a/src/components/dashboard/roadItems/reports/ItemsReports/ReportLists.jsx b/src/components/dashboard/roadItems/reports/ItemsReports/ReportLists.jsx
new file mode 100644
index 0000000..dcd9c1f
--- /dev/null
+++ b/src/components/dashboard/roadItems/reports/ItemsReports/ReportLists.jsx
@@ -0,0 +1,92 @@
+"use client";
+import DataTableWithAuth from "@/core/components/DataTableWithAuth";
+import { Box } from "@mui/material";
+import { useMemo } from "react";
+
+const ReportLists = ({ itemsList, data }) => {
+ const columns = useMemo(() => {
+ const dynamicColumns =
+ itemsList?.map((item) => ({
+ accessorKey: `item_${item.id}`,
+ header: `${item.name}`,
+ id: `item_${item.id}`,
+ enableColumnFilter: false,
+ enableSorting: false,
+ datatype: "text",
+ grow: false,
+ muiTableBodyCellProps: {
+ sx: {
+ textAlign: "center",
+ borderLeft: "1px solid #e1e1e1",
+ py: 0,
+ "&:first-of-type": {
+ borderLeft: "unset",
+ },
+ },
+ },
+ size: 50,
+ Cell: ({ renderedCellValue }) => {
+ return (renderedCellValue / 1).toLocaleString();
+ },
+ })) || [];
+
+ return [
+ {
+ accessorKey: "edare_name",
+ header: "اداره",
+ id: "edare_name",
+ enableColumnFilter: false,
+ enableSorting: false,
+ datatype: "text",
+ grow: false,
+ size: 50,
+ },
+ {
+ accessorKey: "sum",
+ header: "مجموع",
+ id: "sum",
+ enableColumnFilter: false,
+ enableSorting: false,
+ datatype: "text",
+ muiTableBodyCellProps: {
+ sx: {
+ textAlign: "center",
+ borderLeft: "1px solid #e1e1e1",
+ py: 0,
+ "&:first-of-type": {
+ borderLeft: "unset",
+ },
+ },
+ },
+ grow: false,
+ size: 50,
+ Cell: ({ renderedCellValue }) => {
+ return (renderedCellValue / 1).toLocaleString();
+ },
+ },
+ {
+ header: "ایتم های فعالیت روزانه",
+ id: "items",
+ enableColumnFilter: false,
+ enableSorting: false,
+ datatype: "text",
+ grow: false,
+ size: 50,
+ columns: [...dynamicColumns],
+ },
+ ];
+ }, [itemsList]);
+
+ return (
+
+
+
+ );
+};
+
+export default ReportLists;
diff --git a/src/components/dashboard/roadItems/reports/ItemsReports/Search/FromDateController.jsx b/src/components/dashboard/roadItems/reports/ItemsReports/Search/FromDateController.jsx
new file mode 100644
index 0000000..2cfa8af
--- /dev/null
+++ b/src/components/dashboard/roadItems/reports/ItemsReports/Search/FromDateController.jsx
@@ -0,0 +1,27 @@
+import { Controller } from "react-hook-form";
+import MuiDatePicker from "@/core/components/MuiDatePicker";
+import React from "react";
+import moment from "jalali-moment";
+
+const FromDateController = ({ control }) => {
+ return (
+ (
+ {
+ const formattedDate = moment(new Date(newValue)).locale("en").format("YYYY-MM-DD");
+ onChange(formattedDate); // Update the field value in react-hook-form
+ }}
+ helperText={error ? error.message : null}
+ />
+ )}
+ />
+ );
+};
+export default FromDateController;
diff --git a/src/components/dashboard/roadItems/reports/ItemsReports/Search/SearchReportField.jsx b/src/components/dashboard/roadItems/reports/ItemsReports/Search/SearchReportField.jsx
new file mode 100644
index 0000000..9cce1c1
--- /dev/null
+++ b/src/components/dashboard/roadItems/reports/ItemsReports/Search/SearchReportField.jsx
@@ -0,0 +1,45 @@
+import { Button, Grid } from "@mui/material";
+import SearchIcon from "@mui/icons-material/Search";
+import React from "react";
+import FromDateController from "./FromDateController";
+import ToDateController from "./ToDateController";
+import SelectProvince from "./SelectProvince";
+import { Controller } from "react-hook-form";
+
+const SearchReportField = ({ control, hasProvincesPermission }) => {
+ return (
+
+
+
+
+
+
+
+ {hasProvincesPermission && (
+
+
+
+ )}
+
+ (
+ }
+ fullWidth
+ >
+ {isSubmitting ? "درحال دریافت اطلاعات" : "جستجو"}
+
+ )}
+ />
+
+
+ );
+};
+
+export default SearchReportField;
diff --git a/src/components/dashboard/roadItems/reports/ItemsReports/Search/SelectProvince.jsx b/src/components/dashboard/roadItems/reports/ItemsReports/Search/SelectProvince.jsx
new file mode 100644
index 0000000..b1d8a39
--- /dev/null
+++ b/src/components/dashboard/roadItems/reports/ItemsReports/Search/SelectProvince.jsx
@@ -0,0 +1,47 @@
+import { Controller } from "react-hook-form";
+import MuiDatePicker from "@/core/components/MuiDatePicker";
+import React from "react";
+import { FormControl, FormHelperText, InputLabel, LinearProgress, MenuItem, Select, Typography } from "@mui/material";
+import useProvinces from "@/lib/hooks/useProvince";
+
+const SelectProvince = ({ control }) => {
+ const { provinces, loadingProvinces, errorProvinces } = useProvinces();
+ return (
+ (
+
+ استان
+
+ {error && {error.message}}
+
+ )}
+ />
+ );
+};
+export default SelectProvince;
diff --git a/src/components/dashboard/roadItems/reports/ItemsReports/Search/ToDateController.jsx b/src/components/dashboard/roadItems/reports/ItemsReports/Search/ToDateController.jsx
new file mode 100644
index 0000000..003ac20
--- /dev/null
+++ b/src/components/dashboard/roadItems/reports/ItemsReports/Search/ToDateController.jsx
@@ -0,0 +1,29 @@
+import { Controller, useWatch } from "react-hook-form";
+import MuiDatePicker from "@/core/components/MuiDatePicker";
+import React from "react";
+import moment from "jalali-moment";
+
+const ToDateController = ({ control }) => {
+ const minDate = useWatch({ control, name: "from_date" });
+ return (
+ (
+ {
+ const formattedDate = moment(new Date(newValue)).locale("en").format("YYYY-MM-DD");
+ onChange(formattedDate); // Update the field value in react-hook-form
+ }}
+ helperText={error ? error.message : null}
+ />
+ )}
+ />
+ );
+};
+export default ToDateController;
diff --git a/src/components/dashboard/roadItems/reports/ItemsReports/Search/index.jsx b/src/components/dashboard/roadItems/reports/ItemsReports/Search/index.jsx
new file mode 100644
index 0000000..f29d302
--- /dev/null
+++ b/src/components/dashboard/roadItems/reports/ItemsReports/Search/index.jsx
@@ -0,0 +1,13 @@
+import StyledForm from "@/core/components/StyledForm";
+import SearchReportField from "./SearchReportField";
+
+const SearchReportList = ({ handleSubmit, onSearchSubmit, control, hasProvincesPermission }) => {
+ return (
+ <>
+
+
+
+ >
+ );
+};
+export default SearchReportList;
diff --git a/src/components/dashboard/roadItems/reports/ItemsReports/index.jsx b/src/components/dashboard/roadItems/reports/ItemsReports/index.jsx
new file mode 100644
index 0000000..137ed83
--- /dev/null
+++ b/src/components/dashboard/roadItems/reports/ItemsReports/index.jsx
@@ -0,0 +1,166 @@
+"use client";
+import PageTitle from "@/core/components/PageTitle";
+import { LinearProgress, Stack, Typography } from "@mui/material";
+import SearchReportList from "./Search";
+import { useEffect, useState } from "react";
+import ReportLists from "./ReportLists";
+import useRequest from "@/lib/hooks/useRequest";
+import { GET_CITY_ACTIVITY_PER_ITEM, GET_PROVINCE_ACTIVITY_PER_ITEM } from "@/core/utils/routes";
+import useRoadItemGetItems from "@/lib/hooks/useRoadItemGetItems";
+import moment from "jalali-moment";
+import * as yup from "yup";
+import { useForm } from "react-hook-form";
+import { yupResolver } from "@hookform/resolvers/yup";
+import { usePermissions } from "@/lib/hooks/usePermissions";
+import { useAuth } from "@/lib/contexts/auth";
+
+const ReportPage = () => {
+ const [data, setData] = useState(null);
+ const { itemsList, loadingItemsList, errorItemsList } = useRoadItemGetItems();
+ const { data: userPermissions } = usePermissions();
+ const { user } = useAuth();
+ const requestServer = useRequest();
+ const hasProvincesPermission = userPermissions.includes("show-road-item-supervise-cartable");
+
+ const defaultValues = {
+ from_date: moment(new Date()).format("YYYY-MM-DD"),
+ date_to: moment(new Date()).format("YYYY-MM-DD"),
+ province_id: hasProvincesPermission ? "-1" : user.province_id,
+ };
+
+ const onSearchSubmit = async (data) => {
+ const params = new URLSearchParams();
+ params.set("from_date", `${data.from_date}`);
+ params.set("date_to", `${data.date_to}`);
+ if (data.province_id === "-1") {
+ try {
+ const response = await requestServer(`${GET_PROVINCE_ACTIVITY_PER_ITEM}?${params}`);
+ const result = response.data.data;
+ const nationalReport = {
+ edare_name: "کل کشور",
+ sum: result.activities.length
+ ? result.activities
+ .filter((report) => report.p === -1)
+ .reduce((acc, report) => acc + (report.s || 0), 0)
+ : 0,
+ };
+ itemsList.forEach((item) => {
+ const nationalReportForItem = result.activities.find(
+ (report) => report.p === -1 && report.i === item.id
+ );
+ nationalReport[`item_${item.id}`] = nationalReportForItem ? nationalReportForItem.s : 0;
+ });
+
+ setData({
+ data: [
+ nationalReport,
+ ...result.provinces.map((province) => {
+ const filteredReports = result.activities.filter((report) => report.p === province.id);
+ const sum = filteredReports.reduce((acc, report) => acc + (report.s || 0), 0);
+ const rowData = {
+ edare_name: province.name_fa,
+ sum,
+ };
+ itemsList.forEach((item) => {
+ const reportForItem = filteredReports.find((report) => report.i === item.id);
+ rowData[`item_${item.id}`] = reportForItem ? reportForItem.s : 0;
+ });
+ return rowData;
+ }),
+ ],
+ filters: data,
+ });
+ } catch (e) {}
+ } else {
+ try {
+ params.set("province_id", `${data.province_id}`);
+ const response = await requestServer(`${GET_CITY_ACTIVITY_PER_ITEM}?${params}`);
+ const result = response.data.data;
+ const nationalReport = {
+ edare_name: "کل استان",
+ sum: result.activities.length
+ ? result.activities
+ .filter((report) => report.c === -1)
+ .reduce((acc, report) => acc + (report.s || 0), 0)
+ : 0,
+ };
+
+ itemsList.forEach((item) => {
+ const nationalReportForItem = result.activities.find(
+ (report) => report.c === -1 && report.i === item.id
+ );
+ nationalReport[`item_${item.id}`] = nationalReportForItem ? nationalReportForItem.s : 0;
+ });
+
+ setData({
+ data: [
+ nationalReport,
+ ...result.edarateShahri.map((edare) => {
+ const filteredReports = result.activities.filter((report) => report.c === edare.id);
+ const sum = filteredReports.reduce((acc, report) => acc + (report.s || 0), 0);
+
+ const rowData = {
+ edare_name: edare.name_fa,
+ sum,
+ };
+
+ itemsList.forEach((item) => {
+ const reportForItem = filteredReports.find((report) => report.i === item.id);
+ rowData[`item_${item.id}`] = reportForItem ? reportForItem.s : 0;
+ });
+
+ return rowData;
+ }),
+ ],
+ filters: data,
+ });
+ } catch (e) {}
+ }
+ };
+
+ useEffect(() => {
+ if (itemsList.length === 0) return;
+ onSearchSubmit(defaultValues);
+ }, [itemsList]);
+
+ const validationSchema = yup.object().shape({
+ from_date: yup
+ .string()
+ .required("تاریخ شروع الزامی است!")
+ .matches(/^\d{4}-\d{2}-\d{2}$/, "تاریخ شروع الزامی است!")
+ .test("is-valid-date", "تاریخ شروع معتبر نیست!", (value) => moment(value, "YYYY-MM-DD", true).isValid()),
+ date_to: yup
+ .string()
+ .required("تاریخ پایان الزامی است!")
+ .matches(/^\d{4}-\d{2}-\d{2}$/, "تاریخ پایان الزامی است!")
+ .test("is-valid-date", "تاریخ پایان معتبر نیست!", (value) => moment(value, "YYYY-MM-DD", true).isValid()),
+ province_id: yup.string().nullable(),
+ });
+
+ const { control, handleSubmit } = useForm({
+ defaultValues,
+ resolver: yupResolver(validationSchema),
+ mode: "onBlur",
+ });
+ return (
+
+
+
+ {!data || loadingItemsList ? (
+
+ ) : errorItemsList ? (
+
+ خطا در دریافت اطلاعات!!!
+
+ ) : (
+
+ )}
+
+ );
+};
+export default ReportPage;
diff --git a/src/components/dashboard/roadItems/reports/SubItemsReports/Search/FromDateController.jsx b/src/components/dashboard/roadItems/reports/SubItemsReports/Search/FromDateController.jsx
new file mode 100644
index 0000000..2cfa8af
--- /dev/null
+++ b/src/components/dashboard/roadItems/reports/SubItemsReports/Search/FromDateController.jsx
@@ -0,0 +1,27 @@
+import { Controller } from "react-hook-form";
+import MuiDatePicker from "@/core/components/MuiDatePicker";
+import React from "react";
+import moment from "jalali-moment";
+
+const FromDateController = ({ control }) => {
+ return (
+ (
+ {
+ const formattedDate = moment(new Date(newValue)).locale("en").format("YYYY-MM-DD");
+ onChange(formattedDate); // Update the field value in react-hook-form
+ }}
+ helperText={error ? error.message : null}
+ />
+ )}
+ />
+ );
+};
+export default FromDateController;
diff --git a/src/components/dashboard/roadItems/reports/SubItemsReports/Search/SearchReportField.jsx b/src/components/dashboard/roadItems/reports/SubItemsReports/Search/SearchReportField.jsx
new file mode 100644
index 0000000..5487b7f
--- /dev/null
+++ b/src/components/dashboard/roadItems/reports/SubItemsReports/Search/SearchReportField.jsx
@@ -0,0 +1,48 @@
+import { Button, Grid } from "@mui/material";
+import SearchIcon from "@mui/icons-material/Search";
+import React from "react";
+import FromDateController from "./FromDateController";
+import ToDateController from "./ToDateController";
+import SelectProvince from "./SelectProvince";
+import { Controller } from "react-hook-form";
+import SelectItems from "./SelectItems";
+
+const SearchReportField = ({ control, hasProvincesPermission }) => {
+ return (
+
+
+
+
+
+
+
+ {hasProvincesPermission && (
+
+
+
+ )}
+
+
+
+
+ (
+ }
+ fullWidth
+ >
+ {isSubmitting ? "درحال دریافت اطلاعات" : "جستجو"}
+
+ )}
+ />
+
+
+ );
+};
+export default SearchReportField;
diff --git a/src/components/dashboard/roadItems/reports/SubItemsReports/Search/SelectItems.jsx b/src/components/dashboard/roadItems/reports/SubItemsReports/Search/SelectItems.jsx
new file mode 100644
index 0000000..57bcc86
--- /dev/null
+++ b/src/components/dashboard/roadItems/reports/SubItemsReports/Search/SelectItems.jsx
@@ -0,0 +1,42 @@
+import { Controller } from "react-hook-form";
+import MuiDatePicker from "@/core/components/MuiDatePicker";
+import React from "react";
+import { FormControl, FormHelperText, InputLabel, MenuItem, Select } from "@mui/material";
+import useRoadItemGetItems from "@/lib/hooks/useRoadItemGetItems";
+
+const SelectProvince = ({ control }) => {
+ const { itemsList, loadingItemsList, errorItemsList } = useRoadItemGetItems();
+ return (
+ (
+
+ ایتم
+
+ {error && {error.message}}
+
+ )}
+ />
+ );
+};
+export default SelectProvince;
diff --git a/src/components/dashboard/roadItems/reports/SubItemsReports/Search/SelectProvince.jsx b/src/components/dashboard/roadItems/reports/SubItemsReports/Search/SelectProvince.jsx
new file mode 100644
index 0000000..b1d8a39
--- /dev/null
+++ b/src/components/dashboard/roadItems/reports/SubItemsReports/Search/SelectProvince.jsx
@@ -0,0 +1,47 @@
+import { Controller } from "react-hook-form";
+import MuiDatePicker from "@/core/components/MuiDatePicker";
+import React from "react";
+import { FormControl, FormHelperText, InputLabel, LinearProgress, MenuItem, Select, Typography } from "@mui/material";
+import useProvinces from "@/lib/hooks/useProvince";
+
+const SelectProvince = ({ control }) => {
+ const { provinces, loadingProvinces, errorProvinces } = useProvinces();
+ return (
+ (
+
+ استان
+
+ {error && {error.message}}
+
+ )}
+ />
+ );
+};
+export default SelectProvince;
diff --git a/src/components/dashboard/roadItems/reports/SubItemsReports/Search/ToDateController.jsx b/src/components/dashboard/roadItems/reports/SubItemsReports/Search/ToDateController.jsx
new file mode 100644
index 0000000..003ac20
--- /dev/null
+++ b/src/components/dashboard/roadItems/reports/SubItemsReports/Search/ToDateController.jsx
@@ -0,0 +1,29 @@
+import { Controller, useWatch } from "react-hook-form";
+import MuiDatePicker from "@/core/components/MuiDatePicker";
+import React from "react";
+import moment from "jalali-moment";
+
+const ToDateController = ({ control }) => {
+ const minDate = useWatch({ control, name: "from_date" });
+ return (
+ (
+ {
+ const formattedDate = moment(new Date(newValue)).locale("en").format("YYYY-MM-DD");
+ onChange(formattedDate); // Update the field value in react-hook-form
+ }}
+ helperText={error ? error.message : null}
+ />
+ )}
+ />
+ );
+};
+export default ToDateController;
diff --git a/src/components/dashboard/roadItems/reports/SubItemsReports/Search/index.jsx b/src/components/dashboard/roadItems/reports/SubItemsReports/Search/index.jsx
new file mode 100644
index 0000000..0ca7a3f
--- /dev/null
+++ b/src/components/dashboard/roadItems/reports/SubItemsReports/Search/index.jsx
@@ -0,0 +1,12 @@
+import StyledForm from "@/core/components/StyledForm";
+import SearchReportField from "./SearchReportField";
+const SearchReportList = ({ handleSubmit, onSearchSubmit, control, hasProvincesPermission }) => {
+ return (
+ <>
+
+
+
+ >
+ );
+};
+export default SearchReportList;
diff --git a/src/components/dashboard/roadItems/reports/SubItemsReports/SubItemsList.jsx b/src/components/dashboard/roadItems/reports/SubItemsReports/SubItemsList.jsx
new file mode 100644
index 0000000..f047491
--- /dev/null
+++ b/src/components/dashboard/roadItems/reports/SubItemsReports/SubItemsList.jsx
@@ -0,0 +1,16 @@
+import DataTableWithAuth from "@/core/components/DataTableWithAuth";
+import { Box } from "@mui/material";
+
+const SubItemsList = ({ data }) => {
+ return (
+
+
+
+ );
+};
+export default SubItemsList;
diff --git a/src/components/dashboard/roadItems/reports/SubItemsReports/index.jsx b/src/components/dashboard/roadItems/reports/SubItemsReports/index.jsx
new file mode 100644
index 0000000..57521d7
--- /dev/null
+++ b/src/components/dashboard/roadItems/reports/SubItemsReports/index.jsx
@@ -0,0 +1,242 @@
+"use client";
+import SubItemsList from "./SubItemsList";
+import PageTitle from "@/core/components/PageTitle";
+import { LinearProgress, Stack } from "@mui/material";
+import SearchReportList from "./Search";
+import { useEffect, useState } from "react";
+import { usePermissions } from "@/lib/hooks/usePermissions";
+import { useAuth } from "@/lib/contexts/auth";
+import useRequest from "@/lib/hooks/useRequest";
+import moment from "jalali-moment";
+import { GET_CITY_ACTIVITY_PER_SUB_ITEM, GET_PROVINCE_ACTIVITY_PER_SUB_ITEM } from "@/core/utils/routes";
+import * as yup from "yup";
+import { useForm } from "react-hook-form";
+import { yupResolver } from "@hookform/resolvers/yup";
+
+const createColumns = (sub_items) => {
+ const dynamicColumns =
+ sub_items?.map((sub_item) => ({
+ accessorKey: `sub_item_${sub_item.sub_item}`,
+ header: `${sub_item.sub_item_str}`,
+ id: `sub_item_${sub_item.sub_item}`,
+ columns: [
+ {
+ accessorKey: `sub_item_${sub_item.sub_item}_count`,
+ header: "تعداد",
+ id: `sub_item_${sub_item.sub_item}_count`,
+ enableColumnFilter: false,
+ enableSorting: false,
+ datatype: "text",
+ grow: false,
+ muiTableBodyCellProps: {
+ sx: {
+ textAlign: "center",
+ borderLeft: "1px solid #e1e1e1",
+ py: 0,
+ "&:first-of-type": {
+ borderLeft: "unset",
+ },
+ },
+ },
+ size: 50,
+ Cell: ({ renderedCellValue }) => {
+ return (renderedCellValue / 1).toLocaleString();
+ },
+ },
+ {
+ accessorKey: `sub_item_${sub_item.sub_item}_sum`,
+ header: `مجموع (${sub_item.sub_item_unit})`,
+ id: `sub_item_${sub_item.sub_item}_sum`,
+ enableColumnFilter: false,
+ enableSorting: false,
+ datatype: "text",
+ muiTableBodyCellProps: {
+ sx: {
+ textAlign: "center",
+ borderLeft: "1px solid #e1e1e1",
+ py: 0,
+ "&:first-of-type": {
+ borderLeft: "unset",
+ },
+ },
+ },
+ grow: false,
+ size: 50,
+ Cell: ({ renderedCellValue }) => {
+ return (renderedCellValue / 1).toLocaleString();
+ },
+ },
+ ],
+ })) || [];
+
+ return [
+ {
+ accessorKey: "edare_name",
+ header: "اداره",
+ id: "edare_name",
+ enableColumnFilter: false,
+ enableSorting: false,
+ datatype: "text",
+ grow: false,
+ size: 50,
+ },
+ {
+ header: "موارد مشاهده شده فعالیت روزانه",
+ enableColumnFilter: false,
+ id: "subItems",
+ enableSorting: false,
+ datatype: "text",
+ grow: false,
+ size: 50,
+ columns: [...dynamicColumns],
+ },
+ ];
+};
+
+const SubItemsReports = () => {
+ const [data, setData] = useState(null);
+ const { data: userPermissions } = usePermissions();
+ const { user } = useAuth();
+ const requestServer = useRequest();
+ const hasProvincesPermission = userPermissions.includes("show-road-item-supervise-cartable");
+
+ const defaultValues = {
+ from_date: moment(new Date()).format("YYYY-MM-DD"),
+ date_to: moment(new Date()).format("YYYY-MM-DD"),
+ province_id: hasProvincesPermission ? "-1" : user.province_id,
+ item: 1,
+ };
+
+ const onSearchSubmit = async (data) => {
+ const params = new URLSearchParams();
+ params.set("from_date", `${data.from_date}`);
+ params.set("date_to", `${data.date_to}`);
+ params.set("item", `${data.item}`);
+ if (data.province_id === "-1") {
+ try {
+ const response = await requestServer(`${GET_PROVINCE_ACTIVITY_PER_SUB_ITEM}?${params}`);
+ const result = response.data.data;
+ const nationalReport = {
+ edare_name: "کل کشور",
+ };
+
+ result.sub_items.forEach((subItem) => {
+ const nationalReportForSubItem = result.activities.find(
+ (report) => report.p === -1 && report.t === subItem.sub_item
+ );
+ nationalReport[`sub_item_${subItem.sub_item}_count`] = nationalReportForSubItem
+ ? nationalReportForSubItem.c
+ : 0;
+ nationalReport[`sub_item_${subItem.sub_item}_sum`] = nationalReportForSubItem
+ ? nationalReportForSubItem.s
+ : 0;
+ });
+
+ setData({
+ data: [
+ nationalReport,
+ ...result.provinces.map((province) => {
+ const filteredReports = result.activities.filter((report) => report.p === province.id);
+ const rowData = {
+ edare_name: province.name_fa,
+ };
+
+ result.sub_items.forEach((subItem) => {
+ const reportForItem = filteredReports.find((report) => report.t === subItem.sub_item);
+ rowData[`sub_item_${subItem.sub_item}_count`] = reportForItem ? reportForItem.c : 0;
+ rowData[`sub_item_${subItem.sub_item}_sum`] = reportForItem ? reportForItem.s : 0;
+ });
+
+ return rowData;
+ }),
+ ],
+ columns: createColumns(result.sub_items),
+ filters: data,
+ });
+ } catch (e) {}
+ } else {
+ try {
+ params.set("province_id", `${data.province_id}`);
+ const response = await requestServer(`${GET_CITY_ACTIVITY_PER_SUB_ITEM}?${params}`);
+ const result = response.data.data;
+ const nationalReport = {
+ edare_name: "کل استان",
+ };
+
+ result.sub_items.forEach((subItem) => {
+ const nationalReportForSubItem = result.activities.find(
+ (report) => report.ci === -1 && report.t === subItem.sub_item
+ );
+ nationalReport[`sub_item_${subItem.sub_item}_count`] = nationalReportForSubItem
+ ? nationalReportForSubItem.c
+ : 0;
+ nationalReport[`sub_item_${subItem.sub_item}_sum`] = nationalReportForSubItem
+ ? nationalReportForSubItem.s
+ : 0;
+ });
+
+ setData({
+ data: [
+ nationalReport,
+ ...result.edarateShahri.map((edare) => {
+ const filteredReports = result.activities.filter((report) => report.ci === edare.id);
+ const rowData = {
+ edare_name: edare.name_fa,
+ };
+
+ result.sub_items.forEach((subItem) => {
+ const reportForItem = filteredReports.find((report) => report.t === subItem.sub_item);
+ rowData[`sub_item_${subItem.sub_item}_count`] = reportForItem ? reportForItem.c : 0;
+ rowData[`sub_item_${subItem.sub_item}_sum`] = reportForItem ? reportForItem.s : 0;
+ });
+
+ return rowData;
+ }),
+ ],
+ columns: createColumns(result.sub_items),
+ filters: data,
+ });
+ } catch (e) {
+ console.log(e);
+ }
+ }
+ };
+
+ useEffect(() => {
+ onSearchSubmit(defaultValues);
+ }, []);
+
+ const validationSchema = yup.object().shape({
+ from_date: yup
+ .string()
+ .required("تاریخ شروع الزامی است!")
+ .matches(/^\d{4}-\d{2}-\d{2}$/, "تاریخ شروع الزامی است!")
+ .test("is-valid-date", "تاریخ شروع معتبر نیست!", (value) => moment(value, "YYYY-MM-DD", true).isValid()),
+ date_to: yup
+ .string()
+ .required("تاریخ پایان الزامی است!")
+ .matches(/^\d{4}-\d{2}-\d{2}$/, "تاریخ پایان الزامی است!")
+ .test("is-valid-date", "تاریخ پایان معتبر نیست!", (value) => moment(value, "YYYY-MM-DD", true).isValid()),
+ province_id: yup.string().nullable(),
+ item: yup.number().required("ایتم مورد نظر را وارد کنید!!!"),
+ });
+
+ const { control, handleSubmit } = useForm({
+ defaultValues,
+ resolver: yupResolver(validationSchema),
+ mode: "onBlur",
+ });
+ return (
+
+
+
+ {!data ? : }
+
+ );
+};
+export default SubItemsReports;
diff --git a/src/components/dashboard/roadItems/supervisor/SupervisorList.jsx b/src/components/dashboard/roadItems/supervisor/SupervisorList.jsx
index 8ef88db..1dfae7c 100644
--- a/src/components/dashboard/roadItems/supervisor/SupervisorList.jsx
+++ b/src/components/dashboard/roadItems/supervisor/SupervisorList.jsx
@@ -1,4 +1,4 @@
-import { useMemo } from "react";
+import { useEffect, useMemo, useState } from "react";
import { Box, Stack, Typography } from "@mui/material";
import DataTableWithAuth from "@/core/components/DataTableWithAuth";
import Toolbar from "./Toolbar";
@@ -14,6 +14,8 @@ import useRoadItemGetItems from "@/lib/hooks/useRoadItemGetItems";
import useRoadItemGetSubItems from "@/lib/hooks/useRoadItemGetISubtems";
import useEdaratLists from "@/lib/hooks/useEdaratLists";
import MachinesCodeDialog from "./RowActions/MachinesCodeForm";
+import { usePermissions } from "@/lib/hooks/usePermissions";
+import { useAuth } from "@/lib/contexts/auth";
const SupervisorList = () => {
const statusOptions = [
@@ -21,8 +23,47 @@ const SupervisorList = () => {
{ value: 1, label: "تایید" },
{ value: 2, label: "عدم تایید" },
];
- const columns = useMemo(
- () => [
+ const { data: userPermissions } = usePermissions();
+ const hasCountryPermission = userPermissions.includes("show-road-item-supervise-cartable");
+ const { user } = useAuth();
+ const columns = useMemo(() => {
+ const dynamicColumns = {
+ accessorKey: "province_id",
+ header: "استان", // Province
+ id: "province_id",
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterMode: "equals",
+ grow: false,
+ size: 130,
+ ColumnSelectComponent: (props) => {
+ const { provinces, errorProvinces, loadingProvinces } = useProvinces();
+ const getColumnSelectOptions = useMemo(() => {
+ if (loadingProvinces) {
+ return [{ value: "loading", label: "در حال بارگذاری..." }];
+ }
+ if (errorProvinces) {
+ return [{ value: "error", label: "خطا در بارگذاری" }];
+ }
+ return [
+ { value: "", label: props.column.header },
+ ...provinces.map((province) => ({
+ value: province.id,
+ label: province.name_fa,
+ })),
+ ];
+ }, [provinces, errorProvinces, loadingProvinces]);
+ return (
+
+ );
+ },
+ Cell: ({ renderedCellValue, row }) => <>{row.original.province_fa}>,
+ };
+ return [
{
accessorKey: "id",
header: "کد یکتا", // Unique Code
@@ -35,37 +76,7 @@ const SupervisorList = () => {
grow: false,
size: 100,
},
- {
- accessorKey: "province_id",
- header: "استان", // Province
- id: "province_id",
- enableColumnFilter: true,
- datatype: "numeric",
- filterMode: "equals",
- grow: false,
- size: 130,
- ColumnSelectComponent: (props) => {
- const { provinces, errorProvinces, loadingProvinces } = useProvinces();
- const getColumnSelectOptions = () => {
- if (loadingProvinces) {
- return [{ value: "loading", label: "در حال بارگذاری..." }];
- }
- if (errorProvinces) {
- return [{ value: "error", label: "خطا در بارگذاری" }];
- }
- return [
- { value: "", label: props.column.header },
- ...provinces.map((province) => ({
- value: province.id,
- label: province.name_fa,
- })),
- ];
- };
- const columnSelectOption = getColumnSelectOptions();
- return ;
- },
- Cell: ({ renderedCellValue, row }) => <>{row.original.province_fa}>,
- },
+ ...(hasCountryPermission ? [dynamicColumns] : []),
{
accessorKey: "edarat_id",
header: "اداره", // Office
@@ -73,16 +84,19 @@ const SupervisorList = () => {
enableColumnFilter: true,
datatype: "numeric",
filterMode: "equals",
- dependencyId: "province_id",
+ dependencyId: hasCountryPermission ? "province_id" : null,
grow: false,
size: 120,
ColumnSelectComponent: (props) => {
const { edaratList, loadingEdaratList, errorEdaratList } = useEdaratLists(
- props.dependencyFieldValue.value
+ hasCountryPermission ? props.dependencyFieldValue.value : user.province_id
+ );
+ const [prevDependency, setPrevDependency] = useState(
+ hasCountryPermission ? props.dependencyFieldValue.value : user.province_id
);
- const getColumnSelectOptions = () => {
- if (props.dependencyFieldValue.value === "") {
+ const getColumnSelectOptions = useMemo(() => {
+ if (hasCountryPermission && props.dependencyFieldValue.value === "") {
return [{ value: "empty", label: "ابتدا استان را انتخاب کنید" }];
}
if (loadingEdaratList) {
@@ -98,16 +112,33 @@ const SupervisorList = () => {
label: edare.name_fa,
})),
];
- };
- const columnSelectOption = getColumnSelectOptions();
- return ;
+ }, [edaratList, loadingEdaratList, errorEdaratList]);
+ useEffect(() => {
+ if (hasCountryPermission) return;
+ if (prevDependency === props.dependencyFieldValue?.value) return;
+ props.handleChange({ ...props.filterParameters, value: "" });
+ setPrevDependency(props.dependencyFieldValue?.value);
+ }, [props.dependencyFieldValue?.value, hasCountryPermission]);
+ return (
+
+ );
},
Cell: ({ renderedCellValue, row }) => <>{row.original.edarat_name}>,
},
{
- accessorKey: "item_fa",
+ accessorKey: "item",
header: "آیتم فعالیت",
- id: "item_fa",
+ id: "item",
enableColumnFilter: true,
datatype: "numeric",
filterMode: "equals",
@@ -115,7 +146,8 @@ const SupervisorList = () => {
size: 100,
ColumnSelectComponent: (props) => {
const { itemsList, loadingItemsList, errorItemsList } = useRoadItemGetItems();
- const getColumnSelectOptions = () => {
+
+ const getColumnSelectOptions = useMemo(() => {
if (loadingItemsList) {
return [{ value: "loading", label: "در حال بارگذاری..." }];
}
@@ -129,24 +161,35 @@ const SupervisorList = () => {
label: item.name,
})),
];
- };
- const columnSelectOption = getColumnSelectOptions();
- return ;
+ }, [itemsList, loadingItemsList, errorItemsList]);
+
+ return (
+
+ );
+ },
+ Cell: ({ row }) => {
+ return row.original.item_fa;
},
},
{
- accessorKey: "sub_item_fa",
+ accessorKey: "sub_item",
header: "موضوع مشاهده شده",
- id: "sub_item_fa",
+ id: "sub_item",
enableColumnFilter: true,
datatype: "numeric",
filterMode: "equals",
- dependencyId: "item_fa",
+ dependencyId: "item",
ColumnSelectComponent: (props) => {
const { subItemsList, loadingSubItemsList, errorSubItemsList } = useRoadItemGetSubItems(
props.dependencyFieldValue.value
);
- const getColumnSelectOptions = () => {
+ const [prevDependency, setPrevDependency] = useState(props.dependencyFieldValue.value);
+
+ const getColumnSelectOptions = useMemo(() => {
if (props.dependencyFieldValue.value === "") {
return [{ value: "empty", label: "ابتدا آیتم فعالیت را انتخاب کنید" }];
}
@@ -159,13 +202,33 @@ const SupervisorList = () => {
return [
{ value: "", label: props.column.header },
...subItemsList.map((item) => ({
- value: item.id,
+ value: item.sub_item,
label: item.name,
})),
];
- };
- const columnSelectOption = getColumnSelectOptions();
- return ;
+ }, [subItemsList, loadingSubItemsList, errorSubItemsList]);
+
+ useEffect(() => {
+ if (prevDependency === props.dependencyFieldValue.value) return;
+ props.handleChange({ ...props.filterParameters, value: "" });
+ setPrevDependency(props.dependencyFieldValue.value);
+ }, [props.dependencyFieldValue.value]);
+ return (
+
+ );
+ },
+ Cell: ({ row }) => {
+ return row.original.sub_item_fa;
},
},
{
@@ -173,6 +236,7 @@ const SupervisorList = () => {
header: "مقدار", // Value
id: "value",
enableColumnFilter: false,
+ enableSorting: false,
datatype: "text",
filterMode: "equals",
grow: false,
@@ -289,10 +353,12 @@ const SupervisorList = () => {
{
accessorKey: "rahdaran",
header: "راهداران",
- id: "rahdaran",
- enableColumnFilter: false,
+ id: "rahdaran__code",
+ enableColumnFilter: true,
enableSorting: false,
- datatype: "array",
+ datatype: "text",
+ filterMode: "contains",
+ columnFilterModeOptions: ["equals", "contains"],
grow: false,
size: 100,
muiTableBodyCellProps: {
@@ -321,8 +387,7 @@ const SupervisorList = () => {
id: "activity_date_time",
enableColumnFilter: true,
datatype: "date",
- filterMode: "equals",
- columnFilterModeOptions: ["equals", "contains"],
+ filterMode: "between",
grow: false,
size: 100,
},
@@ -332,8 +397,7 @@ const SupervisorList = () => {
id: "created_at",
enableColumnFilter: true,
datatype: "date",
- filterMode: "equals",
- columnFilterModeOptions: ["equals", "contains"],
+ filterMode: "between",
grow: false,
size: 100,
},
@@ -355,9 +419,8 @@ const SupervisorList = () => {
},
Cell: ({ renderedCellValue, row }) => <>{row.original.status_fa}>,
},
- ],
- []
- );
+ ];
+ }, []);
return (
<>
diff --git a/src/components/dashboard/roadItems/supervisor/Toolbar.jsx b/src/components/dashboard/roadItems/supervisor/Toolbar.jsx
index 32c4395..47cb9a9 100644
--- a/src/components/dashboard/roadItems/supervisor/Toolbar.jsx
+++ b/src/components/dashboard/roadItems/supervisor/Toolbar.jsx
@@ -1,10 +1,6 @@
import PrintExcel from "./ExcelPrint";
const Toolbar = ({ table, filterData }) => {
- return (
- <>
-
- >
- );
+ return <>{/**/}>;
};
export default Toolbar;
diff --git a/src/components/dashboard/roadPatrols/operator/Forms/CreatePatrol/CompeleteRequest.jsx b/src/components/dashboard/roadPatrols/operator/Forms/CreatePatrol/CompeleteRequest.jsx
index 3299e47..51816c8 100644
--- a/src/components/dashboard/roadPatrols/operator/Forms/CreatePatrol/CompeleteRequest.jsx
+++ b/src/components/dashboard/roadPatrols/operator/Forms/CreatePatrol/CompeleteRequest.jsx
@@ -140,7 +140,7 @@ const CompeleteRequest = ({ watch, isSubmitting, setValue, register }) => {
{watch("road_patrol_rahdaran_id")?.map((rahdar, index) => (
-
+
نام و کد راهدار
diff --git a/src/components/dashboard/roadPatrols/operator/OperatorList.jsx b/src/components/dashboard/roadPatrols/operator/OperatorList.jsx
index c5e8d7a..e96d08d 100644
--- a/src/components/dashboard/roadPatrols/operator/OperatorList.jsx
+++ b/src/components/dashboard/roadPatrols/operator/OperatorList.jsx
@@ -7,8 +7,8 @@ import { GET_ROAD_PATROL_OPERATOR_LIST } from "@/core/utils/routes";
import moment from "jalali-moment";
import RowActions from "./RowActions";
import ReportForm from "./RowActions/ReportForm";
-import MachinesCodeDialog from "./RowActions/MachinesCodeForm";
import RahdaranDialog from "./RowActions/RahdaranForm";
+import MachinePerformanceForm from "./RowActions/MachinePerformanceForm";
const OperatorList = () => {
const columns = useMemo(
@@ -25,14 +25,13 @@ const OperatorList = () => {
size: 100,
},
{
- accessorKey: "cmms_machines",
- header: "خودرو", // Car ID
- id: "cmmsMachines__machine_code",
+ header: "عملکرد خودرو", // Car ID
enableColumnFilter: true,
+ id: "cmmsMachines__machine_code",
datatype: "text",
filterMode: "contains",
- enableSorting: false,
columnFilterModeOptions: ["equals", "contains"],
+ enableSorting: false,
grow: false,
size: 100,
muiTableBodyCellProps: {
@@ -45,23 +44,22 @@ const OperatorList = () => {
},
},
Cell: ({ renderedCellValue }) => {
- if (renderedCellValue) {
- return (
-
-
-
- );
- }
- return کد خودرویی وجود ندارد;
+ return (
+
+
+
+ );
},
},
{
accessorKey: "rahdaran",
header: "راهداران",
- id: "rahdaran",
- enableColumnFilter: false,
+ id: "rahdaran__code",
+ enableColumnFilter: true,
enableSorting: false,
- datatype: "array",
+ datatype: "text",
+ filterMode: "contains",
+ columnFilterModeOptions: ["equals", "contains"],
grow: false,
size: 100,
muiTableBodyCellProps: {
@@ -85,35 +83,32 @@ const OperatorList = () => {
},
},
{
- accessorFn: (row) => moment(row.start_date).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ accessorFn: (row) => moment(row.start_time).locale("fa").format("HH:mm | yyyy/MM/DD"),
header: "تاریخ شروع",
- id: "start_date",
+ id: "start_time",
enableColumnFilter: true,
datatype: "date",
- filterMode: "equals",
- columnFilterModeOptions: ["equals", "contains"],
+ filterMode: "between",
grow: false,
size: 100,
},
{
- accessorFn: (row) => moment(row.end_date).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ accessorFn: (row) => moment(row.end_time).locale("fa").format("HH:mm | yyyy/MM/DD"),
header: "تاریخ پایان",
- id: "end_date",
+ id: "end_time",
enableColumnFilter: true,
datatype: "date",
- filterMode: "equals",
- columnFilterModeOptions: ["equals", "contains"],
+ filterMode: "between",
grow: false,
size: 100,
},
{
- accessorFn: (row) => moment(row.register_date).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
header: "تاریخ ثبت",
- id: "register_date",
+ id: "created_at",
enableColumnFilter: true,
datatype: "date",
- filterMode: "equals",
- columnFilterModeOptions: ["equals", "contains"],
+ filterMode: "between",
grow: false,
size: 100,
},
diff --git a/src/components/dashboard/roadPatrols/operator/RowActions/MachinePerformanceForm/MachinePerformanceContent.jsx b/src/components/dashboard/roadPatrols/operator/RowActions/MachinePerformanceForm/MachinePerformanceContent.jsx
new file mode 100644
index 0000000..a38a935
--- /dev/null
+++ b/src/components/dashboard/roadPatrols/operator/RowActions/MachinePerformanceForm/MachinePerformanceContent.jsx
@@ -0,0 +1,76 @@
+import { Box, DialogContent, Stack } from "@mui/material";
+import React, { useEffect, useState, useRef } from "react";
+import { Marker, useMap } from "react-leaflet";
+import AzmayeshActiveIcon from "@/assets/images/examine_marker_active.png";
+import StopsInfo from "@/components/dashboard/roadPatrols/operator/RowActions/MachinePerformanceForm/StopsInfo";
+import MapLayer from "@/core/components/MapLayer";
+const defaultIconSize = [35, 35];
+const MachinePerformanceContent = ({ machinesLists }) => {
+ const [selectedPoint, setSelectedPoint] = useState(null);
+ const mapRef = useRef(null);
+ const isFirstRender = useRef(true);
+ const createCustomIcon = (size, iconUrl) => {
+ return L.icon({
+ iconUrl: iconUrl,
+ iconSize: size,
+ iconAnchor: [size[0] / 2, size[1]],
+ popupAnchor: [0, -size[1]],
+ });
+ };
+ const MapWithBounds = () => {
+ const map = useMap();
+ useEffect(() => {
+ if (machinesLists.stopPoints.length > 0) {
+ const bounds = machinesLists.stopPoints.map((point) => [point.latitude, point.longitude]);
+ if (isFirstRender.current) {
+ map.fitBounds(bounds, {
+ padding: [50, 50],
+ });
+ isFirstRender.current = false;
+ } else if (mapRef.current) {
+ mapRef.current.setView(map.getCenter(), map.getZoom());
+ }
+ }
+ }, [machinesLists.stopPoints, map]);
+ return null;
+ };
+ const handleMarkerClick = (point) => {
+ setSelectedPoint(point);
+ };
+
+ return (
+ <>
+
+
+
+
+
+
+
+ {machinesLists.stopPoints.map((point, index) => (
+ handleMarkerClick(point),
+ }}
+ >
+ ))}
+
+
+
+
+
+ >
+ );
+};
+export default MachinePerformanceContent;
diff --git a/src/components/dashboard/roadPatrols/operator/RowActions/MachinePerformanceForm/StopsInfo.jsx b/src/components/dashboard/roadPatrols/operator/RowActions/MachinePerformanceForm/StopsInfo.jsx
new file mode 100644
index 0000000..4483996
--- /dev/null
+++ b/src/components/dashboard/roadPatrols/operator/RowActions/MachinePerformanceForm/StopsInfo.jsx
@@ -0,0 +1,125 @@
+import { Box, Chip, Divider, Grid, Typography } from "@mui/material";
+import AccessAlarmsIcon from "@mui/icons-material/AccessAlarms";
+import PinDropIcon from "@mui/icons-material/PinDrop";
+import LocalGasStationIcon from "@mui/icons-material/LocalGasStation";
+import DirectionsCarIcon from "@mui/icons-material/DirectionsCar";
+
+const StopsInfo = ({ selectedPoint, staticData }) => {
+ return (
+
+
+
+ }
+ label={
+
+ کد ماشین
+
+ }
+ />
+
+
+
+ {staticData.cmmsMachineCode || ""}
+
+
+
+
+ }
+ label={
+
+ مصرف سوخت
+
+ }
+ />
+
+
+
+ {staticData.fuelConsumption || ""} لیتر
+
+
+
+
+ }
+ label={
+
+ مسافت طیشده
+
+ }
+ />
+
+
+
+ {staticData.mileage || ""} کیلومتر
+
+
+
+
+ }
+ label={
+
+ مدت زمان روشن بودن خودرو
+
+ }
+ />
+
+
+
+ {(staticData.accOnDuration / 60)?.toFixed(2) || ""} دقیقه
+
+
+
+
+ }
+ label={
+
+ طول جغرافیایی
+
+ }
+ />
+
+
+
+ {selectedPoint ? selectedPoint.longitude : "نقطه مورد نظر را انتخاب کنید"}
+
+
+
+
+ }
+ label={
+
+ عرض جغرافیایی
+
+ }
+ />
+
+
+
+ {selectedPoint ? selectedPoint.latitude : "نقطه مورد نظر را انتخاب کنید"}
+
+
+
+
+ }
+ label={
+
+ مدت زمان توقف
+
+ }
+ />
+
+
+
+ {selectedPoint ? `${selectedPoint.duration} ثانیه` : "نقطه مورد نظر را انتخاب کنید"}
+
+
+
+ );
+};
+export default StopsInfo;
diff --git a/src/components/dashboard/roadPatrols/supervisor/RowActions/MachinesCodeForm/index.jsx b/src/components/dashboard/roadPatrols/operator/RowActions/MachinePerformanceForm/index.jsx
similarity index 54%
rename from src/components/dashboard/roadPatrols/supervisor/RowActions/MachinesCodeForm/index.jsx
rename to src/components/dashboard/roadPatrols/operator/RowActions/MachinePerformanceForm/index.jsx
index 9696333..242902f 100644
--- a/src/components/dashboard/roadPatrols/supervisor/RowActions/MachinesCodeForm/index.jsx
+++ b/src/components/dashboard/roadPatrols/operator/RowActions/MachinePerformanceForm/index.jsx
@@ -1,13 +1,40 @@
import { Button, Dialog, DialogActions, DialogTitle, IconButton, Tooltip } from "@mui/material";
import DirectionsCarIcon from "@mui/icons-material/DirectionsCar";
+import MachinePerformanceContent from "./MachinePerformanceContent";
import { useState } from "react";
-import MachinesCodeContent from "./MachinesCodeContent";
-const MachinesCodeDialog = ({ machinesLists }) => {
+const MachinePerformanceForm = () => {
const [openMachinesCodeDialog, setOpenMachinesCodeDialog] = useState(false);
+ const machineData = {
+ cmms_machine_code: 245,
+ resultCode: 0,
+ mileage: 17645,
+ accOnDuration: 3599,
+ fuelConsumption: 6.1757503,
+ stopPoints: [
+ {
+ startDT: "2024-12-23T13:55:40",
+ duration: 114,
+ latitude: 37.521317,
+ longitude: 46.103584,
+ },
+ {
+ startDT: "2024-12-23T14:31:11",
+ duration: 14,
+ latitude: 37.566532,
+ longitude: 46.17688,
+ },
+ {
+ startDT: "2024-12-23T14:35:36",
+ duration: 55,
+ latitude: 37.569958,
+ longitude: 46.18166,
+ },
+ ],
+ };
return (
<>
-
+
setOpenMachinesCodeDialog(true)}>
@@ -24,8 +51,8 @@ const MachinesCodeDialog = ({ machinesLists }) => {
dir="rtl"
maxWidth={"md"}
>
- کد خودرو
-
+ عملکرد خودرو
+
+ );
+};
+export default PrintExcel;
diff --git a/src/components/dashboard/roadPatrols/reports/ReportLists.jsx b/src/components/dashboard/roadPatrols/reports/ReportLists.jsx
new file mode 100644
index 0000000..4a3d8e5
--- /dev/null
+++ b/src/components/dashboard/roadPatrols/reports/ReportLists.jsx
@@ -0,0 +1,209 @@
+"use client";
+import DataTableWithAuth from "@/core/components/DataTableWithAuth";
+import { Box } from "@mui/material";
+import { useMemo } from "react";
+import Toolbar from "./Toolbar";
+
+const ReportLists = ({ data }) => {
+ const columns = useMemo(() => {
+ return [
+ {
+ accessorKey: "edare_name",
+ header: "اداره کل",
+ id: "edare_name",
+ enableColumnFilter: false,
+ enableSorting: false,
+ datatype: "text",
+ grow: false,
+ size: 50,
+ },
+
+ {
+ accessorKey: "tedade",
+ header: "تعداد کل",
+ id: "tedade",
+ enableColumnFilter: false,
+ enableSorting: false,
+ datatype: "text",
+ grow: false,
+ size: 50,
+ muiTableBodyCellProps: {
+ sx: {
+ textAlign: "center",
+ borderLeft: "1px solid #e1e1e1",
+ py: 0,
+ "&:first-of-type": {
+ borderLeft: "unset",
+ },
+ },
+ },
+ Cell: ({ renderedCellValue }) => {
+ return (renderedCellValue / 1).toLocaleString();
+ },
+ },
+ {
+ header: "اقدامات لازم جهت رسیدگی آتی",
+ enableColumnFilter: false,
+ enableSorting: false,
+ datatype: "text",
+ grow: false,
+ size: 50,
+ columns: [
+ {
+ accessorKey: "tedad_mavarede_moshede_shode_adi",
+ header: "عادی",
+ id: "tedad_mavarede_moshede_shode_adi",
+ enableColumnFilter: false,
+ enableSorting: false,
+ datatype: "text",
+ grow: false,
+ size: 50,
+ muiTableBodyCellProps: {
+ sx: {
+ textAlign: "center",
+ borderLeft: "1px solid #e1e1e1",
+ py: 0,
+ "&:first-of-type": {
+ borderLeft: "unset",
+ },
+ },
+ },
+ Cell: ({ renderedCellValue }) => {
+ return (renderedCellValue / 1).toLocaleString();
+ },
+ },
+ {
+ accessorKey: "tedad_mavarede_moshede_shode_fori",
+ header: "فوری",
+ id: "tedad_mavarede_moshede_shode_fori",
+ enableColumnFilter: false,
+ enableSorting: false,
+ datatype: "text",
+ grow: false,
+ size: 50,
+ muiTableBodyCellProps: {
+ sx: {
+ textAlign: "center",
+ borderLeft: "1px solid #e1e1e1",
+ py: 0,
+ "&:first-of-type": {
+ borderLeft: "unset",
+ },
+ },
+ },
+ Cell: ({ renderedCellValue }) => {
+ return (renderedCellValue / 1).toLocaleString();
+ },
+ },
+ {
+ accessorKey: "tedad_mavarede_moshede_shode_ani",
+ header: "آنی",
+ id: "tedad_mavarede_moshede_shode_ani",
+ enableColumnFilter: false,
+ enableSorting: false,
+ datatype: "text",
+ grow: false,
+ size: 50,
+ muiTableBodyCellProps: {
+ sx: {
+ textAlign: "center",
+ borderLeft: "1px solid #e1e1e1",
+ py: 0,
+ "&:first-of-type": {
+ borderLeft: "unset",
+ },
+ },
+ },
+ Cell: ({ renderedCellValue }) => {
+ return (renderedCellValue / 1).toLocaleString();
+ },
+ },
+ ],
+ },
+ {
+ accessorKey: "tedad_mavarede_peygiri_shode",
+ header: "اقدامات رسیدگی شده",
+ id: "tedad_mavarede_peygiri_shode",
+ enableColumnFilter: false,
+ enableSorting: false,
+ datatype: "text",
+ grow: false,
+ size: 50,
+ muiTableBodyCellProps: {
+ sx: {
+ textAlign: "center",
+ borderLeft: "1px solid #e1e1e1",
+ py: 0,
+ "&:first-of-type": {
+ borderLeft: "unset",
+ },
+ },
+ },
+ Cell: ({ renderedCellValue }) => {
+ return (renderedCellValue / 1).toLocaleString();
+ },
+ },
+ {
+ accessorKey: "masafat_tey_shode",
+ header: "مجموع مسافت پیمایش شده",
+ id: "masafat_tey_shode",
+ enableColumnFilter: false,
+ enableSorting: false,
+ datatype: "text",
+ grow: false,
+ size: 50,
+ muiTableBodyCellProps: {
+ sx: {
+ textAlign: "center",
+ borderLeft: "1px solid #e1e1e1",
+ py: 0,
+ "&:first-of-type": {
+ borderLeft: "unset",
+ },
+ },
+ },
+ Cell: ({ renderedCellValue }) => {
+ return (renderedCellValue / 1).toLocaleString();
+ },
+ },
+ {
+ accessorKey: "tedad_faliyat_sabt_shode",
+ header: "تعداد فعالیت صورت گرفته حین گشت",
+ id: "tedad_faliyat_sabt_shode",
+ enableColumnFilter: false,
+ enableSorting: false,
+ datatype: "text",
+ grow: false,
+ size: 50,
+ muiTableBodyCellProps: {
+ sx: {
+ textAlign: "center",
+ borderLeft: "1px solid #e1e1e1",
+ py: 0,
+ "&:first-of-type": {
+ borderLeft: "unset",
+ },
+ },
+ },
+ Cell: ({ renderedCellValue }) => {
+ return (renderedCellValue / 1).toLocaleString();
+ },
+ },
+ ];
+ }, []);
+
+ return (
+
+
+
+ );
+};
+
+export default ReportLists;
diff --git a/src/components/dashboard/roadPatrols/reports/Search/FromDateController.jsx b/src/components/dashboard/roadPatrols/reports/Search/FromDateController.jsx
new file mode 100644
index 0000000..2cfa8af
--- /dev/null
+++ b/src/components/dashboard/roadPatrols/reports/Search/FromDateController.jsx
@@ -0,0 +1,27 @@
+import { Controller } from "react-hook-form";
+import MuiDatePicker from "@/core/components/MuiDatePicker";
+import React from "react";
+import moment from "jalali-moment";
+
+const FromDateController = ({ control }) => {
+ return (
+ (
+ {
+ const formattedDate = moment(new Date(newValue)).locale("en").format("YYYY-MM-DD");
+ onChange(formattedDate); // Update the field value in react-hook-form
+ }}
+ helperText={error ? error.message : null}
+ />
+ )}
+ />
+ );
+};
+export default FromDateController;
diff --git a/src/components/dashboard/roadPatrols/reports/Search/SearchReportField.jsx b/src/components/dashboard/roadPatrols/reports/Search/SearchReportField.jsx
new file mode 100644
index 0000000..ab8442c
--- /dev/null
+++ b/src/components/dashboard/roadPatrols/reports/Search/SearchReportField.jsx
@@ -0,0 +1,45 @@
+import { Button, Grid, LinearProgress, Typography } from "@mui/material";
+import SearchIcon from "@mui/icons-material/Search";
+import React from "react";
+import FromDateController from "./FromDateController";
+import ToDateController from "./ToDateController";
+import SelectProvince from "./SelectProvince";
+import { Controller } from "react-hook-form";
+
+const SearchReportField = ({ control, hasProvincesPermission }) => {
+ return (
+
+
+
+
+
+
+
+ {hasProvincesPermission && (
+
+
+
+ )}
+
+ (
+ }
+ fullWidth
+ >
+ {isSubmitting ? "درحال دریافت اطلاعات" : "جستجو"}
+
+ )}
+ />
+
+
+ );
+};
+
+export default SearchReportField;
diff --git a/src/components/dashboard/roadPatrols/reports/Search/SelectProvince.jsx b/src/components/dashboard/roadPatrols/reports/Search/SelectProvince.jsx
new file mode 100644
index 0000000..b1d8a39
--- /dev/null
+++ b/src/components/dashboard/roadPatrols/reports/Search/SelectProvince.jsx
@@ -0,0 +1,47 @@
+import { Controller } from "react-hook-form";
+import MuiDatePicker from "@/core/components/MuiDatePicker";
+import React from "react";
+import { FormControl, FormHelperText, InputLabel, LinearProgress, MenuItem, Select, Typography } from "@mui/material";
+import useProvinces from "@/lib/hooks/useProvince";
+
+const SelectProvince = ({ control }) => {
+ const { provinces, loadingProvinces, errorProvinces } = useProvinces();
+ return (
+ (
+
+ استان
+
+ {error && {error.message}}
+
+ )}
+ />
+ );
+};
+export default SelectProvince;
diff --git a/src/components/dashboard/roadPatrols/reports/Search/ToDateController.jsx b/src/components/dashboard/roadPatrols/reports/Search/ToDateController.jsx
new file mode 100644
index 0000000..003ac20
--- /dev/null
+++ b/src/components/dashboard/roadPatrols/reports/Search/ToDateController.jsx
@@ -0,0 +1,29 @@
+import { Controller, useWatch } from "react-hook-form";
+import MuiDatePicker from "@/core/components/MuiDatePicker";
+import React from "react";
+import moment from "jalali-moment";
+
+const ToDateController = ({ control }) => {
+ const minDate = useWatch({ control, name: "from_date" });
+ return (
+ (
+ {
+ const formattedDate = moment(new Date(newValue)).locale("en").format("YYYY-MM-DD");
+ onChange(formattedDate); // Update the field value in react-hook-form
+ }}
+ helperText={error ? error.message : null}
+ />
+ )}
+ />
+ );
+};
+export default ToDateController;
diff --git a/src/components/dashboard/roadPatrols/reports/Search/index.jsx b/src/components/dashboard/roadPatrols/reports/Search/index.jsx
new file mode 100644
index 0000000..f29d302
--- /dev/null
+++ b/src/components/dashboard/roadPatrols/reports/Search/index.jsx
@@ -0,0 +1,13 @@
+import StyledForm from "@/core/components/StyledForm";
+import SearchReportField from "./SearchReportField";
+
+const SearchReportList = ({ handleSubmit, onSearchSubmit, control, hasProvincesPermission }) => {
+ return (
+ <>
+
+
+
+ >
+ );
+};
+export default SearchReportList;
diff --git a/src/components/dashboard/roadPatrols/reports/Toolbar.jsx b/src/components/dashboard/roadPatrols/reports/Toolbar.jsx
new file mode 100644
index 0000000..5dc6e42
--- /dev/null
+++ b/src/components/dashboard/roadPatrols/reports/Toolbar.jsx
@@ -0,0 +1,7 @@
+import PrintExcel from "./ExcelPrint";
+import { Box } from "@mui/material";
+
+const Toolbar = ({ table, filterData, mutate }) => {
+ return {/**/};
+};
+export default Toolbar;
diff --git a/src/components/dashboard/roadPatrols/reports/index.jsx b/src/components/dashboard/roadPatrols/reports/index.jsx
new file mode 100644
index 0000000..12743aa
--- /dev/null
+++ b/src/components/dashboard/roadPatrols/reports/index.jsx
@@ -0,0 +1,122 @@
+"use client";
+import PageTitle from "@/core/components/PageTitle";
+import { LinearProgress, Stack } from "@mui/material";
+import SearchReportList from "./Search";
+import { useEffect, useState } from "react";
+import ReportLists from "./ReportLists";
+import useRequest from "@/lib/hooks/useRequest";
+import { GET_CITY_ACTIVITY_REPORT, GET_PROVINCE_ACTIVITY_REPORT } from "@/core/utils/routes";
+import moment from "jalali-moment";
+import * as yup from "yup";
+import { useForm } from "react-hook-form";
+import { yupResolver } from "@hookform/resolvers/yup";
+import { usePermissions } from "@/lib/hooks/usePermissions";
+import { useAuth } from "@/lib/contexts/auth";
+
+const ReportPage = () => {
+ const [data, setData] = useState(null);
+ const { data: userPermissions } = usePermissions();
+ const { user } = useAuth();
+ const requestServer = useRequest();
+ const hasProvincesPermission = userPermissions.includes("show-road-patrol-supervise-cartable");
+
+ const defaultValues = {
+ from_date: moment(new Date()).format("YYYY-MM-DD"),
+ date_to: moment(new Date()).format("YYYY-MM-DD"),
+ province_id: hasProvincesPermission ? "-1" : user.province_id,
+ };
+
+ const onSearchSubmit = async (data) => {
+ const params = new URLSearchParams();
+ params.set("from_date", `${data.from_date}`);
+ params.set("date_to", `${data.date_to}`);
+ if (data.province_id === "-1") {
+ try {
+ const response = await requestServer(`${GET_PROVINCE_ACTIVITY_REPORT}?${params}`);
+ const result = response.data.data;
+ const nationalReportForItem = result.activities.find((report) => report.province_id === -1);
+ const nationalReport = {
+ edare_name: "کل کشور",
+ ...nationalReportForItem,
+ };
+
+ setData({
+ data: [
+ nationalReport,
+ ...result.provinces.map((province) => {
+ const filteredReports = result.activities.find(
+ (report) => report.province_id === province.id
+ );
+ return {
+ ...filteredReports,
+ edare_name: province.name_fa,
+ };
+ }),
+ ],
+ filters: data,
+ });
+ } catch (e) {}
+ } else {
+ try {
+ params.set("province_id", `${data.province_id}`);
+ const response = await requestServer(`${GET_CITY_ACTIVITY_REPORT}?${params}`);
+ const result = response.data.data;
+ const nationalReportForItem = result.activities.find((report) => report.edare_id === "-1");
+ const nationalReport = {
+ ...nationalReportForItem,
+ edare_name: "کل استان",
+ };
+ setData({
+ data: [
+ nationalReport,
+ ...result.edarateShahri.map((edare) => {
+ const filteredReports = result.activities.find((report) => report.edare_id == edare.id);
+ return {
+ edare_name: edare.name_fa,
+ ...filteredReports,
+ };
+ }),
+ ],
+ filters: data,
+ });
+ } catch (e) {}
+ }
+ };
+
+ useEffect(() => {
+ onSearchSubmit(defaultValues);
+ }, []);
+
+ const validationSchema = yup.object().shape({
+ from_date: yup
+ .string()
+ .required("تاریخ شروع الزامی است!")
+ .matches(/^\d{4}-\d{2}-\d{2}$/, "تاریخ شروع الزامی است!")
+ .test("is-valid-date", "تاریخ شروع معتبر نیست!", (value) => moment(value, "YYYY-MM-DD", true).isValid()),
+ date_to: yup
+ .string()
+ .required("تاریخ پایان الزامی است!")
+ .matches(/^\d{4}-\d{2}-\d{2}$/, "تاریخ پایان الزامی است!")
+ .test("is-valid-date", "تاریخ پایان معتبر نیست!", (value) => moment(value, "YYYY-MM-DD", true).isValid()),
+ province_id: yup.string().nullable(),
+ });
+
+ const { control, handleSubmit } = useForm({
+ defaultValues,
+ resolver: yupResolver(validationSchema),
+ mode: "onBlur",
+ });
+ return (
+
+
+
+ {!data ? : }
+
+ );
+};
+export default ReportPage;
diff --git a/src/components/dashboard/roadPatrols/supervisor/RowActions/DeleteForm/DeleteContent.jsx b/src/components/dashboard/roadPatrols/supervisor/RowActions/DeleteForm/DeleteContent.jsx
index bb9303d..3e6386f 100644
--- a/src/components/dashboard/roadPatrols/supervisor/RowActions/DeleteForm/DeleteContent.jsx
+++ b/src/components/dashboard/roadPatrols/supervisor/RowActions/DeleteForm/DeleteContent.jsx
@@ -3,7 +3,13 @@ import useRequest from "@/lib/hooks/useRequest";
import React, { useState } from "react";
import { DELETE_ROAD_PATROL_SUPERVISOR } from "@/core/utils/routes";
-const DeleteContent = ({ rowId, mutate, setOpenDeleteDialog }) => {
+const DeleteContent = ({
+ rowId,
+ mutate,
+ setOpenDeleteDialog,
+ hasCompleteDeletePermission,
+ hasPartialDeletePermission,
+}) => {
const requestServer = useRequest({ notificationSuccess: true });
const [submittingPartial, setSubmittingPartial] = useState(false);
const [submittingGeneral, setSubmittingGeneral] = useState(false);
@@ -49,41 +55,59 @@ const DeleteContent = ({ rowId, mutate, setOpenDeleteDialog }) => {
لطفاً نوع حذف مورد نظر را انتخاب کنید.
-
- حذف جزئی : حذف گشت بدون اقدامات انجام شده.
-
-
- حذف کلی : حذف گشت با اقدامات انجام شده.
-
+ {hasPartialDeletePermission && (
+
+ حذف جزئی : حذف گشت بدون اقدامات انجام شده.
+
+ )}
+ {hasCompleteDeletePermission && (
+
+ حذف کلی : حذف گشت با اقدامات انجام شده.
+
+ )}
-
+
setOpenDeleteDialog(false)} variant="outlined" color="primary">
بستن
-
- {submittingPartial ? "درحال ارسال اطلاعات..." : "حذف جزئی"}
-
-
- {submittingGeneral ? "درحال ارسال اطلاعات..." : "حذف کلی"}
-
+ {hasPartialDeletePermission && (
+
+ {submittingPartial ? "درحال ارسال اطلاعات..." : "حذف جزئی"}
+
+ )}
+ {hasCompleteDeletePermission && (
+
+ {submittingGeneral ? "درحال ارسال اطلاعات..." : "حذف کلی"}
+
+ )}
>
);
diff --git a/src/components/dashboard/roadPatrols/supervisor/RowActions/DeleteForm/index.jsx b/src/components/dashboard/roadPatrols/supervisor/RowActions/DeleteForm/index.jsx
index a7218df..07a903f 100644
--- a/src/components/dashboard/roadPatrols/supervisor/RowActions/DeleteForm/index.jsx
+++ b/src/components/dashboard/roadPatrols/supervisor/RowActions/DeleteForm/index.jsx
@@ -2,7 +2,7 @@ import React, { useState } from "react";
import { Tooltip, IconButton, Dialog, DialogTitle } from "@mui/material";
import DeleteIcon from "@mui/icons-material/Delete";
import DeleteContent from "./DeleteContent";
-const DeleteForm = ({ rowId, mutate }) => {
+const DeleteForm = ({ rowId, mutate, hasCompleteDeletePermission, hasPartialDeletePermission }) => {
const [openDeleteDialog, setOpenDeleteDialog] = useState(false);
return (
@@ -24,7 +24,13 @@ const DeleteForm = ({ rowId, mutate }) => {
maxWidth={"md"}
>
حذف گشت
-
+
>
);
diff --git a/src/components/dashboard/roadPatrols/supervisor/RowActions/MachinePerformanceForm/MachinePerformanceContent.jsx b/src/components/dashboard/roadPatrols/supervisor/RowActions/MachinePerformanceForm/MachinePerformanceContent.jsx
new file mode 100644
index 0000000..09e5af6
--- /dev/null
+++ b/src/components/dashboard/roadPatrols/supervisor/RowActions/MachinePerformanceForm/MachinePerformanceContent.jsx
@@ -0,0 +1,76 @@
+import { Box, DialogContent, Stack } from "@mui/material";
+import React, { useEffect, useState, useRef } from "react";
+import { Marker, useMap } from "react-leaflet";
+import AzmayeshActiveIcon from "@/assets/images/examine_marker_active.png";
+import StopsInfo from "./StopsInfo";
+import MapLayer from "@/core/components/MapLayer";
+const defaultIconSize = [35, 35];
+const MachinePerformanceContent = ({ machinesLists }) => {
+ const [selectedPoint, setSelectedPoint] = useState(null);
+ const mapRef = useRef(null);
+ const isFirstRender = useRef(true);
+ const createCustomIcon = (size, iconUrl) => {
+ return L.icon({
+ iconUrl: iconUrl,
+ iconSize: size,
+ iconAnchor: [size[0] / 2, size[1]],
+ popupAnchor: [0, -size[1]],
+ });
+ };
+ const MapWithBounds = () => {
+ const map = useMap();
+ useEffect(() => {
+ if (machinesLists.stopPoints.length > 0) {
+ const bounds = machinesLists.stopPoints.map((point) => [point.latitude, point.longitude]);
+ if (isFirstRender.current) {
+ map.fitBounds(bounds, {
+ padding: [50, 50],
+ });
+ isFirstRender.current = false;
+ } else if (mapRef.current) {
+ mapRef.current.setView(map.getCenter(), map.getZoom());
+ }
+ }
+ }, [machinesLists.stopPoints, map]);
+ return null;
+ };
+ const handleMarkerClick = (point) => {
+ setSelectedPoint(point);
+ };
+
+ return (
+ <>
+
+
+
+
+
+
+
+ {machinesLists.stopPoints.map((point, index) => (
+ handleMarkerClick(point),
+ }}
+ >
+ ))}
+
+
+
+
+
+ >
+ );
+};
+export default MachinePerformanceContent;
diff --git a/src/components/dashboard/roadPatrols/supervisor/RowActions/MachinePerformanceForm/StopsInfo.jsx b/src/components/dashboard/roadPatrols/supervisor/RowActions/MachinePerformanceForm/StopsInfo.jsx
new file mode 100644
index 0000000..25d9238
--- /dev/null
+++ b/src/components/dashboard/roadPatrols/supervisor/RowActions/MachinePerformanceForm/StopsInfo.jsx
@@ -0,0 +1,129 @@
+import { Box, Chip, Divider, Grid, Typography } from "@mui/material";
+import AccessAlarmsIcon from "@mui/icons-material/AccessAlarms";
+import PinDropIcon from "@mui/icons-material/PinDrop";
+import LocalGasStationIcon from "@mui/icons-material/LocalGasStation";
+import DirectionsCarIcon from "@mui/icons-material/DirectionsCar";
+const StopsInfo = ({ selectedPoint, staticData }) => {
+ return (
+
+
+
+ }
+ label={
+
+ کد ماشین
+
+ }
+ />
+
+
+
+ {staticData.cmmsMachineCode || ""}
+
+
+
+
+ }
+ label={
+
+ مصرف سوخت
+
+ }
+ />
+
+
+
+ {staticData.fuelConsumption || ""} لیتر
+
+
+
+
+ }
+ label={
+
+ مسافت طیشده
+
+ }
+ />
+
+
+
+ {staticData.mileage || ""} کیلومتر
+
+
+
+
+ }
+ label={
+
+ مدت زمان روشن بودن خودرو
+
+ }
+ />
+
+
+
+ {(staticData.accOnDuration / 60)?.toFixed(2) || ""} دقیقه
+
+
+
+ {selectedPoint && (
+ <>
+
+
+ }
+ label={
+
+ طول جغرافیایی
+
+ }
+ />
+
+
+
+ {selectedPoint.longitude || ""}
+
+
+
+
+ }
+ label={
+
+ عرض جغرافیایی
+
+ }
+ />
+
+
+
+ {selectedPoint.latitude || ""}
+
+
+
+
+ }
+ label={
+
+ مدت زمان توقف
+
+ }
+ />
+
+
+
+ {selectedPoint.duration || ""} ثانیه
+
+
+ >
+ )}
+
+ );
+};
+export default StopsInfo;
diff --git a/src/components/dashboard/roadPatrols/supervisor/RowActions/MachinePerformanceForm/index.jsx b/src/components/dashboard/roadPatrols/supervisor/RowActions/MachinePerformanceForm/index.jsx
new file mode 100644
index 0000000..242902f
--- /dev/null
+++ b/src/components/dashboard/roadPatrols/supervisor/RowActions/MachinePerformanceForm/index.jsx
@@ -0,0 +1,70 @@
+import { Button, Dialog, DialogActions, DialogTitle, IconButton, Tooltip } from "@mui/material";
+import DirectionsCarIcon from "@mui/icons-material/DirectionsCar";
+import MachinePerformanceContent from "./MachinePerformanceContent";
+import { useState } from "react";
+
+const MachinePerformanceForm = () => {
+ const [openMachinesCodeDialog, setOpenMachinesCodeDialog] = useState(false);
+ const machineData = {
+ cmms_machine_code: 245,
+ resultCode: 0,
+ mileage: 17645,
+ accOnDuration: 3599,
+ fuelConsumption: 6.1757503,
+ stopPoints: [
+ {
+ startDT: "2024-12-23T13:55:40",
+ duration: 114,
+ latitude: 37.521317,
+ longitude: 46.103584,
+ },
+ {
+ startDT: "2024-12-23T14:31:11",
+ duration: 14,
+ latitude: 37.566532,
+ longitude: 46.17688,
+ },
+ {
+ startDT: "2024-12-23T14:35:36",
+ duration: 55,
+ latitude: 37.569958,
+ longitude: 46.18166,
+ },
+ ],
+ };
+ return (
+ <>
+
+ setOpenMachinesCodeDialog(true)}>
+
+
+
+ setOpenMachinesCodeDialog(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"}
+ >
+ عملکرد خودرو
+
+
+ setOpenMachinesCodeDialog(false)}
+ variant="outlined"
+ color="secondary"
+ autoFocus
+ >
+ بستن
+
+
+
+ >
+ );
+};
+export default MachinePerformanceForm;
diff --git a/src/components/dashboard/roadPatrols/supervisor/RowActions/MachinesCodeForm/MachinesCodeContent.jsx b/src/components/dashboard/roadPatrols/supervisor/RowActions/MachinesCodeForm/MachinesCodeContent.jsx
deleted file mode 100644
index 1eef774..0000000
--- a/src/components/dashboard/roadPatrols/supervisor/RowActions/MachinesCodeForm/MachinesCodeContent.jsx
+++ /dev/null
@@ -1,55 +0,0 @@
-import { DialogContent, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from "@mui/material";
-import ShowPlak from "@/core/components/ShowPlak";
-
-const MachinesCodeContent = ({ machinesLists }) => {
- return (
- <>
-
-
-
-
-
-
- کد ماشین
- نام خودرو
- پلاک
-
-
-
- {machinesLists.map((machine) => {
- return (
-
- {machine.machine_code}
- {machine.car_name}
-
- {machine.plak_number ? (
-
- ) : null}
-
-
- );
- })}
-
-
-
-
-
- >
- );
-};
-export default MachinesCodeContent;
diff --git a/src/components/dashboard/roadPatrols/supervisor/RowActions/OfficerDescription/index.jsx b/src/components/dashboard/roadPatrols/supervisor/RowActions/OfficerDescription/index.jsx
index 04b5946..1ba3991 100644
--- a/src/components/dashboard/roadPatrols/supervisor/RowActions/OfficerDescription/index.jsx
+++ b/src/components/dashboard/roadPatrols/supervisor/RowActions/OfficerDescription/index.jsx
@@ -37,7 +37,7 @@ const OfficerDescriptionForm = ({ description }) => {
-
+
{description || "هیچ توضیحی موجود نیست"}
diff --git a/src/components/dashboard/roadPatrols/supervisor/RowActions/index.jsx b/src/components/dashboard/roadPatrols/supervisor/RowActions/index.jsx
index 09d7502..0b3d0a0 100644
--- a/src/components/dashboard/roadPatrols/supervisor/RowActions/index.jsx
+++ b/src/components/dashboard/roadPatrols/supervisor/RowActions/index.jsx
@@ -1,10 +1,21 @@
import { Box } from "@mui/material";
import DeleteForm from "./DeleteForm";
+import { usePermissions } from "@/lib/hooks/usePermissions";
const RowActions = ({ row, mutate }) => {
+ const { data: userPermissions } = usePermissions();
+ const hasPartialDeletePermission = userPermissions.includes("partial-delete-road-patrol");
+ const hasCompleteDeletePermission = userPermissions.includes("complete-delete-road-patrol");
return (
-
+ {hasPartialDeletePermission | hasCompleteDeletePermission && (
+
+ )}
);
};
diff --git a/src/components/dashboard/roadPatrols/supervisor/SupervisorList.jsx b/src/components/dashboard/roadPatrols/supervisor/SupervisorList.jsx
index 5ec3369..6408d4d 100644
--- a/src/components/dashboard/roadPatrols/supervisor/SupervisorList.jsx
+++ b/src/components/dashboard/roadPatrols/supervisor/SupervisorList.jsx
@@ -1,6 +1,6 @@
"use client";
-import { useMemo } from "react";
-import {Box, Stack, Typography} from "@mui/material";
+import { useEffect, useMemo, useState } from "react";
+import { Box, Stack, Typography } from "@mui/material";
import DataTableWithAuth from "@/core/components/DataTableWithAuth";
import Toolbar from "./Toolbar";
import { GET_ROAD_PATROL_SUPERVISOR_LIST } from "@/core/utils/routes";
@@ -11,12 +11,53 @@ import CustomSelectByDependency from "@/core/components/DataTable/filter/fieldsT
import useEdaratLists from "@/lib/hooks/useEdaratLists";
import OfficerDescriptionForm from "./RowActions/OfficerDescription";
import ReportForm from "./RowActions/ReportForm";
-import MachinesCodeDialog from "./RowActions/MachinesCodeForm";
import RahdaranDialog from "./RowActions/RahdaranForm";
+import MachinePerformanceForm from "./RowActions/MachinePerformanceForm";
+import { usePermissions } from "@/lib/hooks/usePermissions";
+import { useAuth } from "@/lib/contexts/auth";
-const OperatorList = () => {
- const columns = useMemo(
- () => [
+const SupervisorList = () => {
+ const { data: userPermissions } = usePermissions();
+ const hasCountryPermission = userPermissions.includes("show-road-patrol-supervise-cartable");
+ const { user } = useAuth();
+ const columns = useMemo(() => {
+ const dynamicColumns = {
+ accessorKey: "province_id",
+ header: "استان", // Province
+ id: "province_id",
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterMode: "equals",
+ grow: false,
+ size: 130,
+ ColumnSelectComponent: (props) => {
+ const { provinces, errorProvinces, loadingProvinces } = useProvinces();
+ const getColumnSelectOptions = useMemo(() => {
+ if (loadingProvinces) {
+ return [{ value: "loading", label: "در حال بارگذاری..." }];
+ }
+ if (errorProvinces) {
+ return [{ value: "error", label: "خطا در بارگذاری" }];
+ }
+ return [
+ { value: "", label: props.column.header },
+ ...provinces.map((province) => ({
+ value: province.id,
+ label: province.name_fa,
+ })),
+ ];
+ }, [provinces, errorProvinces, loadingProvinces]);
+ return (
+
+ );
+ },
+ Cell: ({ renderedCellValue, row }) => <>{row.original.province_fa}>,
+ };
+ return [
{
accessorKey: "id",
header: "کد یکتا",
@@ -28,35 +69,7 @@ const OperatorList = () => {
grow: false,
size: 100,
},
- {
- accessorKey: "province_id",
- header: "استان",
- id: "province_id",
- enableColumnFilter: true,
- datatype: "numeric",
- filterMode: "equals",
- ColumnSelectComponent: (props) => {
- const { provinces, errorProvinces, loadingProvinces } = useProvinces();
- const getColumnSelectOptions = () => {
- if (loadingProvinces) {
- return [{ value: "loading", label: "در حال بارگذاری..." }];
- }
- if (errorProvinces) {
- return [{ value: "error", label: "خطا در بارگذاری" }];
- }
- return [
- { value: "", label: props.column.header },
- ...provinces.map((province) => ({
- value: province.id,
- label: province.name_fa,
- })),
- ];
- };
- const columnSelectOption = getColumnSelectOptions();
- return ;
- },
- Cell: ({ renderedCellValue, row }) => <>{row.original.province_fa}>,
- },
+ ...(hasCountryPermission ? [dynamicColumns] : []),
{
accessorKey: "edare_id",
header: "اداره",
@@ -64,15 +77,19 @@ const OperatorList = () => {
enableColumnFilter: true,
datatype: "numeric",
filterMode: "equals",
- dependencyId: "province_id",
+ dependencyId: hasCountryPermission ? "province_id" : null,
grow: false,
size: 120,
ColumnSelectComponent: (props) => {
const { edaratList, loadingEdaratList, errorEdaratList } = useEdaratLists(
- props.dependencyFieldValue.value
+ hasCountryPermission ? props.dependencyFieldValue.value : user.province_id
);
- const getColumnSelectOptions = () => {
- if (props.dependencyFieldValue.value === "") {
+ const [prevDependency, setPrevDependency] = useState(
+ hasCountryPermission ? props.dependencyFieldValue.value : user.province_id
+ );
+
+ const getColumnSelectOptions = useMemo(() => {
+ if (hasCountryPermission && props.dependencyFieldValue.value === "") {
return [{ value: "empty", label: "ابتدا استان را انتخاب کنید" }];
}
if (loadingEdaratList) {
@@ -88,21 +105,37 @@ const OperatorList = () => {
label: edare.name_fa,
})),
];
- };
- const columnSelectOption = getColumnSelectOptions();
- return ;
+ }, [edaratList, loadingEdaratList, errorEdaratList]);
+ useEffect(() => {
+ if (hasCountryPermission) return;
+ if (prevDependency === props.dependencyFieldValue?.value) return;
+ props.handleChange({ ...props.filterParameters, value: "" });
+ setPrevDependency(props.dependencyFieldValue?.value);
+ }, [props.dependencyFieldValue?.value, hasCountryPermission]);
+ return (
+
+ );
},
Cell: ({ renderedCellValue, row }) => <>{row.original.edare_name}>,
},
{
- accessorKey: "cmms_machines",
- header: "خودرو", // Car ID
- id: "cmmsMachines__machine_code",
+ header: "عملکرد خودرو",
enableColumnFilter: true,
+ id: "cmmsMachines__machine_code",
datatype: "text",
filterMode: "contains",
- enableSorting: false,
columnFilterModeOptions: ["equals", "contains"],
+ enableSorting: false,
grow: false,
size: 100,
muiTableBodyCellProps: {
@@ -114,24 +147,21 @@ const OperatorList = () => {
},
},
},
- Cell: ({ renderedCellValue }) => {
- if (renderedCellValue) {
- return (
-
-
-
- );
- }
- return کد خودرویی وجود ندارد;
- },
+ Cell: () => (
+
+
+
+ ),
},
{
accessorKey: "rahdaran",
header: "راهداران",
- id: "rahdaran",
- enableColumnFilter: false,
+ id: "rahdaran__code",
+ enableColumnFilter: true,
enableSorting: false,
- datatype: "array",
+ datatype: "text",
+ filterMode: "contains",
+ columnFilterModeOptions: ["equals", "contains"],
grow: false,
size: 100,
muiTableBodyCellProps: {
@@ -143,47 +173,42 @@ const OperatorList = () => {
},
},
},
- Cell: ({ renderedCellValue }) => {
- if (renderedCellValue) {
- return (
-
-
-
- );
- }
- return بدون شخص;
- },
+ Cell: ({ renderedCellValue }) =>
+ renderedCellValue ? (
+
+
+
+ ) : (
+ بدون شخص
+ ),
},
{
- accessorFn: (row) => moment(row.start_date).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ accessorFn: (row) => moment(row.start_time).locale("fa").format("HH:mm | yyyy/MM/DD"),
header: "تاریخ شروع",
- id: "start_date",
+ id: "start_time",
enableColumnFilter: true,
datatype: "date",
- filterMode: "equals",
- columnFilterModeOptions: ["equals", "contains"],
+ filterMode: "between",
grow: false,
size: 100,
},
{
- accessorFn: (row) => moment(row.end_date).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ accessorFn: (row) => moment(row.end_time).locale("fa").format("HH:mm | yyyy/MM/DD"),
header: "تاریخ پایان",
- id: "end_date",
+ id: "end_time",
enableColumnFilter: true,
datatype: "date",
- filterMode: "equals",
- columnFilterModeOptions: ["equals", "contains"],
+ filterMode: "between",
grow: false,
size: 100,
},
{
- accessorFn: (row) => moment(row.register_date).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
header: "تاریخ ثبت",
- id: "register_date",
+ id: "created_at",
enableColumnFilter: true,
datatype: "date",
- filterMode: "equals",
- columnFilterModeOptions: ["equals", "contains"],
+ filterMode: "between",
grow: false,
size: 100,
},
@@ -204,13 +229,11 @@ const OperatorList = () => {
},
},
},
- Cell: ({ renderedCellValue }) => {
- return (
-
-
-
- );
- },
+ Cell: ({ renderedCellValue }) => (
+
+
+
+ ),
},
{
header: "گزارش مامور",
@@ -227,17 +250,14 @@ const OperatorList = () => {
},
},
},
- Cell: ({ renderedCellValue, row }) => {
- return (
-
-
-
- );
- },
+ Cell: ({ row }) => (
+
+
+
+ ),
},
- ],
- []
- );
+ ];
+ }, []);
return (
<>
@@ -258,4 +278,4 @@ const OperatorList = () => {
>
);
};
-export default OperatorList;
+export default SupervisorList;
diff --git a/src/components/dashboard/roadPatrols/supervisor/Toolbar.jsx b/src/components/dashboard/roadPatrols/supervisor/Toolbar.jsx
index 32c4395..47cb9a9 100644
--- a/src/components/dashboard/roadPatrols/supervisor/Toolbar.jsx
+++ b/src/components/dashboard/roadPatrols/supervisor/Toolbar.jsx
@@ -1,10 +1,6 @@
import PrintExcel from "./ExcelPrint";
const Toolbar = ({ table, filterData }) => {
- return (
- <>
-
- >
- );
+ return <>{/**/}>;
};
export default Toolbar;
diff --git a/src/components/dashboard/roadPatrols/supervisor/index.jsx b/src/components/dashboard/roadPatrols/supervisor/index.jsx
index 67f9f63..3fa490b 100644
--- a/src/components/dashboard/roadPatrols/supervisor/index.jsx
+++ b/src/components/dashboard/roadPatrols/supervisor/index.jsx
@@ -1,13 +1,13 @@
"use client";
import PageTitle from "@/core/components/PageTitle";
import { Stack } from "@mui/material";
-import SuperviserList from "./SupervisorList";
+import SupervisorList from "./SupervisorList";
const SupervisorPage = () => {
return (
-
+
);
};
diff --git a/src/core/components/ActivityCodeLog.jsx b/src/core/components/ActivityCodeLog.jsx
index cf284e6..f301549 100644
--- a/src/core/components/ActivityCodeLog.jsx
+++ b/src/core/components/ActivityCodeLog.jsx
@@ -3,6 +3,7 @@
import { useEffect, useState, memo } from "react";
import useRequest from "@/lib/hooks/useRequest";
import { ACTIVITY_LOG } from "@/core/utils/routes";
+import NumberField from "@/core/components/NumberField";
const ActivityCodeLog = memo(({ activity_code }) => {
const requestServer = useRequest({ notificationShow: false });
@@ -32,5 +33,6 @@ const ActivityCodeLog = memo(({ activity_code }) => {
return null;
});
+ActivityCodeLog.displayName = "ActivityCodeLog";
export default ActivityCodeLog;
diff --git a/src/core/components/CarCode.jsx b/src/core/components/CarCode.jsx
index a5e5ea7..60d7cda 100644
--- a/src/core/components/CarCode.jsx
+++ b/src/core/components/CarCode.jsx
@@ -77,10 +77,14 @@ const CarCode = ({ carCode, setCarCode, inputValueDefault = "", error, multiple
renderInput={(params) => (
{
setSortData(event);
};
- const fetchUrl = useMemo(() => {
+ const fetchUrl = useCallback(() => {
const params = new URLSearchParams();
params.set("start", `${pagination.pageIndex * pagination.pageSize}`);
params.set("size", pagination.pageSize);
@@ -76,7 +76,7 @@ const DataTable_Main = (props) => {
}
};
- const { data, isValidating, mutate } = useSWR(fetchUrl, fetcher, {
+ const { data, isValidating, mutate } = useSWR(props.data ? "" : fetchUrl(), fetcher, {
revalidateIfStale: true,
revalidateOnFocus: false,
revalidateOnReconnect: true,
@@ -129,7 +129,11 @@ const DataTable_Main = (props) => {
onSortingChange: onSortingChange,
rowCount: totalRowCount,
renderTopToolbarCustomActions: ({ table }) => (
- <>{TableToolbar && }>
+ <>
+ {TableToolbar && (
+
+ )}
+ >
),
renderRowActions: ({ row }) => ,
...props,
@@ -146,6 +150,7 @@ const DataTable_Main = (props) => {
user_id={user_id}
page_name={page_name}
table_name={table_name}
+ special_data={props.data}
/>
);
};
diff --git a/src/core/components/DataTable/filter/FilterBody.jsx b/src/core/components/DataTable/filter/FilterBody.jsx
index d0eb7cf..32d3e3f 100644
--- a/src/core/components/DataTable/filter/FilterBody.jsx
+++ b/src/core/components/DataTable/filter/FilterBody.jsx
@@ -9,6 +9,7 @@ import { useEffect, useState } from "react";
import { Controller, useForm, useWatch } from "react-hook-form";
import * as Yup from "yup";
import FilterBodyController from "./FilterBodyController";
+import FilterBodyControllerWithDependency from "@/core/components/DataTable/filter/FilterBodyControllerWithDependency";
const ScrollBox = styled(Box)({
flexGrow: 1,
@@ -74,7 +75,7 @@ function FilterBody({ columns, drawerState, setDrawerState }) {
} = useForm({
defaultValues: filterData,
resolver: yupResolver(validationSchema),
- mode: "onChange",
+ mode: "onBlur",
});
const onSubmit = (data) => {
@@ -93,9 +94,17 @@ function FilterBody({ columns, drawerState, setDrawerState }) {