diff --git a/jsconfig.json b/jsconfig.json
index b51472a..c136578 100644
--- a/jsconfig.json
+++ b/jsconfig.json
@@ -1,27 +1,27 @@
// javascript for production
-{
- "compilerOptions": {
- "paths": {
- "@/*": ["./src/*"],
- "^/*": ["./public/*"]
- }
- }
-}
-
-// typescript for local development
// {
// "compilerOptions": {
-// "jsx": "react-jsx",
-// "noUnusedLocals": true,
-// "noImplicitAny": false,
-// "checkJs": true,
-// "allowJs": true,
-// "strict": true,
-// "baseUrl": ".",
// "paths": {
// "@/*": ["./src/*"],
// "^/*": ["./public/*"]
// }
-// },
-// "exclude": ["node_modules"]
+// }
// }
+
+// typescript for local development
+{
+ "compilerOptions": {
+ "jsx": "react-jsx",
+ "noUnusedLocals": true,
+ "noImplicitAny": false,
+ "checkJs": true,
+ "allowJs": true,
+ "strict": true,
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["./src/*"],
+ "^/*": ["./public/*"]
+ }
+ },
+ "exclude": ["node_modules"]
+}
diff --git a/src/app/(withAuth)/(dashboardLayout)/dashboard/road-missions/reports/machinesReports/page.js b/src/app/(withAuth)/(dashboardLayout)/dashboard/road-missions/reports/machinesReports/page.js
new file mode 100644
index 0000000..0656840
--- /dev/null
+++ b/src/app/(withAuth)/(dashboardLayout)/dashboard/road-missions/reports/machinesReports/page.js
@@ -0,0 +1,18 @@
+import MachinesReportsPage from "@/components/dashboard/roadMissions/reports/machinesReports";
+import WithPermission from "@/core/middlewares/withPermission";
+
+export const metadata = {
+ title: "کارتابل گزارش ماشینها",
+};
+
+export default function Page() {
+ return (
+
+
+
+ );
+}
diff --git a/src/components/dashboard/roadMissions/reports/machinesReports/ExcelPrint/index.jsx b/src/components/dashboard/roadMissions/reports/machinesReports/ExcelPrint/index.jsx
new file mode 100644
index 0000000..ef85a7f
--- /dev/null
+++ b/src/components/dashboard/roadMissions/reports/machinesReports/ExcelPrint/index.jsx
@@ -0,0 +1,77 @@
+"use client";
+import {
+ EXPORT_GET_MACHINES_COUNTRY_ACTIVITY_REPORT,
+ EXPORT_GET_MACHINES_PROVINCE_ACTIVITY_REPORT,
+} from "@/core/utils/routes";
+import useRequest from "@/lib/hooks/useRequest";
+import { useTheme } from "@emotion/react";
+import DescriptionIcon from "@mui/icons-material/Description";
+import { Button, CircularProgress, IconButton, useMediaQuery } from "@mui/material";
+import FileSaver from "file-saver";
+import moment from "jalali-moment";
+import { useMemo, useState } from "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) {
+ acc.push({ id: filter.id, 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);
+ const CountryOrProvince = activeFilters.find((item) => item.id === "province_id");
+ const requestUrl =
+ CountryOrProvince.value === "-1"
+ ? EXPORT_GET_MACHINES_COUNTRY_ACTIVITY_REPORT
+ : EXPORT_GET_MACHINES_PROVINCE_ACTIVITY_REPORT;
+ requestServer(`${requestUrl}?${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/roadMissions/reports/machinesReports/MachinesReportsList.jsx b/src/components/dashboard/roadMissions/reports/machinesReports/MachinesReportsList.jsx
new file mode 100644
index 0000000..4eaae92
--- /dev/null
+++ b/src/components/dashboard/roadMissions/reports/machinesReports/MachinesReportsList.jsx
@@ -0,0 +1,78 @@
+"use client";
+import DataTableWithAuth from "@/core/components/DataTableWithAuth";
+import { Box } from "@mui/material";
+import { useMemo } from "react";
+import Toolbar from "./Toolbar";
+
+const MachinesReportsList = ({ data, specialFilter }) => {
+ const columns = useMemo(() => {
+ return [
+ {
+ accessorKey: "machine_id",
+ header: "کد یکتا",
+ id: "machine_id",
+ enableColumnFilter: false,
+ enableSorting: false,
+ datatype: "numeric",
+ grow: false,
+ size: 50,
+ },
+ {
+ accessorKey: "car_name",
+ header: "مدل ماشین",
+ id: "car_name",
+ enableColumnFilter: false,
+ enableSorting: false,
+ datatype: "text",
+ grow: false,
+ size: 50,
+ },
+ {
+ accessorKey: "machine_code",
+ header: "کد ماشین",
+ id: "machine_code",
+ enableColumnFilter: false,
+ enableSorting: false,
+ datatype: "text",
+ grow: false,
+ size: 50,
+ },
+ {
+ accessorKey: "func",
+ header: "کارکرد",
+ id: "func",
+ enableColumnFilter: false,
+ enableSorting: false,
+ datatype: "number",
+ grow: false,
+ size: 50,
+ },
+ {
+ accessorKey: "missions",
+ header: "تعداد ماموریت",
+ id: "missions",
+ enableColumnFilter: false,
+ enableSorting: false,
+ datatype: "number",
+ grow: false,
+ size: 50,
+ },
+ ];
+ }, []);
+
+ return (
+
+
+
+ );
+};
+
+export default MachinesReportsList;
diff --git a/src/components/dashboard/roadMissions/reports/machinesReports/Search/FromDateController.jsx b/src/components/dashboard/roadMissions/reports/machinesReports/Search/FromDateController.jsx
new file mode 100644
index 0000000..490ee7b
--- /dev/null
+++ b/src/components/dashboard/roadMissions/reports/machinesReports/Search/FromDateController.jsx
@@ -0,0 +1,27 @@
+import MuiDatePicker from "@/core/components/MuiDatePicker";
+import moment from "jalali-moment";
+import { Controller } from "react-hook-form";
+
+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/roadMissions/reports/machinesReports/Search/SearchReportField.jsx b/src/components/dashboard/roadMissions/reports/machinesReports/Search/SearchReportField.jsx
new file mode 100644
index 0000000..bde2a4c
--- /dev/null
+++ b/src/components/dashboard/roadMissions/reports/machinesReports/Search/SearchReportField.jsx
@@ -0,0 +1,44 @@
+import SearchIcon from "@mui/icons-material/Search";
+import { Button, Grid } from "@mui/material";
+import { Controller } from "react-hook-form";
+import FromDateController from "./FromDateController";
+import SelectProvince from "./SelectProvince";
+import ToDateController from "./ToDateController";
+
+const SearchReportField = ({ control, hasProvincesPermission }) => {
+ return (
+
+
+
+
+
+
+
+ {hasProvincesPermission && (
+
+
+
+ )}
+
+ (
+ }
+ fullWidth
+ >
+ {isSubmitting ? "درحال دریافت اطلاعات" : "جستجو"}
+
+ )}
+ />
+
+
+ );
+};
+
+export default SearchReportField;
diff --git a/src/components/dashboard/roadMissions/reports/machinesReports/Search/SelectProvince.jsx b/src/components/dashboard/roadMissions/reports/machinesReports/Search/SelectProvince.jsx
new file mode 100644
index 0000000..2b24d67
--- /dev/null
+++ b/src/components/dashboard/roadMissions/reports/machinesReports/Search/SelectProvince.jsx
@@ -0,0 +1,45 @@
+import useProvinces from "@/lib/hooks/useProvince";
+import { FormControl, FormHelperText, InputLabel, MenuItem, Select } from "@mui/material";
+import { Controller } from "react-hook-form";
+
+const SelectProvince = ({ control }) => {
+ const { provinces, loadingProvinces, errorProvinces } = useProvinces();
+ return (
+ (
+
+ استان
+
+ {error && {error.message}}
+
+ )}
+ />
+ );
+};
+export default SelectProvince;
diff --git a/src/components/dashboard/roadMissions/reports/machinesReports/Search/ToDateController.jsx b/src/components/dashboard/roadMissions/reports/machinesReports/Search/ToDateController.jsx
new file mode 100644
index 0000000..fc4a776
--- /dev/null
+++ b/src/components/dashboard/roadMissions/reports/machinesReports/Search/ToDateController.jsx
@@ -0,0 +1,30 @@
+import MuiDatePicker from "@/core/components/MuiDatePicker";
+import moment from "jalali-moment";
+import { Controller, useWatch } from "react-hook-form";
+
+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/roadMissions/reports/machinesReports/Search/index.jsx b/src/components/dashboard/roadMissions/reports/machinesReports/Search/index.jsx
new file mode 100644
index 0000000..f29d302
--- /dev/null
+++ b/src/components/dashboard/roadMissions/reports/machinesReports/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/roadMissions/reports/machinesReports/Toolbar.jsx b/src/components/dashboard/roadMissions/reports/machinesReports/Toolbar.jsx
new file mode 100644
index 0000000..0f726c7
--- /dev/null
+++ b/src/components/dashboard/roadMissions/reports/machinesReports/Toolbar.jsx
@@ -0,0 +1,11 @@
+import { Box } from "@mui/material";
+import PrintExcel from "./ExcelPrint";
+
+const Toolbar = ({ table, filterData, mutate }) => {
+ return (
+
+
+
+ );
+};
+export default Toolbar;
diff --git a/src/components/dashboard/roadMissions/reports/machinesReports/index.jsx b/src/components/dashboard/roadMissions/reports/machinesReports/index.jsx
new file mode 100644
index 0000000..594fdb1
--- /dev/null
+++ b/src/components/dashboard/roadMissions/reports/machinesReports/index.jsx
@@ -0,0 +1,109 @@
+"use client";
+import PageTitle from "@/core/components/PageTitle";
+import { GET_MACHINES_COUNTRY_ACTIVITY_REPORT, GET_MACHINES_PROVINCE_ACTIVITY_REPORT } from "@/core/utils/routes";
+import { useAuth } from "@/lib/contexts/auth";
+import { usePermissions } from "@/lib/hooks/usePermissions";
+import useRequest from "@/lib/hooks/useRequest";
+import { yupResolver } from "@hookform/resolvers/yup";
+import { LinearProgress, Stack } from "@mui/material";
+import moment from "jalali-moment";
+import { useEffect, useState } from "react";
+import { useForm } from "react-hook-form";
+import * as yup from "yup";
+import MachinesReportsList from "./MachinesReportsList";
+import SearchReportList from "./Search";
+
+const MachinesReportsPage = () => {
+ const [data, setData] = useState(null);
+ const { data: userPermissions } = usePermissions();
+ const { user } = useAuth();
+ const requestServer = useRequest();
+ const hasProvincesPermission = userPermissions?.includes("mission-report-country");
+
+ const defaultValues = {
+ from_date: moment(new Date()).format("YYYY-MM-DD"),
+ date_to: moment(new Date()).format("YYYY-MM-DD"),
+ province_id: user.province_id || "-1",
+ };
+ const defaultFilter = [
+ { value: `${defaultValues.province_id}`, datatype: "numeric", id: "province_id", fn: "equals" },
+ { value: `${defaultValues.from_date}`, datatype: "date", id: "from_date", fn: "between" },
+ { value: `${defaultValues.date_to}`, datatype: "date", id: "date_to", fn: "between" },
+ ];
+ const [specialFilter, setSpecialFilter] = useState(defaultFilter);
+
+ const onSearchSubmit = async (data) => {
+ const params = new URLSearchParams();
+ params.set("from_date", `${data.from_date} 00:00:00`);
+ params.set("date_to", `${data.date_to} 23:59:59`);
+ setSpecialFilter([
+ { value: `${data.province_id}`, datatype: "numeric", id: "province_id", fn: "equals" },
+ { value: `${data.from_date}`, datatype: "date", id: "from_date", fn: "between" },
+ { value: `${data.date_to}`, datatype: "date", id: "date_to", fn: "between" },
+ ]);
+ if (data.province_id === "-1") {
+ try {
+ const response = await requestServer(`${GET_MACHINES_COUNTRY_ACTIVITY_REPORT}?${params}`);
+ const result = response.data.data;
+
+ setData({
+ data: result.activities,
+ filters: data,
+ });
+ } catch (e) {}
+ } else {
+ try {
+ params.set("province_id", `${data.province_id}`);
+ const response = await requestServer(`${GET_MACHINES_PROVINCE_ACTIVITY_REPORT}?${params}`);
+
+ const result = response.data.data;
+
+ setData({
+ data: result.activities,
+ filters: data,
+ });
+ } catch (e) {}
+ }
+ };
+
+ useEffect(() => {
+ if (!userPermissions) return;
+ onSearchSubmit(defaultValues);
+ }, [userPermissions]);
+
+ 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: "all",
+ });
+
+ console.log(data);
+
+ return (
+
+
+
+ {!data ? : }
+
+ );
+};
+export default MachinesReportsPage;
diff --git a/src/core/utils/pageMenu.js b/src/core/utils/pageMenu.js
index 99366c4..bd24701 100644
--- a/src/core/utils/pageMenu.js
+++ b/src/core/utils/pageMenu.js
@@ -192,6 +192,15 @@ export const pageMenu = [
badges: [{ key: "mission.request_portal" }],
permissions: ["all"],
},
+ {
+ id: "machinesReports",
+ label: "ماشینها",
+ icon: ,
+ type: "page",
+ route: "/dashboard/road-missions/reports/machinesReports",
+ badges: [{ key: "mission.request_portal" }],
+ permissions: ["all"],
+ },
],
},
],
diff --git a/src/core/utils/pageMenuDev.js b/src/core/utils/pageMenuDev.js
index 4bc0665..ab888c7 100644
--- a/src/core/utils/pageMenuDev.js
+++ b/src/core/utils/pageMenuDev.js
@@ -190,6 +190,15 @@ export const pageMenuDev = [
badges: [{ key: "mission.request_portal" }],
permissions: ["all"],
},
+ {
+ id: "machinesReports",
+ label: "ماشینها",
+ icon: ,
+ type: "page",
+ route: "/dashboard/road-missions/reports/machinesReports",
+ badges: [{ key: "mission.request_portal" }],
+ permissions: ["all"],
+ },
],
},
],
diff --git a/src/core/utils/routes.js b/src/core/utils/routes.js
index c970699..2bac1c4 100644
--- a/src/core/utils/routes.js
+++ b/src/core/utils/routes.js
@@ -247,6 +247,12 @@ export const FINISH_MISSION = api + "/api/v3/missions/control_unit/finish";
export const GET_ROAD_MISSIONS_VIOLATIONS_LIST = api + "/api/v3/missions/violation_management";
export const GET_MISSION_PROVINCE_ACTIVITY_REPORT = api + "/api/v3/missions/report/country_activity";
export const GET_MISSION_CITY_ACTIVITY_REPORT = api + "/api/v3/missions/report/country_activity";
+export const GET_MACHINES_COUNTRY_ACTIVITY_REPORT = api + "/api/v3/missions/report_machine/country_machines_activity";
+export const GET_MACHINES_PROVINCE_ACTIVITY_REPORT = api + "/api/v3/missions/report_machine/province_machines_activity";
+export const EXPORT_GET_MACHINES_COUNTRY_ACTIVITY_REPORT =
+ api + "/api/v3/missions/report_machine/country_machines_activity_excel";
+export const EXPORT_GET_MACHINES_PROVINCE_ACTIVITY_REPORT =
+ api + "/api/v3/missions/report_machine/province_machines_activity_excel";
export const CREATE_VIOLATION = api + "/api/v3/missions/violation_management";
export const EDIT_VIOLATION = api + "/api/v3/missions/violation_management";
export const EXPORT_COUNTRY_ROAD_MISSIONS_REPORTS = api + "/api/v3/missions/report/country_excel_activity";