diff --git a/src/components/dashboard/roadSafety/reports/map/PointsOnMap/DialogInfoItem/ContentInfoItem.jsx b/src/components/dashboard/roadSafety/reports/map/PointsOnMap/DialogInfoItem/ContentInfoItem.jsx index 50957e5..58064a2 100644 --- a/src/components/dashboard/roadSafety/reports/map/PointsOnMap/DialogInfoItem/ContentInfoItem.jsx +++ b/src/components/dashboard/roadSafety/reports/map/PointsOnMap/DialogInfoItem/ContentInfoItem.jsx @@ -63,7 +63,11 @@ const ContentInfoItem = ({ data }) => { )} - + { {data.step == 3 && ( - + { const fetchData = async () => { try { setLoading(true); - const query = buildQueryParams(); + const params = new URLSearchParams(); + const filters = DataTableFilterDataStructure(filterData, isArrayEmpty); + params.set("filters", JSON.stringify(filters || [])); + const query = params.toString(); const response = await requestServer(`${GET_ROAD_SAFETY_REPORT_MAP}?${query}`); const fetchedData = response?.data?.data || []; diff --git a/src/components/dashboard/roadSafety/reports/reportPage/ExcelPrint/index.jsx b/src/components/dashboard/roadSafety/reports/reportPage/ExcelPrint/index.jsx index 192d4fb..8283a74 100644 --- a/src/components/dashboard/roadSafety/reports/reportPage/ExcelPrint/index.jsx +++ b/src/components/dashboard/roadSafety/reports/reportPage/ExcelPrint/index.jsx @@ -7,18 +7,15 @@ import DescriptionIcon from "@mui/icons-material/Description"; import useRequest from "@/lib/hooks/useRequest"; import { useTheme } from "@emotion/react"; import { EXPORT_COUNTRY_ROAD_PATROL_REPORTS, EXPORT_PROVINCE_ROAD_PATROL_REPORTS } from "@/core/utils/routes"; +import isArrayEmpty from "@/core/utils/isArrayEmpty"; +import DataTableFilterDataStructure from "@/core/utils/DataTableFilterDataStructure"; 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 activeFilters = DataTableFilterDataStructure(filterData, isArrayEmpty); const filterParams = useMemo(() => { const params = new URLSearchParams(); @@ -33,7 +30,7 @@ const PrintExcel = ({ table, filterData }) => { setLoading(true); const CountryOrProvince = activeFilters.find((item) => item.id === "province_id"); const requestUrl = - CountryOrProvince.value === "-1" ? EXPORT_COUNTRY_ROAD_PATROL_REPORTS : EXPORT_PROVINCE_ROAD_PATROL_REPORTS; + CountryOrProvince.value === "" ? EXPORT_COUNTRY_ROAD_PATROL_REPORTS : EXPORT_PROVINCE_ROAD_PATROL_REPORTS; requestServer(`${requestUrl}?${filterParams}`, "get", { requestOptions: { responseType: "blob" }, }) diff --git a/src/components/dashboard/roadSafety/reports/reportPage/ReportLists.jsx b/src/components/dashboard/roadSafety/reports/reportPage/ReportLists.jsx index 9d64db2..cb0e8b7 100644 --- a/src/components/dashboard/roadSafety/reports/reportPage/ReportLists.jsx +++ b/src/components/dashboard/roadSafety/reports/reportPage/ReportLists.jsx @@ -4,7 +4,7 @@ import { Box } from "@mui/material"; import { useMemo } from "react"; import Toolbar from "./Toolbar"; -const ReportLists = ({ data, specialFilter }) => { +const ReportLists = ({ data, filterData, setFilterData, isLoading }) => { const columns = useMemo(() => { return [ { @@ -289,11 +289,13 @@ const ReportLists = ({ data, specialFilter }) => { ); diff --git a/src/components/dashboard/roadSafety/reports/reportPage/index.jsx b/src/components/dashboard/roadSafety/reports/reportPage/index.jsx index cafa140..eca67ce 100644 --- a/src/components/dashboard/roadSafety/reports/reportPage/index.jsx +++ b/src/components/dashboard/roadSafety/reports/reportPage/index.jsx @@ -1,141 +1,247 @@ "use client"; +import CustomSelectByDependency from "@/core/components/FilterDrawer/fieldsType/CustomSelectByDependency"; 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 DataTableFilterDataStructure from "@/core/utils/DataTableFilterDataStructure"; +import isArrayEmpty from "@/core/utils/isArrayEmpty"; import { GET_ROAD_SAFETY_CITY_ACTIVITY_REPORT, GET_ROAD_SAFETY_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"; +import useProvinces from "@/lib/hooks/useProvince"; +import useRequest from "@/lib/hooks/useRequest"; +import useSafetyAndPrivacyGetItems from "@/lib/hooks/useSafetyAndPrivacyGetItems"; +import { Box, LinearProgress, Stack } from "@mui/material"; +import { useEffect, useMemo, useState } from "react"; +import ReportLists from "./ReportLists"; + +const statusOptions = [ + { value: "", label: "همه وضعیت ها" }, + { value: 1, label: "گام اول (شناسایی)" }, + { value: 2, label: "گام دوم (مستندات قضایی)" }, + { value: 3, label: "گام سوم (برخورد)" }, +]; +const axisOptions = [ + { value: "", label: "همه محور ها" }, + { value: 1, label: "آزادراه" }, + { value: 2, label: "بزرگراه" }, + { value: 3, label: "اصلی" }, + { value: 4, label: "فرعی" }, + { value: 5, label: "روستایی" }, +]; const ReportPage = () => { - const [data, setData] = useState(null); const { data: userPermissions } = usePermissions(); - const { user } = useAuth(); - const requestServer = useRequest(); const hasProvincesPermission = userPermissions.includes("show-safety-and-privacy-operator-cartable"); + const requestServer = useRequest(); + const [data, setData] = useState(null); + const [isLoading, setLoading] = useState(true); - 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, - axis_type_id: "-1", - }; - const defaultFilter = [ - { value: `${defaultValues.province_id}`, datatype: "numeric", id: "province_id", fn: "equals" }, - { value: `${defaultValues.axis_type_id}`, datatype: "numeric", id: "axis_type_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 defaultValues = useMemo(() => { + const provinceFilter = { + header: "استان", + id: "province_id", + filterMode: "equals", + datatype: "numeric", + value: "", + SelectComponent: (props) => { + const { provinces, errorProvinces, loadingProvinces } = useProvinces(); + const getSelectOptions = useMemo(() => { + if (loadingProvinces) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorProvinces) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: "کل کشور" }, + ...provinces.map((province) => ({ + value: province.id, + label: province.name_fa, + })), + ]; + }, [provinces, errorProvinces, loadingProvinces]); + return ( + + ); + }, + }; - const onSearchSubmit = async (data) => { - const params = new URLSearchParams(); - params.set("from_date", `${data.from_date}`); - params.set("date_to", `${data.date_to}`); - if (data.axis_type_id != "-1") params.set("axis_type_id", `${data.axis_type_id}`); + return [ + ...(hasProvincesPermission ? [provinceFilter] : []), + { + header: "مورد مشاهده شده", + id: "info_id", + filterMode: "equals", + datatype: "numeric", + value: "", + SelectComponent: (props) => { + const { itemsList, loadingItemsList, errorItemsList } = useSafetyAndPrivacyGetItems(); - setSpecialFilter([ - { value: `${data.province_id}`, datatype: "numeric", id: "province_id", fn: "equals" }, - { value: `${data.axis_type_id}`, datatype: "numeric", id: "axis_type_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_ROAD_SAFETY_PROVINCE_ACTIVITY_REPORT}?${params}`); - const result = response.data.data; - const nationalReportForItem = result.activities.find((report) => report.province_id === -1); - const nationalReport = { - edare_name: "کل کشور", - ...nationalReportForItem, - }; + const getSelectOptions = useMemo(() => { + if (loadingItemsList) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorItemsList) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: "همه موارد" }, + ...itemsList.map((item) => ({ + value: item.id, + label: item.name, + })), + ]; + }, [itemsList, loadingItemsList, errorItemsList]); - 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_ROAD_SAFETY_CITY_ACTIVITY_REPORT}?${params}`); - const result = response.data.data; - const nationalReportForItem = result.activities.find((report) => report.edare_shahri_id == "-1"); - const nationalReport = { - ...nationalReportForItem, - edare_name: "کل استان", - }; - setData({ - data: [ - nationalReport, - ...result.edarateShahri.map((edare) => { - const filteredReports = result.activities.find( - (report) => report.edare_shahri_id == edare.id - ); - return { - edare_name: edare.name_fa, - ...filteredReports, - }; - }), - ], - filters: data, - }); - } catch (e) {} - } - }; + return ( + + ); + }, + }, + { + header: "نوع محور", + id: "axis_type_id", + filterMode: "equals", + datatype: "numeric", + value: "", + selectOption: () => { + return axisOptions.map((status) => ({ + value: status.value, + label: status.label, + })); + }, + }, + { + header: "وضعیت", + id: "step", + filterMode: "equals", + datatype: "numeric", + value: "", + selectOption: () => { + return statusOptions.map((status) => ({ + value: status.value, + label: status.label, + })); + }, + }, + { + header: "تاریخ ثبت", + id: "created_at", + filterMode: "between", + datatype: "date", + value: ["", ""], + }, + { + header: "تاریخ بازدید", + id: "activity_date_time", + filterMode: "between", + datatype: "date", + value: ["", ""], + }, + { + header: "تاریخ بارگذاری مستندات", + id: "judiciary_document_upload_date", + filterMode: "between", + datatype: "date", + value: ["", ""], + }, + { + header: "تاریخ اقدام", + id: "action_date", + filterMode: "between", + datatype: "date", + value: ["", ""], + }, + ]; + }, []); + const [filterData, setFilterData] = useState( + defaultValues.reduce((acc, item) => { + acc[item.id] = item; + return acc; + }, {}) + ); useEffect(() => { - if (!userPermissions) return; - onSearchSubmit(defaultValues); - }, [userPermissions]); + const fetchData = async () => { + try { + setLoading(true); + const params = new URLSearchParams(); + const filters = DataTableFilterDataStructure(filterData, isArrayEmpty); + params.set("filters", JSON.stringify(filters || [])); + const query = params.toString(); + const province_id = filterData.province_id.value; + if (province_id === "") { + try { + const response = await requestServer(`${GET_ROAD_SAFETY_PROVINCE_ACTIVITY_REPORT}?${query}`); + const result = response.data.data; + const nationalReportForItem = result.activities.find((report) => report.province_id === -1); + const nationalReport = { + edare_name: "کل کشور", + ...nationalReportForItem, + }; - 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(), - axis_type_id: yup.string().nullable(), - }); + setData([ + nationalReport, + ...result.provinces.map((province) => { + const filteredReports = result.activities.find( + (report) => report.province_id === province.id + ); + return { + ...filteredReports, + edare_name: province.name_fa, + }; + }), + ]); + } catch (e) { } + } else { + try { + const response = await requestServer(`${GET_ROAD_SAFETY_CITY_ACTIVITY_REPORT}?${params}`); + const result = response.data.data; + const nationalReportForItem = result.activities.find( + (report) => report.edare_shahri_id == "-1" + ); + const nationalReport = { + ...nationalReportForItem, + edare_name: "کل استان", + }; + setData([ + nationalReport, + ...result.edarateShahri.map((edare) => { + const filteredReports = result.activities.find( + (report) => report.edare_shahri_id == edare.id + ); + return { + edare_name: edare.name_fa, + ...filteredReports, + }; + }), + ]); + } catch (e) { } + } + } catch (error) { + console.log(error); + } finally { + setLoading(false); + } + }; + + fetchData(); + }, [filterData]); - const { control, handleSubmit } = useForm({ - defaultValues, - resolver: yupResolver(validationSchema), - mode: "onBlur", - }); return ( - - {!data ? : } + {!data ? ( + + ) : ( + + )} ); }; diff --git a/src/core/components/DataTable/Main.js b/src/core/components/DataTable/Main.js index efad5a0..ef2d81a 100644 --- a/src/core/components/DataTable/Main.js +++ b/src/core/components/DataTable/Main.js @@ -113,7 +113,7 @@ const DataTable_Main = (props) => { ...initialStateProps, }, state: { - showProgressBars: isValidating, + showProgressBars: isValidating || props.loading, columnVisibility: flattenHideData, sorting: sortData, pagination, @@ -171,6 +171,8 @@ const DataTable_Main = (props) => { page_name={page_name} table_name={table_name} special_data={props.data} + special_filter={specialFilter} + setFilterData={props.setFilterData} /> ); }; diff --git a/src/core/components/DataTable/filter/FilterCustom.jsx b/src/core/components/DataTable/filter/FilterCustom.jsx new file mode 100644 index 0000000..f8d43f3 --- /dev/null +++ b/src/core/components/DataTable/filter/FilterCustom.jsx @@ -0,0 +1,32 @@ +import { useCallback, useState } from "react"; +import FilterButton from "./FilterButton"; +import { Box, Drawer } from "@mui/material"; +import FilterDrawer from "../../FilterDrawer"; + +const FilterCustom = ({ filterData, setFilterData }) => { + const [open, setOpen] = useState(false); + + const closeDrawer = useCallback(() => setOpen(false), []); + + return ( + <> + + setOpen(false)} + sx={{ overflowY: "hidden", display: "flex", flexDirection: "column", height: "100%", zIndex: "1300" }} + > + + {open && ( + + )} + + + + ); +}; +export default FilterCustom; diff --git a/src/core/components/DataTable/table/Paper.js b/src/core/components/DataTable/table/Paper.js index 14665a3..9ce08fc 100644 --- a/src/core/components/DataTable/table/Paper.js +++ b/src/core/components/DataTable/table/Paper.js @@ -14,6 +14,7 @@ const DataTable_Paper = ({ need_filter, table_url, table_title, + setFilterData, ...rest }) => { const { @@ -86,6 +87,7 @@ const DataTable_Paper = ({ page_name={page_name} table_name={table_name} table_title={table_title} + setFilterData={setFilterData} {...paperProps} /> ))} diff --git a/src/core/components/DataTable/toolbar/TopToolbar.js b/src/core/components/DataTable/toolbar/TopToolbar.js index 2c322ff..ea0c6d0 100644 --- a/src/core/components/DataTable/toolbar/TopToolbar.js +++ b/src/core/components/DataTable/toolbar/TopToolbar.js @@ -6,6 +6,7 @@ import FilterColumn from "@/core/components/DataTable/filter"; import UpdateTable from "@/core/components/DataTable/update/UpdateTable"; import ResetStorage from "@/core/components/DataTable/reset/ResetStorage"; import HideColumn from "@/core/components/DataTable/hide"; +import FilterCustom from "../filter/FilterCustom"; const DataTable_TopToolbar = ({ mutate, @@ -18,6 +19,8 @@ const DataTable_TopToolbar = ({ table_name, table_title, special_data, + special_filter, + setFilterData, }) => { const { getState, @@ -118,6 +121,9 @@ const DataTable_TopToolbar = ({ table_name={table_name} /> )} + {special_filter && setFilterData && ( + + )} )} diff --git a/src/core/utils/DataTableFilterDataStructure.js b/src/core/utils/DataTableFilterDataStructure.js index c88bdfc..43f1144 100644 --- a/src/core/utils/DataTableFilterDataStructure.js +++ b/src/core/utils/DataTableFilterDataStructure.js @@ -1,9 +1,10 @@ export default function DataTableFilterDataStructure(filterData, isValueEmpty) { return Object.values(filterData) .filter((filter) => !isValueEmpty(filter.value)) - .map(({ filterMode, id, ...rest }) => ({ - ...rest, + .map(({ filterMode, id, datatype, value }) => ({ id: id.replace(/__/g, "."), fn: filterMode, + datatype, + value, })); }