Merge branch 'feature/excel_print' into 'develop'

Feature/excel print

See merge request witel-front-end/rms!61
This commit is contained in:
AmirHossein Mahmoodi
2025-02-11 07:52:38 +00:00
32 changed files with 373 additions and 135 deletions

View File

@@ -7,6 +7,8 @@ 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";
import DataTableFilterDataStructure from "@/core/utils/DataTableFilterDataStructure";
import isArrayEmpty from "@/core/utils/isArrayEmpty";
const PrintExcel = ({ table, filterData }) => {
const theme = useTheme();
@@ -14,8 +16,7 @@ const PrintExcel = ({ table, filterData }) => {
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
if (filter.value && (!Array.isArray(filter.value) || filter.value.some((item) => item.trim() !== ""))) {
acc.push({ id: key, value: filter.value });
}
return acc;
@@ -23,10 +24,14 @@ const PrintExcel = ({ table, filterData }) => {
const filterParams = useMemo(() => {
const params = new URLSearchParams();
activeFilters.length > 0 &&
if (activeFilters.length > 0) {
activeFilters.map((filter, index) => {
params.set(`${filter.id}`, filter.value);
const filteredFilterData = DataTableFilterDataStructure(filterData, isArrayEmpty);
params.set("filters", JSON.stringify(filteredFilterData.length === 0 ? [] : filteredFilterData));
});
} else {
params.set("filters", JSON.stringify([]));
}
return params;
}, [activeFilters]);
@@ -36,7 +41,7 @@ const PrintExcel = ({ table, filterData }) => {
requestOptions: { responseType: "blob" },
})
.then((response) => {
const filename = `خروجی کارتابل فعالیت روزانه تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`;
const filename = `خروجی کارتابل عملیات فعالیت روزانه تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`;
FileSaver.saveAs(response.data, filename);
})
.catch(() => {})

View File

@@ -6,7 +6,7 @@ import ObservedGashtCreate from "./Actions/ObservedGashtCreate";
const Toolbar = ({ table, filterData, mutate }) => {
return (
<Stack direction={"row"} spacing={2}>
{/*<PrintExcel table={table} filterData={filterData} />*/}
<PrintExcel table={table} filterData={filterData} />
<OperatorCreate mutate={mutate} />
<ObservedGashtCreate mutate={mutate} />
</Stack>

View File

@@ -5,7 +5,10 @@ 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 {
EXPORT_COUNTRY_ROAD_ITEM_REPORTS_PER_ITEM,
EXPORT_PROVINCE_ROAD_ITEM_REPORTS_PER_ITEM,
} from "@/core/utils/routes";
import { useTheme } from "@emotion/react";
const PrintExcel = ({ table, filterData }) => {
@@ -15,8 +18,7 @@ const PrintExcel = ({ table, filterData }) => {
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 });
acc.push({ id: filter.id, value: filter.value });
}
return acc;
}, []);
@@ -32,11 +34,17 @@ const PrintExcel = ({ table, filterData }) => {
const clickHandler = () => {
setLoading(true);
requestServer(`${EXPORT_ROAD_ITEMS_OPERATOR_LIST}?${filterParams}`, "get", {
const CountryOrProvince = activeFilters.find((item) => item.id === "province_id");
const requestUrl =
CountryOrProvince.value === "-1"
? EXPORT_COUNTRY_ROAD_ITEM_REPORTS_PER_ITEM
: EXPORT_PROVINCE_ROAD_ITEM_REPORTS_PER_ITEM;
requestServer(`${requestUrl}?${filterParams}`, "get", {
requestOptions: { responseType: "blob" },
})
.then((response) => {
const filename = `خروجی کارتابل گزارشات فعالیت روزانه تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`;
const filename = `خروجی کارتابل گزارشات فعالیت روزانه براساس ایتم تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`;
FileSaver.saveAs(response.data, filename);
})
.catch(() => {})

View File

@@ -2,8 +2,9 @@
import DataTableWithAuth from "@/core/components/DataTableWithAuth";
import { Box } from "@mui/material";
import { useMemo } from "react";
import Toolbar from "./TableToolbar";
const ReportLists = ({ itemsList, data }) => {
const ReportLists = ({ itemsList, data, specialFilter }) => {
const columns = useMemo(() => {
const dynamicColumns =
itemsList?.map((item) => ({
@@ -85,6 +86,8 @@ const ReportLists = ({ itemsList, data }) => {
page_name={"roadItemReportByItems"}
table_name={"roadItemReportByItemsList"}
enablePagination={false}
TableToolbar={Toolbar}
specialFilter={specialFilter}
/>
</Box>
);

View File

@@ -0,0 +1,10 @@
import PrintExcel from "./ExcelPrint";
const Toolbar = ({ table, filterData }) => {
return (
<>
<PrintExcel table={table} filterData={filterData} />
</>
);
};
export default Toolbar;

View File

@@ -18,6 +18,7 @@ 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");
@@ -27,11 +28,22 @@ const ReportPage = () => {
date_to: moment(new Date()).format("YYYY-MM-DD"),
province_id: hasProvincesPermission ? "-1" : user.province_id,
};
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}`);
params.set("date_to", `${data.date_to}`);
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_PROVINCE_ACTIVITY_PER_ITEM}?${params}`);
@@ -158,7 +170,7 @@ const ReportPage = () => {
خطا در دریافت اطلاعات!!!
</Typography>
) : (
<ReportLists data={data} itemsList={itemsList} />
<ReportLists specialFilter={specialFilter} data={data} itemsList={itemsList} />
)}
</Stack>
);

View File

@@ -0,0 +1,77 @@
"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 { useTheme } from "@emotion/react";
import {
EXPORT_COUNTRY_ROAD_ITEM_REPORTS_PER_SUB_ITEM,
EXPORT_PROVINCE_ROAD_ITEM_REPORTS_PER_SUB_ITEM,
} from "@/core/utils/routes";
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_COUNTRY_ROAD_ITEM_REPORTS_PER_SUB_ITEM
: EXPORT_PROVINCE_ROAD_ITEM_REPORTS_PER_SUB_ITEM;
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 ? (
<IconButton aria-label="خروجی اکسل" color="primary" onClick={clickHandler}>
<DescriptionIcon sx={{ fontSize: "25px" }} />
</IconButton>
) : (
<Button
color="primary"
variant="contained"
size="small"
disabled={loading}
sx={{ textTransform: "unset", alignSelf: "center" }}
startIcon={loading ? <CircularProgress size={18} color="inherit" /> : <DescriptionIcon />}
onClick={clickHandler}
>
خروجی اکسل
</Button>
)}
</>
);
};
export default PrintExcel;

View File

@@ -1,7 +1,8 @@
import DataTableWithAuth from "@/core/components/DataTableWithAuth";
import { Box } from "@mui/material";
import Toolbar from "./TableToolbar";
const SubItemsList = ({ data }) => {
const SubItemsList = ({ data, specialFilter }) => {
return (
<Box sx={{ p: 1, border: 1, borderColor: "divider", borderRadius: 1 }}>
<DataTableWithAuth
@@ -10,6 +11,8 @@ const SubItemsList = ({ data }) => {
page_name={"roadItemReportBySubItems"}
table_name={"roadItemReportBySubItemsList"}
enablePagination={false}
TableToolbar={Toolbar}
specialFilter={specialFilter}
/>
</Box>
);

View File

@@ -0,0 +1,10 @@
import PrintExcel from "./ExcelPrint";
const Toolbar = ({ table, filterData }) => {
return (
<>
<PrintExcel table={table} filterData={filterData} />
</>
);
};
export default Toolbar;

View File

@@ -106,12 +106,25 @@ const SubItemsReports = () => {
province_id: hasProvincesPermission ? "-1" : user.province_id,
item: 1,
};
const defaultFilter = [
{ value: `${defaultValues.province_id}`, datatype: "numeric", id: "province_id", fn: "equals" },
{ value: `${defaultValues.item}`, datatype: "numeric", id: "item", 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}`);
params.set("date_to", `${data.date_to}`);
params.set("item", `${data.item}`);
setSpecialFilter([
{ value: `${data.province_id}`, datatype: "numeric", id: "province_id", fn: "equals" },
{ value: `${data.item}`, datatype: "numeric", id: "item", 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_PROVINCE_ACTIVITY_PER_SUB_ITEM}?${params}`);
@@ -235,7 +248,7 @@ const SubItemsReports = () => {
handleSubmit={handleSubmit}
onSearchSubmit={onSearchSubmit}
/>
{!data ? <LinearProgress /> : <SubItemsList data={data} />}
{!data ? <LinearProgress /> : <SubItemsList specialFilter={specialFilter} data={data} />}
</Stack>
);
};

View File

@@ -6,6 +6,8 @@ import DescriptionIcon from "@mui/icons-material/Description";
import useRequest from "@/lib/hooks/useRequest";
import { EXPORT_ROAD_ITEMS_SUPERVISOR_LIST } from "@/core/utils/routes";
import { useTheme } from "@emotion/react";
import DataTableFilterDataStructure from "@/core/utils/DataTableFilterDataStructure";
import isArrayEmpty from "@/core/utils/isArrayEmpty";
const PrintExcel = ({ table, filterData }) => {
const [loading, setLoading] = useState(false);
@@ -13,8 +15,7 @@ const PrintExcel = ({ table, filterData }) => {
const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
const requestServer = useRequest();
const activeFilters = Object.entries(filterData).reduce((acc, [key, filter]) => {
if (filter.value) {
// Check if there's an active filter
if (filter.value && (!Array.isArray(filter.value) || filter.value.some((item) => item.trim() !== ""))) {
acc.push({ id: key, value: filter.value });
}
return acc;
@@ -22,20 +23,23 @@ const PrintExcel = ({ table, filterData }) => {
const filterParams = useMemo(() => {
const params = new URLSearchParams();
activeFilters.length > 0 &&
if (activeFilters.length > 0) {
activeFilters.map((filter, index) => {
params.set(`${filter.id}`, filter.value);
const filteredFilterData = DataTableFilterDataStructure(filterData, isArrayEmpty);
params.set("filters", JSON.stringify(filteredFilterData.length === 0 ? [] : filteredFilterData));
});
} else {
params.set("filters", JSON.stringify([]));
}
return params;
}, [activeFilters]);
const clickHandler = () => {
setLoading(true);
requestServer(`${EXPORT_ROAD_ITEMS_SUPERVISOR_LIST}?${filterParams}`, "get", {
requestOptions: { responseType: "blob" },
})
.then((response) => {
const filename = `خروجی کارتابل فعالیت روزانه تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`;
const filename = `خروجی کارتابل ارزیابی فعالیت روزانه تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`;
FileSaver.saveAs(response.data, filename);
})
.catch(() => {})

View File

@@ -1,6 +1,10 @@
import PrintExcel from "./ExcelPrint";
const Toolbar = ({ table, filterData }) => {
return <>{/*<PrintExcel table={table} filterData={filterData} />*/}</>;
return (
<>
<PrintExcel table={table} filterData={filterData} />
</>
);
};
export default Toolbar;

View File

@@ -22,7 +22,7 @@ const OperatorCreate = ({ mutate }) => {
<AddCircle sx={{ fontSize: "25px" }} />
</IconButton>
) : (
<Button variant="contained" color="primary" startIcon={<AddCircle />} onClick={handleOpen}>
<Button size="small" variant="contained" color="primary" startIcon={<AddCircle />} onClick={handleOpen}>
ثبت اقدام
</Button>
)}

View File

@@ -1,17 +1,21 @@
import { Button, CircularProgress } from "@mui/material";
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_PATROL_OPERATOR_LIST } from "@/core/utils/routes";
import DataTableFilterDataStructure from "@/core/utils/DataTableFilterDataStructure";
import isArrayEmpty from "@/core/utils/isArrayEmpty";
import { useTheme } from "@emotion/react";
const PrintExcel = ({ table, filterData }) => {
const [loading, setLoading] = useState(false);
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
const requestServer = useRequest();
const activeFilters = Object.entries(filterData).reduce((acc, [key, filter]) => {
if (filter.value) {
// Check if there's an active filter
if (filter.value && (!Array.isArray(filter.value) || filter.value.some((item) => item.trim() !== ""))) {
acc.push({ id: key, value: filter.value });
}
return acc;
@@ -19,10 +23,14 @@ const PrintExcel = ({ table, filterData }) => {
const filterParams = useMemo(() => {
const params = new URLSearchParams();
activeFilters.length > 0 &&
if (activeFilters.length > 0) {
activeFilters.map((filter, index) => {
params.set(`${filter.id}`, filter.value);
const filteredFilterData = DataTableFilterDataStructure(filterData, isArrayEmpty);
params.set("filters", JSON.stringify(filteredFilterData.length === 0 ? [] : filteredFilterData));
});
} else {
params.set("filters", JSON.stringify([]));
}
return params;
}, [activeFilters]);
@@ -32,7 +40,7 @@ const PrintExcel = ({ table, filterData }) => {
requestOptions: { responseType: "blob" },
})
.then((response) => {
const filename = `خروجی کارتابل عملیات تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`;
const filename = `خروجی کارتابل عملیات گشت راهداری تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`;
FileSaver.saveAs(response.data, filename);
})
.catch(() => {})
@@ -42,16 +50,25 @@ const PrintExcel = ({ table, filterData }) => {
};
return (
<Button
color="primary"
variant="contained"
disabled={loading}
sx={{ textTransform: "unset", alignSelf: "center" }}
startIcon={loading ? <CircularProgress size={18} color="inherit" /> : <DescriptionIcon />}
onClick={clickHandler}
>
خروجی اکسل
</Button>
<>
{isMobile ? (
<IconButton aria-label="خروجی اکسل" color="primary" onClick={clickHandler}>
<DescriptionIcon sx={{ fontSize: "25px" }} />
</IconButton>
) : (
<Button
color="primary"
variant="contained"
size="small"
disabled={loading}
sx={{ textTransform: "unset", alignSelf: "center" }}
startIcon={loading ? <CircularProgress size={18} color="inherit" /> : <DescriptionIcon />}
onClick={clickHandler}
>
خروجی اکسل
</Button>
)}
</>
);
};

View File

@@ -92,7 +92,7 @@ const CompeleteRequest = ({ allData, handlePrev, mutate, setOpen }) => {
setOtpSended(true);
setDelayPerRequest(true);
setValueSend("phoneNumber", data.phoneNumber);
} catch (error) { }
} catch (error) {}
};
const sendData = useCallback(
@@ -287,8 +287,8 @@ const CompeleteRequest = ({ allData, handlePrev, mutate, setOpen }) => {
{delayPerRequest
? formatCounter(counter)
: isSubmittingOtp
? "درحال دریافت کد ..."
: "دریافت کد"}
? "درحال دریافت کد ..."
: "دریافت کد"}
</Button>
</Box>
</StyledForm>

View File

@@ -4,7 +4,7 @@ import MapLoading from "@/core/components/MapLayer/Loading";
import ShowPlak from "@/core/components/ShowPlak";
import { formatSecondsToHHMMSS } from "@/core/utils/formatSecondsToHHMMSS";
import AddRoadIcon from "@mui/icons-material/AddRoad";
import BadgeIcon from '@mui/icons-material/Badge';
import BadgeIcon from "@mui/icons-material/Badge";
import DirectionsCarFilledIcon from "@mui/icons-material/DirectionsCarFilled";
import ElectricCarIcon from "@mui/icons-material/ElectricCar";
import LocalGasStationIcon from "@mui/icons-material/LocalGasStation";
@@ -12,16 +12,7 @@ import QrCode2Icon from "@mui/icons-material/QrCode2";
import QueryBuilderIcon from "@mui/icons-material/QueryBuilder";
import ShareLocationIcon from "@mui/icons-material/ShareLocation";
import WatchLaterIcon from "@mui/icons-material/WatchLater";
import {
Box,
Card,
CardContent,
Chip,
Divider,
Fade,
Stack,
Typography
} from "@mui/material";
import { Box, Card, CardContent, Chip, Divider, Fade, Stack, Typography } from "@mui/material";
import moment from "jalali-moment";
import dynamic from "next/dynamic";
import React, { useEffect } from "react";

View File

@@ -44,7 +44,7 @@ const MachinePerformanceContent = ({ machinesLists }) => {
return (
<>
<DialogContent>
<Stack direction={"row"} spacing={4} justifyContent={"space-between"} alignItems={'center'}>
<Stack direction={"row"} spacing={4} justifyContent={"space-between"} alignItems={"center"}>
<StopsInfo
staticData={{
cmmsMachineCode: machinesLists.cmms_machine_code,
@@ -89,7 +89,12 @@ const MachinePerformanceContent = ({ machinesLists }) => {
</Box>
</Box>
</Stack>
<Grid container spacing={1} direction="row" sx={{ flex: 1, justifyContent: "space-between", alignItems: "center", mt: 2 }}>
<Grid
container
spacing={1}
direction="row"
sx={{ flex: 1, justifyContent: "space-between", alignItems: "center", mt: 2 }}
>
<Grid item xs={12} sm={12} sx={{ display: "flex", alignItems: "center" }}>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Chip

View File

@@ -5,13 +5,18 @@ import LocalGasStationIcon from "@mui/icons-material/LocalGasStation";
import QrCode2Icon from "@mui/icons-material/QrCode2";
import AddRoadIcon from "@mui/icons-material/AddRoad";
import DirectionsCarFilledIcon from "@mui/icons-material/DirectionsCarFilled";
import BadgeIcon from '@mui/icons-material/Badge';
import BadgeIcon from "@mui/icons-material/Badge";
import { formatSecondsToHHMMSS } from "@/core/utils/formatSecondsToHHMMSS";
import ShowPlak from "@/core/components/ShowPlak";
const StopsInfo = ({ staticData }) => {
return (
<Grid container spacing={3} direction="row" sx={{ flex: 1, justifyContent: "space-between", alignItems: "center" }}>
<Grid
container
spacing={3}
direction="row"
sx={{ flex: 1, justifyContent: "space-between", alignItems: "center" }}
>
<Grid item xs={12} sm={12} sx={{ display: "flex", alignItems: "center" }}>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Chip

View File

@@ -6,7 +6,7 @@ const Toolbar = ({ table, filterData, mutate }) => {
return (
<Box sx={{ display: "flex", gap: 1 }}>
<OperatorCreate table={table} mutate={mutate} />
{/*<PrintExcel table={table} filterData={filterData} />*/}
<PrintExcel table={table} filterData={filterData} />
</Box>
);
};

View File

@@ -1,16 +1,21 @@
import { Button, CircularProgress } from "@mui/material";
"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 { useTheme } from "@emotion/react";
import { EXPORT_COUNTRY_ROAD_PATROL_REPORTS, EXPORT_PROVINCE_ROAD_PATROL_REPORTS } from "@/core/utils/routes";
const PrintExcel = ({ table, filterData }) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
const [loading, setLoading] = useState(false);
const requestServer = useRequest();
const requestServer = useRequest({ notificationSuccess: true });
const activeFilters = Object.entries(filterData).reduce((acc, [key, filter]) => {
if (filter) {
acc.push({ id: key, value: filter });
if (filter.value) {
acc.push({ id: filter.id, value: filter.value });
}
return acc;
}, []);
@@ -25,31 +30,43 @@ const PrintExcel = ({ table, filterData }) => {
}, [activeFilters]);
const clickHandler = () => {
// setLoading(true);
// requestServer(`${EXPORT_ROAD_PATROL_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);
// });
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;
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 (
<Button
color="primary"
variant="contained"
disabled={loading}
sx={{ textTransform: "unset", alignSelf: "center" }}
startIcon={loading ? <CircularProgress size={18} color="inherit" /> : <DescriptionIcon />}
onClick={clickHandler}
>
خروجی اکسل
</Button>
<>
{isMobile ? (
<IconButton aria-label="خروجی اکسل" color="primary" onClick={clickHandler}>
<DescriptionIcon sx={{ fontSize: "25px" }} />
</IconButton>
) : (
<Button
color="primary"
variant="contained"
size="small"
disabled={loading}
sx={{ textTransform: "unset", alignSelf: "center" }}
startIcon={loading ? <CircularProgress size={18} color="inherit" /> : <DescriptionIcon />}
onClick={clickHandler}
>
خروجی اکسل
</Button>
)}
</>
);
};
export default PrintExcel;

View File

@@ -4,7 +4,7 @@ import { Box } from "@mui/material";
import { useMemo } from "react";
import Toolbar from "./Toolbar";
const ReportLists = ({ data }) => {
const ReportLists = ({ data, specialFilter }) => {
const columns = useMemo(() => {
return [
{
@@ -195,12 +195,12 @@ const ReportLists = ({ data }) => {
return (
<Box sx={{ p: 1, border: 1, borderColor: "divider", borderRadius: 1 }}>
<DataTableWithAuth
specialFilter={data.filters}
TableToolbar={Toolbar}
columns={columns}
data={data.data}
page_name={"roadPatrolReport"}
table_name={"roadPatrolReportList"}
specialFilter={specialFilter}
/>
</Box>
);

View File

@@ -2,6 +2,10 @@ import PrintExcel from "./ExcelPrint";
import { Box } from "@mui/material";
const Toolbar = ({ table, filterData, mutate }) => {
return <Box sx={{ display: "flex", gap: 1 }}>{/*<PrintExcel table={table} filterData={filterData} />*/}</Box>;
return (
<Box sx={{ display: "flex", gap: 1 }}>
<PrintExcel table={table} filterData={filterData} />
</Box>
);
};
export default Toolbar;

View File

@@ -25,11 +25,22 @@ const ReportPage = () => {
date_to: moment(new Date()).format("YYYY-MM-DD"),
province_id: hasProvincesPermission ? "-1" : user.province_id,
};
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}`);
params.set("date_to", `${data.date_to}`);
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_PROVINCE_ACTIVITY_REPORT}?${params}`);
@@ -115,7 +126,7 @@ const ReportPage = () => {
handleSubmit={handleSubmit}
onSearchSubmit={onSearchSubmit}
/>
{!data ? <LinearProgress /> : <ReportLists data={data} />}
{!data ? <LinearProgress /> : <ReportLists specialFilter={specialFilter} data={data} />}
</Stack>
);
};

View File

@@ -1,17 +1,21 @@
import { Button, CircularProgress } from "@mui/material";
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_PATROL_SUPERVISOR_LIST } from "@/core/utils/routes";
import DataTableFilterDataStructure from "@/core/utils/DataTableFilterDataStructure";
import isArrayEmpty from "@/core/utils/isArrayEmpty";
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();
const activeFilters = Object.entries(filterData).reduce((acc, [key, filter]) => {
if (filter.value) {
// Check if there's an active filter
if (filter.value && (!Array.isArray(filter.value) || filter.value.some((item) => item.trim() !== ""))) {
acc.push({ id: key, value: filter.value });
}
return acc;
@@ -19,10 +23,14 @@ const PrintExcel = ({ table, filterData }) => {
const filterParams = useMemo(() => {
const params = new URLSearchParams();
activeFilters.length > 0 &&
if (activeFilters.length > 0) {
activeFilters.map((filter, index) => {
params.set(`${filter.id}`, filter.value);
const filteredFilterData = DataTableFilterDataStructure(filterData, isArrayEmpty);
params.set("filters", JSON.stringify(filteredFilterData.length === 0 ? [] : filteredFilterData));
});
} else {
params.set("filters", JSON.stringify([]));
}
return params;
}, [activeFilters]);
@@ -32,7 +40,7 @@ const PrintExcel = ({ table, filterData }) => {
requestOptions: { responseType: "blob" },
})
.then((response) => {
const filename = `خروجی کارتابل ارزیابی تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`;
const filename = `خروجی کارتابل ارزیابی گشت راهداری تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`;
FileSaver.saveAs(response.data, filename);
})
.catch(() => {})
@@ -42,17 +50,25 @@ const PrintExcel = ({ table, filterData }) => {
};
return (
<Button
color="primary"
variant="contained"
size="small"
disabled={loading}
sx={{ textTransform: "unset", alignSelf: "center" }}
startIcon={loading ? <CircularProgress size={18} color="inherit" /> : <DescriptionIcon />}
onClick={clickHandler}
>
خروجی اکسل
</Button>
<>
{isMobile ? (
<IconButton aria-label="خروجی اکسل" color="primary" onClick={clickHandler}>
<DescriptionIcon sx={{ fontSize: "25px" }} />
</IconButton>
) : (
<Button
color="primary"
variant="contained"
size="small"
disabled={loading}
sx={{ textTransform: "unset", alignSelf: "center" }}
startIcon={loading ? <CircularProgress size={18} color="inherit" /> : <DescriptionIcon />}
onClick={clickHandler}
>
خروجی اکسل
</Button>
)}
</>
);
};

View File

@@ -44,7 +44,7 @@ const MachinePerformanceContent = ({ machinesLists }) => {
return (
<>
<DialogContent>
<Stack direction={"row"} spacing={4} justifyContent={"space-between"} alignItems={'center'}>
<Stack direction={"row"} spacing={4} justifyContent={"space-between"} alignItems={"center"}>
<StopsInfo
staticData={{
cmmsMachineCode: machinesLists.cmms_machine_code,
@@ -89,7 +89,12 @@ const MachinePerformanceContent = ({ machinesLists }) => {
</Box>
</Box>
</Stack>
<Grid container spacing={1} direction="row" sx={{ flex: 1, justifyContent: "space-between", alignItems: "center", mt: 2 }}>
<Grid
container
spacing={1}
direction="row"
sx={{ flex: 1, justifyContent: "space-between", alignItems: "center", mt: 2 }}
>
<Grid item xs={12} sm={12} sx={{ display: "flex", alignItems: "center" }}>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Chip
@@ -147,4 +152,4 @@ const MachinePerformanceContent = ({ machinesLists }) => {
</>
);
};
export default MachinePerformanceContent;
export default MachinePerformanceContent;

View File

@@ -5,7 +5,7 @@ import LocalGasStationIcon from "@mui/icons-material/LocalGasStation";
import QrCode2Icon from "@mui/icons-material/QrCode2";
import AddRoadIcon from "@mui/icons-material/AddRoad";
import DirectionsCarFilledIcon from "@mui/icons-material/DirectionsCarFilled";
import BadgeIcon from '@mui/icons-material/Badge';
import BadgeIcon from "@mui/icons-material/Badge";
import { formatSecondsToHHMMSS } from "@/core/utils/formatSecondsToHHMMSS";
import ShowPlak from "@/core/components/ShowPlak";
@@ -162,4 +162,4 @@ const StopsInfo = ({ selectedPoint, staticData }) => {
</Grid>
);
};
export default StopsInfo;
export default StopsInfo;

View File

@@ -48,4 +48,4 @@ const MachinePerformanceForm = ({ row }) => {
</>
);
};
export default MachinePerformanceForm;
export default MachinePerformanceForm;

View File

@@ -1,6 +1,10 @@
import PrintExcel from "./ExcelPrint";
const Toolbar = ({ table, filterData }) => {
return <>{/*<PrintExcel table={table} filterData={filterData} />*/}</>;
return (
<>
<PrintExcel table={table} filterData={filterData} />
</>
);
};
export default Toolbar;

View File

@@ -7,6 +7,8 @@ import { useCallback, useMemo, useState } from "react";
import useRequest from "@/lib/hooks/useRequest";
import useSWR from "swr";
import { flattenObjectOfObjects } from "@/core/utils/flattenObjectOfObjects";
import DataTableFilterDataStructure from "@/core/utils/DataTableFilterDataStructure";
import isArrayEmpty from "@/core/utils/isArrayEmpty";
const DataTable_Main = (props) => {
const request = useRequest();
@@ -37,26 +39,13 @@ const DataTable_Main = (props) => {
const params = new URLSearchParams();
params.set("start", `${pagination.pageIndex * pagination.pageSize}`);
params.set("size", pagination.pageSize);
const isValueEmpty = (value) => {
if (Array.isArray(value)) {
return value.length === 0 || value.every((v) => v === "");
}
return value === "" || value === null || value === undefined;
};
if (specialFilter) {
const filteredSpecialFilterData = Object.values(specialFilter).filter(
(filter) => !isValueEmpty(filter.value)
(filter) => !isArrayEmpty(filter.value)
);
params.set("filters", JSON.stringify(filteredSpecialFilterData || []));
} else {
const filteredFilterData = Object.values(filterData)
.filter((filter) => !isValueEmpty(filter.value))
.map(({ filterMode, id, ...rest }) => ({
...rest,
id: id.replace(/__/g, "."),
fn: filterMode,
}));
const filteredFilterData = DataTableFilterDataStructure(filterData, isArrayEmpty);
params.set("filters", JSON.stringify(filteredFilterData.length === 0 ? [] : filteredFilterData));
}
params.set("sorting", JSON.stringify(sortData));

View File

@@ -0,0 +1,9 @@
export default function DataTableFilterDataStructure(filterData, isValueEmpty) {
return Object.values(filterData)
.filter((filter) => !isValueEmpty(filter.value))
.map(({ filterMode, id, ...rest }) => ({
...rest,
id: id.replace(/__/g, "."),
fn: filterMode,
}));
}

View File

@@ -0,0 +1,6 @@
export default function isArrayEmpty(value) {
if (Array.isArray(value)) {
return value.length === 0 || value.every((v) => v === "");
}
return value === "" || value === null || value === undefined;
}

View File

@@ -30,23 +30,33 @@ export const UPDATE_AZMAYESH_TYPE = api + "/api/v3/azmayesh_types/update";
//road patrol
export const GET_ROAD_PATROL_OPERATOR_LIST = api + "/api/v3/road_patrols/operator_index";
export const EXPORT_ROAD_PATROL_OPERATOR_LIST = api + "/v2/road_patrols/operator/cartable/report";
export const EXPORT_ROAD_PATROL_OPERATOR_LIST = api + "/api/v3/road_patrols/operator_report";
export const GET_ROAD_PATROL_SUPERVISOR_LIST = api + "/api/v3/road_patrols/supervisor_index";
export const EXPORT_ROAD_PATROL_SUPERVISOR_LIST = api + "/v2/road_patrols/supervisor/cartable/report";
export const EXPORT_ROAD_PATROL_SUPERVISOR_LIST = api + "/api/v3/road_patrols/supervisor_report";
export const EXPORT_PROVINCE_ROAD_PATROL_REPORTS = api + "/api/v3/road_patrol_reports/province_activity_excel";
export const EXPORT_COUNTRY_ROAD_PATROL_REPORTS = api + "/api/v3/road_patrol_reports/country_activity_excel";
export const DELETE_ROAD_PATROL_SUPERVISOR = api + "/api/v3/road_patrols/delete";
export const GET_ROAD_PATROL_OPERATOR_REPORT = api + "/v2/road_patrols/operator/report";
export const GET_ROAD_PATROL_SUPERVISOR_REPORT = api + "/v2/road_patrols/supervisor/report";
export const CREATE_PATROL = api + "/api/v3/road_patrols/store";
export const GET_FMS_DATA = api + "/api/v3/fms_vehicle/get_activity";
export const GET_OTP_TOKEN = api + "/v2/get_otp_token";
export const GET_PROVINCE_ACTIVITY_REPORT = api + "/api/v3/road_patrol_reports/province_activity";
export const GET_CITY_ACTIVITY_REPORT = api + "/api/v3/road_patrol_reports/city_activity";
export const GET_PROVINCE_ACTIVITY_REPORT = api + "/api/v3/road_patrol_reports/country_activity";
export const GET_CITY_ACTIVITY_REPORT = api + "/api/v3/road_patrol_reports/province_activity";
// road items
export const GET_ROAD_ITEMS_SUPERVISOR_LIST = api + "/api/v3/road_items/supervisor_index";
export const EXPORT_ROAD_ITEMS_SUPERVISOR_LIST = api + "/api/v3/road_items/supervisor_report";
export const GET_ROAD_ITEMS_OPERATOR_LIST = api + "/api/v3/road_items/operator_index";
export const EXPORT_ROAD_ITEMS_OPERATOR_LIST = api + "/api/v3/road_items/operator_report";
export const EXPORT_PROVINCE_ROAD_ITEM_REPORTS_PER_ITEM =
api + "/api/v3/road_item_reports/province_activity_excel_per_item";
export const EXPORT_COUNTRY_ROAD_ITEM_REPORTS_PER_ITEM =
api + "/api/v3/road_item_reports/country_activity_excel_per_item";
export const EXPORT_PROVINCE_ROAD_ITEM_REPORTS_PER_SUB_ITEM =
api + "/api/v3/road_item_reports/province_activity_excel_per_sub_item";
export const EXPORT_COUNTRY_ROAD_ITEM_REPORTS_PER_SUB_ITEM =
api + "/api/v3/road_item_reports/country_activity_excel_per_sub_item";
export const GET_ROAD_ITEMS_ITEM = api + "/v2/items";
export const GET_ROAD_ITEMS_SUB_ITEM = api + "/v2/sub_items";
export const GET_EDARAT_LISTS = api + "/public/contents/edarate_shahri_by_province";
@@ -59,10 +69,10 @@ export const RESTORE_BY_SUPERVISOR = api + "/api/v3/road_items/restore";
export const GET_CAR_LIST_SEARCH = api + "/api/v3/cmms_machines/search";
export const GET_RAHDARANS_LIST_SEARCH = api + "/api/v3/rahdaran/search";
export const GET_OBSERVED_GASHT_LIST = api + "/api/v3/observed_items/filter";
export const GET_PROVINCE_ACTIVITY_PER_ITEM = api + "/api/v3/road_item_reports/province_activity_per_item";
export const GET_CITY_ACTIVITY_PER_ITEM = api + "/api/v3/road_item_reports/city_activity_per_item";
export const GET_PROVINCE_ACTIVITY_PER_SUB_ITEM = api + "/api/v3/road_item_reports/province_activity_per_sub_item";
export const GET_CITY_ACTIVITY_PER_SUB_ITEM = api + "/api/v3/road_item_reports/city_activity_per_sub_item";
export const GET_PROVINCE_ACTIVITY_PER_ITEM = api + "/api/v3/road_item_reports/country_activity_per_item";
export const GET_CITY_ACTIVITY_PER_ITEM = api + "/api/v3/road_item_reports/province_activity_per_item";
export const GET_PROVINCE_ACTIVITY_PER_SUB_ITEM = api + "/api/v3/road_item_reports/country_activity_per_sub_item";
export const GET_CITY_ACTIVITY_PER_SUB_ITEM = api + "/api/v3/road_item_reports/province_activity_per_sub_item";
// activity code log
export const ACTIVITY_LOG = api + "/api/v3/profile/add_activity";