22 Commits

Author SHA1 Message Date
2f91d31816 Merge tag 'v1.9.2' into develop
v1.9.2
2026-07-14 15:04:16 +03:30
40437079c9 Merge branch 'release/v1.9.2' 2026-07-14 15:04:06 +03:30
605114e0e4 v1.9.2 2026-07-14 15:03:30 +03:30
0ce0b608a4 Merge pull request 'bugfix/delete_violations' (#14) from bugfix/delete_violations into develop
Reviewed-on: #14
2026-07-14 11:26:11 +00:00
457bef64c4 add deleteviolations 2026-07-14 14:55:30 +03:30
f78a2c3cbb build and format 2026-07-14 14:46:03 +03:30
2c7679e52b add excel report to road missions 2026-07-14 14:44:21 +03:30
42194d2030 Merge branch 'develop' of http://git.witel.ir/RMS/frontend into bugfix/delete_violations 2026-07-14 09:00:46 +03:30
6520dd0365 Merge pull request 'feature/missions_table_updates' (#13) from feature/missions_table_updates into develop
Reviewed-on: #13
2026-07-14 05:30:09 +00:00
6cf30a591c add delete violation and base report page 2026-07-14 08:59:49 +03:30
1680cb44b7 added enter/exit columns to operator violations 2026-07-12 11:39:39 +03:30
51afdd47a0 added province and city filter to machine missions 2026-07-12 11:11:08 +03:30
f0d9a17e01 Merge tag 'v1.9.1' into develop
v1.9.1
2026-06-22 15:21:40 +03:30
3308f14d49 Merge branch 'release/v1.9.1' 2026-06-22 15:21:29 +03:30
7f77165ec4 v1.9.1 2026-06-22 15:20:40 +03:30
0435654762 Merge pull request 'feature/moddle_point' (#12) from feature/moddle_point into develop
Reviewed-on: #12
2026-06-22 11:48:26 +00:00
f94374958d build and format 2026-06-22 15:15:04 +03:30
a26f07d2ad 2 middle point 2026-06-22 15:14:02 +03:30
d1b74585d7 build & format 2026-06-22 15:04:47 +03:30
6115e0ded2 refactored violations, add controller and edit
replaced text explanation with select fields
2026-06-22 14:56:02 +03:30
40f80fac3a refactored explanation field on create flow
road missions operator cartable
2026-06-22 12:03:39 +03:30
188c7c45af base select options 2026-06-21 15:03:20 +03:30
46 changed files with 1035 additions and 325 deletions

View File

@@ -1,5 +1,5 @@
HOST="rms.witel.ir" HOST="rms.witel.ir"
HOST_RMTO="rms.rmto.ir" HOST_RMTO="rms.rmto.ir"
NEXT_PUBLIC_VERSION="1.9.0" NEXT_PUBLIC_VERSION="1.9.2"
NEXT_PUBLIC_API_URL="https://rms.witel.ir" NEXT_PUBLIC_API_URL="https://rms.witel.ir"
NEXT_PUBLIC_MAPTILE_ENDPOINT="https://rmsmap.rmto.ir/141map" NEXT_PUBLIC_MAPTILE_ENDPOINT="https://rmsmap.rmto.ir/141map"

View File

@@ -11,7 +11,7 @@ import { useEffect, useRef, useState } from "react";
import DataBox from "./DataBox"; import DataBox from "./DataBox";
import AlarmText from "./AlarmText"; import AlarmText from "./AlarmText";
const MAX_WAYPOINTS = 1; const MAX_WAYPOINTS = 2;
const Routing = ({ setArea, setLocations, locations, area }) => { const Routing = ({ setArea, setLocations, locations, area }) => {
const mapPrevSourceMarker = useRef(); const mapPrevSourceMarker = useRef();

View File

@@ -0,0 +1,34 @@
import useRoadItemGetItems from "@/lib/hooks/useRoadItemGetItems";
import { Controller } from "react-hook-form";
import SelectBox from "@/core/components/SelectBox";
const ItemSelectField = ({ control, setValue }) => {
const { itemsList, loadingItemsList, errorItemsList } = useRoadItemGetItems();
function getItemName(val) {
return itemsList.find((item) => item.id === val)?.name;
}
return (
<Controller
control={control}
name={"item_id"}
render={({ field, fieldState: { error } }) => (
<SelectBox
value={field.value}
label="موضوع"
selectors={itemsList}
isLoading={loadingItemsList}
schema={{ name: "name", value: "id" }}
error={errorItemsList}
helperText={error?.message}
onChange={(value) => {
field.onChange(value);
setValue("explanation", getItemName(value));
setValue("sub_item_id", "");
}}
/>
)}
/>
);
};
export default ItemSelectField;

View File

@@ -0,0 +1,37 @@
import useRoadItemGetSubItems from "@/lib/hooks/useRoadItemGetISubtems";
import { Controller } from "react-hook-form";
import SelectBox from "@/core/components/SelectBox";
const SubItemSelectField = ({ control, watch, setValue, getValues }) => {
const itemId = watch("item_id");
const { subItemsList, loadingSubItemsList, errorSubItemsList } = useRoadItemGetSubItems(itemId);
function createExplanation(val) {
const currentExplanation = getValues("explanation");
const selectedItem = subItemsList.find((item) => item.id === val)?.name;
return `${currentExplanation}-${selectedItem}`;
}
return (
<Controller
control={control}
name={"sub_item_id"}
render={({ field, fieldState: { error } }) => (
<SelectBox
value={field.value}
label="اقدام انجام شده"
selectors={subItemsList}
isLoading={loadingSubItemsList}
schema={{ name: "name", value: "id" }}
error={errorSubItemsList}
helperText={error?.message}
onChange={(val) => {
field.onChange(val);
setValue("explanation", createExplanation(val));
}}
/>
)}
/>
);
};
export default SubItemSelectField;

View File

@@ -9,12 +9,15 @@ import { ExitToApp } from "@mui/icons-material";
import { Box, Button, DialogActions, DialogContent, Grid, Stack } from "@mui/material"; import { Box, Button, DialogActions, DialogContent, Grid, Stack } from "@mui/material";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import { array, object, string } from "yup"; import { array, object, string } from "yup";
import ItemSelectField from "./ItemSelectField";
import SubItemSelectField from "./SubItemSelectField";
const validationSchema = object({ const validationSchema = object({
explanation: string().required("موضوع را مشخص کنید!"),
end_point: string().required("مقصد را مشخص کنید!"), end_point: string().required("مقصد را مشخص کنید!"),
region: string().required("محور ماموریت را مشخص کنید!"), region: string().required("محور ماموریت را مشخص کنید!"),
category_id: string().required("نوع ماموریت را مشخص کنید!"), category_id: string().required("نوع ماموریت را مشخص کنید!"),
item_id: string().required("موضوع را مشخص کنید!"),
sub_item_id: string().required("اقدام انجام شده را مشخص کنید!"),
requested_machines: array().min(1, "نوع خودرو را مشخص کنید!").required("نوع خودرو را مشخص کنید!"), requested_machines: array().min(1, "نوع خودرو را مشخص کنید!").required("نوع خودرو را مشخص کنید!"),
road_observed_id: string().when("category_id", { road_observed_id: string().when("category_id", {
is: "3", is: "3",
@@ -25,6 +28,8 @@ const validationSchema = object({
const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => { const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => {
const defaultValues = { const defaultValues = {
item_id: allData.item_id,
sub_item_id: allData.sub_item_id,
explanation: allData.explanation, explanation: allData.explanation,
end_point: allData.end_point, end_point: allData.end_point,
region: allData.region, region: allData.region,
@@ -33,7 +38,7 @@ const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => {
road_observed_id: allData.road_observed_id, road_observed_id: allData.road_observed_id,
}; };
const { control, handleSubmit } = useForm({ const { control, handleSubmit, watch, setValue, getValues } = useForm({
defaultValues, defaultValues,
resolver: yupResolver(validationSchema), resolver: yupResolver(validationSchema),
mode: "all", mode: "all",
@@ -51,24 +56,14 @@ const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => {
<Stack> <Stack>
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12} sm={6}> <Grid item xs={12} sm={6}>
<Controller <ItemSelectField control={control} watch={watch} setValue={setValue} />
</Grid>
<Grid item xs={12} sm={6}>
<SubItemSelectField
control={control} control={control}
name={"explanation"} watch={watch}
render={({ field, fieldState: { error } }) => ( setValue={setValue}
<PersianTextField getValues={getValues}
value={field.value}
variant="outlined"
name="explanation"
onChange={field.onChange}
label="موضوع"
placeholder={"موضوع را وارد کنید"}
fullWidth
size="small"
error={error}
helperText={error?.message}
InputLabelProps={{ shrink: true }}
/>
)}
/> />
</Grid> </Grid>
<Grid item xs={12} sm={6}> <Grid item xs={12} sm={6}>

View File

@@ -44,6 +44,8 @@ const Create = ({ mutate }) => {
start_date: result.start_date, start_date: result.start_date,
end_date: result.end_date, end_date: result.end_date,
}), }),
item_id: result.item_id,
sub_item_id: result.sub_item_id,
}, },
hasSidebarUpdate: true, hasSidebarUpdate: true,
}) })
@@ -93,6 +95,8 @@ const Create = ({ mutate }) => {
defaultValues={{ defaultValues={{
explanation: "", explanation: "",
category_id: "", category_id: "",
item_id: null,
sub_item_id: null,
road_observed_id: "", road_observed_id: "",
rahdaran: [], rahdaran: [],
requested_machines: [], requested_machines: [],

View File

@@ -4,7 +4,7 @@ import ViolationsList from "./ViolationsList";
const ViolationsDialog = ({ open, setOpen, mutate }) => { const ViolationsDialog = ({ open, setOpen, mutate }) => {
return ( return (
<Dialog open={open} fullWidth maxWidth="xs"> <Dialog open={open} fullWidth maxWidth="sm">
<IconButton <IconButton
aria-label="close" aria-label="close"
onClick={() => setOpen(false)} onClick={() => setOpen(false)}

View File

@@ -11,7 +11,7 @@ import { useEffect, useRef, useState } from "react";
import DataBox from "./DataBox"; import DataBox from "./DataBox";
import AlarmText from "./AlarmText"; import AlarmText from "./AlarmText";
const MAX_WAYPOINTS = 1; const MAX_WAYPOINTS = 2;
const Routing = ({ setArea, setLocations, locations, area }) => { const Routing = ({ setArea, setLocations, locations, area }) => {
const mapPrevSourceMarker = useRef(); const mapPrevSourceMarker = useRef();

View File

@@ -0,0 +1,34 @@
import useRoadItemGetItems from "@/lib/hooks/useRoadItemGetItems";
import { Controller } from "react-hook-form";
import SelectBox from "@/core/components/SelectBox";
const ItemSelectField = ({ control, setValue }) => {
const { itemsList, loadingItemsList, errorItemsList } = useRoadItemGetItems();
function getItemName(val) {
return itemsList.find((item) => item.id === val)?.name;
}
return (
<Controller
control={control}
name={"item_id"}
render={({ field, fieldState: { error } }) => (
<SelectBox
value={field.value}
label="موضوع"
selectors={itemsList}
isLoading={loadingItemsList}
schema={{ name: "name", value: "id" }}
error={errorItemsList}
helperText={error?.message}
onChange={(value) => {
field.onChange(value);
setValue("explanation", getItemName(value));
setValue("sub_item_id", "");
}}
/>
)}
/>
);
};
export default ItemSelectField;

View File

@@ -0,0 +1,37 @@
import useRoadItemGetSubItems from "@/lib/hooks/useRoadItemGetISubtems";
import { Controller } from "react-hook-form";
import SelectBox from "@/core/components/SelectBox";
const SubItemSelectField = ({ control, watch, setValue, getValues }) => {
const itemId = watch("item_id");
const { subItemsList, loadingSubItemsList, errorSubItemsList } = useRoadItemGetSubItems(itemId);
function createExplanation(val) {
const currentExplanation = getValues("explanation");
const selectedItem = subItemsList.find((item) => item.id === val)?.name;
return `${currentExplanation}-${selectedItem}`;
}
return (
<Controller
control={control}
name={"sub_item_id"}
render={({ field, fieldState: { error } }) => (
<SelectBox
value={field.value}
label="اقدام انجام شده"
selectors={subItemsList}
isLoading={loadingSubItemsList}
schema={{ name: "name", value: "id" }}
error={errorSubItemsList}
helperText={error?.message}
onChange={(val) => {
field.onChange(val);
setValue("explanation", createExplanation(val));
}}
/>
)}
/>
);
};
export default SubItemSelectField;

View File

@@ -8,10 +8,12 @@ import { ExitToApp } from "@mui/icons-material";
import { Box, Button, DialogActions, DialogContent, Grid, Stack } from "@mui/material"; import { Box, Button, DialogActions, DialogContent, Grid, Stack } from "@mui/material";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import { object, string } from "yup"; import { object, string } from "yup";
import FastReactCode from "./FastReactCode"; import ItemSelectField from "./ItemSelectField";
import SubItemSelectField from "./SubItemSelectField";
const validationSchema = object({ const validationSchema = object({
explanation: string().required("موضوع را مشخص کنید!"), item_id: string().required("موضوع را مشخص کنید!"),
sub_item_id: string().required("اقدام انجام شده را مشخص کنید!"),
end_point: string().required("مقصد را مشخص کنید!"), end_point: string().required("مقصد را مشخص کنید!"),
region: string().required("محور ماموریت را مشخص کنید!"), region: string().required("محور ماموریت را مشخص کنید!"),
category_id: string().required("نوع ماموریت را مشخص کنید!"), category_id: string().required("نوع ماموریت را مشخص کنید!"),
@@ -24,6 +26,8 @@ const validationSchema = object({
const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => { const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => {
const defaultValues = { const defaultValues = {
item_id: allData.item_id,
sub_item_id: allData.sub_item_id,
explanation: allData.explanation, explanation: allData.explanation,
end_point: allData.end_point, end_point: allData.end_point,
region: allData.region, region: allData.region,
@@ -31,7 +35,7 @@ const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => {
road_observed_id: allData.road_observed_id, road_observed_id: allData.road_observed_id,
}; };
const { control, handleSubmit } = useForm({ const { control, handleSubmit, watch, setValue, getValues } = useForm({
defaultValues, defaultValues,
resolver: yupResolver(validationSchema), resolver: yupResolver(validationSchema),
mode: "all", mode: "all",
@@ -49,24 +53,14 @@ const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => {
<Stack> <Stack>
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12} sm={6}> <Grid item xs={12} sm={6}>
<Controller <ItemSelectField control={control} watch={watch} setValue={setValue} />
</Grid>
<Grid item xs={12} sm={6}>
<SubItemSelectField
control={control} control={control}
name={"explanation"} watch={watch}
render={({ field, fieldState: { error } }) => ( setValue={setValue}
<PersianTextField getValues={getValues}
value={field.value}
variant="outlined"
name="explanation"
onChange={field.onChange}
label="موضوع"
placeholder={"موضوع را وارد کنید"}
fullWidth
size="small"
error={error}
helperText={error?.message}
InputLabelProps={{ shrink: true }}
/>
)}
/> />
</Grid> </Grid>
<Grid item xs={12} sm={6}> <Grid item xs={12} sm={6}>

View File

@@ -1,12 +1,11 @@
import { AccessTime, Engineering, InsertDriveFile, Person, Verified, Map } from "@mui/icons-material"; import { Engineering, InsertDriveFile, Map, Person, Verified } from "@mui/icons-material";
import { Box, Tab, Tabs } from "@mui/material"; import { Box, Tab, Tabs } from "@mui/material";
import { useReducer, useState } from "react"; import { useReducer, useState } from "react";
import GetDateTime from "./GetDateTime"; import Area from "./Area";
import GetItemInfo from "./GetItemInfo"; import GetItemInfo from "./GetItemInfo";
import MachineAndDriver from "./MachineAndDriver"; import MachineAndDriver from "./MachineAndDriver";
import Rahdaran from "./Rahdaran"; import Rahdaran from "./Rahdaran";
import Verify from "./Verify"; import Verify from "./Verify";
import Area from "./Area";
function TabPanel(props) { function TabPanel(props) {
const { children, value, index } = props; const { children, value, index } = props;

View File

@@ -26,6 +26,8 @@ const MissionCorrection = ({ row, mutate, baseMutate }) => {
end_point: result.end_point, end_point: result.end_point,
driver: result.driver.id, driver: result.driver.id,
encoded_route: result.area, encoded_route: result.area,
item_id: result.item_id,
sub_item_id: result.sub_item_id,
}, },
hasSidebarUpdate: true, hasSidebarUpdate: true,
}) })

View File

@@ -116,6 +116,54 @@ const ViolationsList = ({ setOpen, mutate }) => {
}, },
Cell: ({ row }) => <>{row.original.city_name}</>, Cell: ({ row }) => <>{row.original.city_name}</>,
}, },
{
accessorKey: "enter_time",
header: "تاریخ و ساعت ورود",
id: "enter_time",
enableColumnFilter: true,
datatype: "text",
filterMode: "equals",
columnFilterModeOptions: ["equals", "contains"],
grow: false,
size: 140,
Cell: ({ cell }) => {
const value = formatDateTime(cell.getValue());
if (!value) return "-";
return (
<>
<span className="font-medium">{value.date}</span>
<span> - </span>
<span className="text-xs text-muted-foreground">{value.time}</span>
</>
);
},
},
{
accessorKey: "exit_time",
header: "تاریخ و ساعت خروج",
id: "exit_time",
enableColumnFilter: true,
datatype: "text",
filterMode: "equals",
columnFilterModeOptions: ["equals", "contains"],
grow: false,
size: 140,
Cell: ({ cell }) => {
const value = formatDateTime(cell.getValue());
if (!value) return "-";
return (
<div className="flex flex-col leading-tight">
<span className="font-medium">{value.date}</span>
<span> - </span>
<span className="text-xs text-muted-foreground">{value.time}</span>
</div>
);
},
},
]; ];
}, []); }, []);
@@ -139,3 +187,22 @@ const ViolationsList = ({ setOpen, mutate }) => {
); );
}; };
export default ViolationsList; export default ViolationsList;
const formatDateTime = (value) => {
if (!value) return null;
const date = new Date(value.replace(" ", "T"));
return {
date: new Intl.DateTimeFormat("fa-IR", {
year: "numeric",
month: "2-digit",
day: "2-digit",
}).format(date),
time: new Intl.DateTimeFormat("fa-IR", {
hour: "2-digit",
minute: "2-digit",
}).format(date),
};
};

View File

@@ -11,7 +11,7 @@ import { useEffect, useRef, useState } from "react";
import DataBox from "./DataBox"; import DataBox from "./DataBox";
import AlarmText from "./AlarmText"; import AlarmText from "./AlarmText";
const MAX_WAYPOINTS = 1; const MAX_WAYPOINTS = 2;
const Routing = ({ setArea, setLocations, locations, area }) => { const Routing = ({ setArea, setLocations, locations, area }) => {
const mapPrevSourceMarker = useRef(); const mapPrevSourceMarker = useRef();

View File

@@ -0,0 +1,34 @@
import useRoadItemGetItems from "@/lib/hooks/useRoadItemGetItems";
import { Controller } from "react-hook-form";
import SelectBox from "@/core/components/SelectBox";
const ItemSelectField = ({ control, setValue }) => {
const { itemsList, loadingItemsList, errorItemsList } = useRoadItemGetItems();
function getItemName(val) {
return itemsList.find((item) => item.id === val)?.name;
}
return (
<Controller
control={control}
name={"item_id"}
render={({ field, fieldState: { error } }) => (
<SelectBox
value={field.value}
label="موضوع"
selectors={itemsList}
isLoading={loadingItemsList}
schema={{ name: "name", value: "id" }}
error={errorItemsList}
helperText={error?.message}
onChange={(value) => {
field.onChange(value);
setValue("explanation", getItemName(value));
setValue("sub_item_id", "");
}}
/>
)}
/>
);
};
export default ItemSelectField;

View File

@@ -0,0 +1,37 @@
import useRoadItemGetSubItems from "@/lib/hooks/useRoadItemGetISubtems";
import { Controller } from "react-hook-form";
import SelectBox from "@/core/components/SelectBox";
const SubItemSelectField = ({ control, watch, setValue, getValues }) => {
const itemId = watch("item_id");
const { subItemsList, loadingSubItemsList, errorSubItemsList } = useRoadItemGetSubItems(itemId);
function createExplanation(val) {
const currentExplanation = getValues("explanation");
const selectedItem = subItemsList.find((item) => item.id === val)?.name;
return `${currentExplanation}-${selectedItem}`;
}
return (
<Controller
control={control}
name={"sub_item_id"}
render={({ field, fieldState: { error } }) => (
<SelectBox
value={field.value}
label="اقدام انجام شده"
selectors={subItemsList}
isLoading={loadingSubItemsList}
schema={{ name: "name", value: "id" }}
error={errorSubItemsList}
helperText={error?.message}
onChange={(val) => {
field.onChange(val);
setValue("explanation", createExplanation(val));
}}
/>
)}
/>
);
};
export default SubItemSelectField;

View File

@@ -1,3 +1,4 @@
import LtrTextField from "@/core/components/LtrTextField";
import PersianTextField from "@/core/components/PersianTextField"; import PersianTextField from "@/core/components/PersianTextField";
import SelectBox from "@/core/components/SelectBox"; import SelectBox from "@/core/components/SelectBox";
import StyledForm from "@/core/components/StyledForm"; import StyledForm from "@/core/components/StyledForm";
@@ -8,7 +9,8 @@ import { ExitToApp } from "@mui/icons-material";
import { Box, Button, DialogActions, DialogContent, Grid, Stack } from "@mui/material"; import { Box, Button, DialogActions, DialogContent, Grid, Stack } from "@mui/material";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import { object, string } from "yup"; import { object, string } from "yup";
import LtrTextField from "@/core/components/LtrTextField"; import ItemSelectField from "./ItemSelectField";
import SubItemSelectField from "./SubItemSelectField";
const validationSchema = object({ const validationSchema = object({
explanation: string().required("موضوع را مشخص کنید!"), explanation: string().required("موضوع را مشخص کنید!"),
@@ -24,6 +26,8 @@ const validationSchema = object({
const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => { const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => {
const defaultValues = { const defaultValues = {
item_id: allData.item_id,
sub_item_id: allData.sub_item_id,
explanation: allData.explanation, explanation: allData.explanation,
end_point: allData.end_point, end_point: allData.end_point,
region: allData.region, region: allData.region,
@@ -31,7 +35,7 @@ const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => {
road_observed_id: allData.road_observed_id, road_observed_id: allData.road_observed_id,
}; };
const { control, handleSubmit } = useForm({ const { control, handleSubmit, watch, setValue, getValues } = useForm({
defaultValues, defaultValues,
resolver: yupResolver(validationSchema), resolver: yupResolver(validationSchema),
mode: "all", mode: "all",
@@ -49,24 +53,14 @@ const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => {
<Stack> <Stack>
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12} sm={6}> <Grid item xs={12} sm={6}>
<Controller <ItemSelectField control={control} watch={watch} setValue={setValue} />
</Grid>
<Grid item xs={12} sm={6}>
<SubItemSelectField
control={control} control={control}
name={"explanation"} watch={watch}
render={({ field, fieldState: { error } }) => ( setValue={setValue}
<PersianTextField getValues={getValues}
value={field.value}
variant="outlined"
name="explanation"
onChange={field.onChange}
label="موضوع"
placeholder={"موضوع را وارد کنید"}
fullWidth
size="small"
error={error}
helperText={error?.message}
InputLabelProps={{ shrink: true }}
/>
)}
/> />
</Grid> </Grid>
<Grid item xs={12} sm={6}> <Grid item xs={12} sm={6}>
@@ -126,7 +120,7 @@ const GetItemInfo = ({ allData, setAllData, handlePrev, setTabState }) => {
}} }}
/> />
</Grid> </Grid>
<Grid item xs={12} sm={12}> <Grid item xs={6} sm={6}>
<Stack> <Stack>
<Controller <Controller
control={control} control={control}

View File

@@ -93,10 +93,12 @@ const Verify = ({ allData, handlePrev, submitForm, submitting }) => {
<Stack direction={"row"} alignItems={"center"} spacing={1}> <Stack direction={"row"} alignItems={"center"} spacing={1}>
<Typography variant="body2">خودرو</Typography> <Typography variant="body2">خودرو</Typography>
<Divider sx={{ flex: 1 }} /> <Divider sx={{ flex: 1 }} />
<Chip {allData.machine && (
size="small" <Chip
label={`${allData.machine.machine_code} | ${allData.machine.car_name}`} size="small"
/> label={`${allData.machine.machine_code} | ${allData.machine.car_name}`}
/>
)}
</Stack> </Stack>
{/* <Stack direction={"row"} alignItems={"center"} spacing={1}> {/* <Stack direction={"row"} alignItems={"center"} spacing={1}>
<Typography variant="body2">راننده</Typography> <Typography variant="body2">راننده</Typography>

View File

@@ -9,6 +9,8 @@ const DialogAdd = ({ mutate, setOpen, oldBound, rahdaran, machine, row }) => {
const requestServer = useRequest({ notificationSuccess: true }); const requestServer = useRequest({ notificationSuccess: true });
const submitForm = async (result) => { const submitForm = async (result) => {
console.log("result: ", result);
setSubmitting(true); setSubmitting(true);
await requestServer(`${REQUEST_MISSION_CONTINUE_MISSION}/${row.original.id}`, "post", { await requestServer(`${REQUEST_MISSION_CONTINUE_MISSION}/${row.original.id}`, "post", {
data: { data: {
@@ -29,6 +31,8 @@ const DialogAdd = ({ mutate, setOpen, oldBound, rahdaran, machine, row }) => {
end_point: result.end_point, end_point: result.end_point,
category_id: result.category_id, category_id: result.category_id,
explanation: result.explanation, explanation: result.explanation,
item_id: result.item_id,
sub_item_id: result.sub_item_id,
...(result.category_id == 3 ...(result.category_id == 3
? { ? {
road_observed_id: result.road_observed_id, road_observed_id: result.road_observed_id,
@@ -51,6 +55,8 @@ const DialogAdd = ({ mutate, setOpen, oldBound, rahdaran, machine, row }) => {
<CreateForm <CreateForm
defaultValues={{ defaultValues={{
explanation: "", explanation: "",
item_id: "",
sub_item_id: "",
category_id: "", category_id: "",
rahdaran: rahdaran.filter((r) => !r.is_driver), rahdaran: rahdaran.filter((r) => !r.is_driver),
bound_type: "polyline", bound_type: "polyline",

View File

@@ -51,6 +51,8 @@ const EditController = ({ row, mutate, openEditDialog, setOpenEditDialog }) => {
await requestServer(`${UPDATE_REQUEST_MISSION}/${row.original.id}`, "post", { await requestServer(`${UPDATE_REQUEST_MISSION}/${row.original.id}`, "post", {
data: { data: {
explanation: result.explanation, explanation: result.explanation,
item_id: result.item_id,
sub_item_id: result.sub_item_id,
category_id: result.category_id, category_id: result.category_id,
...(result.category_id == 3 ...(result.category_id == 3
@@ -101,6 +103,8 @@ const EditController = ({ row, mutate, openEditDialog, setOpenEditDialog }) => {
<CreateForm <CreateForm
defaultValues={{ defaultValues={{
explanation: row.original.explanation, explanation: row.original.explanation,
item_id: row.original.item_id,
sub_item_id: row.original.sub_item_id,
category_id: row.original.category_id, category_id: row.original.category_id,
road_observed_id: row.original.category_id == 3 ? (row.original.road_observed?.[0]?.id ?? "") : "", road_observed_id: row.original.category_id == 3 ? (row.original.road_observed?.[0]?.id ?? "") : "",

View File

@@ -4,16 +4,19 @@ import { Box } from "@mui/material";
import { useMemo } from "react"; import { useMemo } from "react";
import Toolbar from "./Toolbar"; import Toolbar from "./Toolbar";
import RowActions from "./RowActions"; import RowActions from "./RowActions";
import { GET_DRIVERS_ACTIVITY_REPORT } from "@/core/utils/routes";
const DriverReportsList = ({ data, specialFilter }) => { const DriverReportsList = ({ specialFilter }) => {
const columns = useMemo(() => { const columns = useMemo(() => {
return [ return [
{ {
accessorKey: "driver_id", accessorKey: "driver_id",
header: "کد یکتا", header: "کد یکتا",
id: "driver_id", id: "driver_id",
enableColumnFilter: false, enableColumnFilter: true,
enableSorting: false, filterMode: "equals",
columnFilterModeOptions: ["equals", "contains"],
enableSorting: true,
datatype: "numeric", datatype: "numeric",
grow: false, grow: false,
size: 50, size: 50,
@@ -22,8 +25,10 @@ const DriverReportsList = ({ data, specialFilter }) => {
accessorKey: "driver_name", accessorKey: "driver_name",
header: "نام راننده", header: "نام راننده",
id: "driver_name", id: "driver_name",
enableColumnFilter: false, enableColumnFilter: true,
enableSorting: false, filterMode: "equals",
columnFilterModeOptions: ["equals", "contains"],
enableSorting: true,
datatype: "text", datatype: "text",
grow: false, grow: false,
size: 50, size: 50,
@@ -43,7 +48,7 @@ const DriverReportsList = ({ data, specialFilter }) => {
header: "تعداد ماموریت", header: "تعداد ماموریت",
id: "missions", id: "missions",
enableColumnFilter: false, enableColumnFilter: false,
enableSorting: false, enableSorting: true,
datatype: "number", datatype: "number",
grow: false, grow: false,
size: 50, size: 50,
@@ -56,8 +61,9 @@ const DriverReportsList = ({ data, specialFilter }) => {
<Box sx={{ p: 1, border: 1, borderColor: "divider", borderRadius: 1 }}> <Box sx={{ p: 1, border: 1, borderColor: "divider", borderRadius: 1 }}>
<DataTableWithAuth <DataTableWithAuth
TableToolbar={Toolbar} TableToolbar={Toolbar}
need_filter={true}
columns={columns} columns={columns}
data={data.data} table_url={GET_DRIVERS_ACTIVITY_REPORT}
page_name={"driverReport"} page_name={"driverReport"}
table_name={"driverReportList"} table_name={"driverReportList"}
enablePagination={false} enablePagination={false}

View File

@@ -1,8 +1,5 @@
"use client"; "use client";
import { import { EXPORT_GET_DRIVER_ACTIVITY_REPORT } from "@/core/utils/routes";
EXPORT_GET_DRIVER_COUNTRY_ACTIVITY_REPORT,
EXPORT_GET_DRIVER_PROVINCE_ACTIVITY_REPORT,
} from "@/core/utils/routes";
import useRequest from "@/lib/hooks/useRequest"; import useRequest from "@/lib/hooks/useRequest";
import { useTheme } from "@emotion/react"; import { useTheme } from "@emotion/react";
import DescriptionIcon from "@mui/icons-material/Description"; import DescriptionIcon from "@mui/icons-material/Description";
@@ -34,11 +31,7 @@ const PrintExcel = ({ table, filterData }) => {
const clickHandler = () => { const clickHandler = () => {
setLoading(true); setLoading(true);
const CountryOrProvince = activeFilters.find((item) => item.id === "province_id"); const requestUrl = EXPORT_GET_DRIVER_ACTIVITY_REPORT;
const requestUrl =
CountryOrProvince.value === "-1"
? EXPORT_GET_DRIVER_COUNTRY_ACTIVITY_REPORT
: EXPORT_GET_DRIVER_PROVINCE_ACTIVITY_REPORT;
requestServer(`${requestUrl}?${filterParams}`, "get", { requestServer(`${requestUrl}?${filterParams}`, "get", {
requestOptions: { responseType: "blob" }, requestOptions: { responseType: "blob" },
}) })
@@ -66,7 +59,7 @@ const PrintExcel = ({ table, filterData }) => {
disabled={loading} disabled={loading}
sx={{ textTransform: "unset", alignSelf: "center" }} sx={{ textTransform: "unset", alignSelf: "center" }}
startIcon={loading ? <CircularProgress size={18} color="inherit" /> : <DescriptionIcon />} startIcon={loading ? <CircularProgress size={18} color="inherit" /> : <DescriptionIcon />}
onClick={clickHandler} // onClick={clickHandler}
> >
خروجی اکسل خروجی اکسل
</Button> </Button>

View File

@@ -0,0 +1,79 @@
"use client";
import { EXPORT_GET_DRIVER_DETAILS_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, specialFilterData }) => {
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 activeSpecialFilters = Object.entries(specialFilterData).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);
});
activeSpecialFilters.length > 0 &&
activeSpecialFilters.map((filter, index) => {
params.set(`${filter.id}`, filter.value);
});
return params;
}, [activeFilters, activeSpecialFilters]);
const clickHandler = () => {
setLoading(true);
const requestUrl = EXPORT_GET_DRIVER_DETAILS_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 ? (
<IconButton aria-label="خروجی اکسل" color="success" onClick={clickHandler}>
<DescriptionIcon sx={{ fontSize: "25px" }} />
</IconButton>
) : (
<Button
color="success"
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

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

View File

@@ -1,11 +1,52 @@
import CustomSelectByDependency from "@/core/components/DataTable/filter/fieldsType/CustomSelectByDependency";
import DataTableWithAuth from "@/core/components/DataTableWithAuth"; import DataTableWithAuth from "@/core/components/DataTableWithAuth";
import { GET_DRIVER_DETAILS } from "@/core/utils/routes"; import { GET_DRIVER_DETAILS } from "@/core/utils/routes";
import useCities from "@/lib/hooks/useCities";
import useProvinces from "@/lib/hooks/useProvince";
import { Box } from "@mui/material"; import { Box } from "@mui/material";
import { useMemo } from "react"; import { useMemo } from "react";
import Toolbar from "./Toolbar";
const DriverList = ({ row, specialFilter }) => { const DriverList = ({ row, specialFilter }) => {
const columns = useMemo( const columns = useMemo(() => {
() => [ const dynamicColumns = {
header: "استان",
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: "کل کشور" },
...provinces.map((province) => ({
value: province.id,
label: province.name_fa,
})),
];
}, [provinces, errorProvinces, loadingProvinces]);
return (
<CustomSelectByDependency
{...props}
value={loadingProvinces ? "loading" : props.filterParameters.value}
columnSelectOption={getColumnSelectOptions}
/>
);
},
Cell: ({ renderedCellValue, row }) => {
return <>{row.original.province_name}</>;
},
};
return [
{ {
accessorKey: "id", accessorKey: "id",
header: "کد یکتا", header: "کد یکتا",
@@ -17,27 +58,52 @@ const DriverList = ({ row, specialFilter }) => {
grow: false, grow: false,
size: 80, size: 80,
}, },
...[dynamicColumns],
{ {
accessorKey: "province_name",
header: "استان",
id: "province_name",
enableColumnFilter: true,
datatype: "text",
filterMode: "equals",
columnFilterModeOptions: ["equals", "contains"],
grow: false,
size: 100,
},
{
accessorKey: "city_name",
header: "شهر", header: "شهر",
id: "city_name", id: "city_id",
enableColumnFilter: true, enableColumnFilter: true,
datatype: "text", datatype: "numeric",
filterMode: "equals", filterMode: "equals",
columnFilterModeOptions: ["equals", "contains"], dependencyId: "province_id",
grow: false, grow: false,
size: 100, size: 120,
ColumnSelectComponent: (props) => {
const { cityList, loadingCityList, errorCityList } = useCities(props.dependencyFieldValue.value);
const getColumnSelectOptions = useMemo(() => {
if (props.dependencyFieldValue.value === "") {
return [{ value: "empty", label: "ابتدا استان را انتخاب کنید" }];
}
if (loadingCityList) {
return [{ value: "loading", label: "در حال بارگذاری..." }];
}
if (errorCityList) {
return [{ value: "error", label: "خطا در بارگذاری" }];
}
return [
{ value: "", label: "کل ادارات" },
...cityList.map((edare) => ({
value: edare.id,
label: edare.name_fa,
})),
];
}, [cityList, loadingCityList, errorCityList]);
return (
<CustomSelectByDependency
{...props}
value={
props.dependencyFieldValue?.value === ""
? "empty"
: loadingCityList
? "loading"
: props.filterParameters.value
}
columnSelectOption={getColumnSelectOptions}
/>
);
},
Cell: ({ row }) => <>{row.original.city_name}</>,
}, },
{ {
accessorKey: "station_name", accessorKey: "station_name",
@@ -83,19 +149,22 @@ const DriverList = ({ row, specialFilter }) => {
grow: false, grow: false,
size: 100, size: 100,
}, },
], ];
[] }, []);
);
return ( return (
<> <>
<Box sx={{ mt: 3 }}> <Box sx={{ mt: 3 }}>
<DataTableWithAuth <DataTableWithAuth
TableToolbar={Toolbar}
need_filter={true} need_filter={true}
columns={columns} columns={columns}
specialFilter={specialFilter} specialFilter={specialFilter}
specialQueries={{
driver_id: row.driver_id,
}}
sorting={[{ id: "id", desc: true }]} sorting={[{ id: "id", desc: true }]}
table_url={`${GET_DRIVER_DETAILS}/${row.driver_id}`} table_url={GET_DRIVER_DETAILS}
page_name={"driverListReport"} page_name={"driverListReport"}
table_name={"driverList"} table_name={"driverList"}
positionActionsColumn={"first"} positionActionsColumn={"first"}

View File

@@ -1,11 +1,9 @@
"use client"; "use client";
import PageTitle from "@/core/components/PageTitle"; import PageTitle from "@/core/components/PageTitle";
import { GET_DRIVER_COUNTRY_ACTIVITY_REPORT, GET_DRIVER_PROVINCE_ACTIVITY_REPORT } from "@/core/utils/routes";
import { useAuth } from "@/lib/contexts/auth"; import { useAuth } from "@/lib/contexts/auth";
import { usePermissions } from "@/lib/hooks/usePermissions"; import { usePermissions } from "@/lib/hooks/usePermissions";
import useRequest from "@/lib/hooks/useRequest";
import { yupResolver } from "@hookform/resolvers/yup"; import { yupResolver } from "@hookform/resolvers/yup";
import { LinearProgress, Stack } from "@mui/material"; import { Stack } from "@mui/material";
import moment from "jalali-moment"; import moment from "jalali-moment";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
@@ -14,10 +12,8 @@ import DriverReportsList from "./DriverReportsList";
import SearchReportList from "./Search"; import SearchReportList from "./Search";
const DriverReportsPage = () => { const DriverReportsPage = () => {
const [data, setData] = useState(null);
const { data: userPermissions } = usePermissions(); const { data: userPermissions } = usePermissions();
const { user } = useAuth(); const { user } = useAuth();
const requestServer = useRequest();
const hasProvincesPermission = userPermissions?.includes("mission-report-country"); const hasProvincesPermission = userPermissions?.includes("mission-report-country");
const defaultValues = { const defaultValues = {
@@ -32,38 +28,32 @@ const DriverReportsPage = () => {
]; ];
const [specialFilter, setSpecialFilter] = useState(defaultFilter); const [specialFilter, setSpecialFilter] = useState(defaultFilter);
const onSearchSubmit = async (data) => { const onSearchSubmit = (data) => {
const params = new URLSearchParams(); const filters = [
params.set("from_date", `${data.from_date} 00:00:00`); {
params.set("date_to", `${data.date_to} 23:59:59`); value: `${data.from_date} 00:00:00`,
setSpecialFilter([ datatype: "date",
{ value: `${data.province_id}`, datatype: "numeric", id: "province_id", fn: "equals" }, id: "start_time",
{ value: `${data.from_date} 00:00:00`, datatype: "date", id: "start_time", fn: "greaterThan" }, fn: "greaterThan",
{ value: `${data.date_to} 23:59:59`, datatype: "date", id: "finish_time", fn: "lessThan" }, },
]); {
if (data.province_id === "-1") { value: `${data.date_to} 23:59:59`,
try { datatype: "date",
const response = await requestServer(`${GET_DRIVER_COUNTRY_ACTIVITY_REPORT}?${params}`); id: "finish_time",
const result = response.data.data; fn: "lessThan",
},
];
setData({ if (data.province_id !== "-1") {
data: result.activities, filters.unshift({
filters: data, value: data.province_id,
}); datatype: "numeric",
} catch (e) {} id: "province_id",
} else { fn: "equals",
try { });
params.set("province_id", `${data.province_id}`);
const response = await requestServer(`${GET_DRIVER_PROVINCE_ACTIVITY_REPORT}?${params}`);
const result = response.data.data;
setData({
data: result.activities,
filters: data,
});
} catch (e) {}
} }
setSpecialFilter(filters);
}; };
useEffect(() => { useEffect(() => {
@@ -100,7 +90,7 @@ const DriverReportsPage = () => {
handleSubmit={handleSubmit} handleSubmit={handleSubmit}
onSearchSubmit={onSearchSubmit} onSearchSubmit={onSearchSubmit}
/> />
{!data ? <LinearProgress /> : <DriverReportsList specialFilter={specialFilter} data={data} />} <DriverReportsList specialFilter={specialFilter} />
</Stack> </Stack>
); );
}; };

View File

@@ -1,8 +1,5 @@
"use client"; "use client";
import { import { EXPORT_GET_MACHINES_ACTIVITY_REPORT } from "@/core/utils/routes";
EXPORT_GET_MACHINES_COUNTRY_ACTIVITY_REPORT,
EXPORT_GET_MACHINES_PROVINCE_ACTIVITY_REPORT,
} from "@/core/utils/routes";
import useRequest from "@/lib/hooks/useRequest"; import useRequest from "@/lib/hooks/useRequest";
import { useTheme } from "@emotion/react"; import { useTheme } from "@emotion/react";
import DescriptionIcon from "@mui/icons-material/Description"; import DescriptionIcon from "@mui/icons-material/Description";
@@ -34,16 +31,12 @@ const PrintExcel = ({ table, filterData }) => {
const clickHandler = () => { const clickHandler = () => {
setLoading(true); setLoading(true);
const CountryOrProvince = activeFilters.find((item) => item.id === "province_id"); const requestUrl = EXPORT_GET_MACHINES_ACTIVITY_REPORT;
const requestUrl =
CountryOrProvince.value === "-1"
? EXPORT_GET_MACHINES_COUNTRY_ACTIVITY_REPORT
: EXPORT_GET_MACHINES_PROVINCE_ACTIVITY_REPORT;
requestServer(`${requestUrl}?${filterParams}`, "get", { requestServer(`${requestUrl}?${filterParams}`, "get", {
requestOptions: { responseType: "blob" }, requestOptions: { responseType: "blob" },
}) })
.then((response) => { .then((response) => {
const filename = `خروجی کارتابل گزارشات گشت راهداری تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`; const filename = `خروجی کارتابل گزارشات ماشین ها تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`;
FileSaver.saveAs(response.data, filename); FileSaver.saveAs(response.data, filename);
}) })
.catch(() => {}) .catch(() => {})
@@ -66,7 +59,7 @@ const PrintExcel = ({ table, filterData }) => {
disabled={loading} disabled={loading}
sx={{ textTransform: "unset", alignSelf: "center" }} sx={{ textTransform: "unset", alignSelf: "center" }}
startIcon={loading ? <CircularProgress size={18} color="inherit" /> : <DescriptionIcon />} startIcon={loading ? <CircularProgress size={18} color="inherit" /> : <DescriptionIcon />}
onClick={clickHandler} // onClick={clickHandler}
> >
خروجی اکسل خروجی اکسل
</Button> </Button>

View File

@@ -4,17 +4,24 @@ import { Box } from "@mui/material";
import { useMemo } from "react"; import { useMemo } from "react";
import Toolbar from "./Toolbar"; import Toolbar from "./Toolbar";
import RowActions from "./RowActions"; import RowActions from "./RowActions";
import {
GET_MACHINES_ACTIVITY_REPORT,
GET_MACHINES_COUNTRY_ACTIVITY_REPORT,
GET_MACHINES_PROVINCE_ACTIVITY_REPORT,
} from "@/core/utils/routes";
const MachinesReportsList = ({ data, specialFilter }) => { const MachinesReportsList = ({ specialFilter }) => {
const columns = useMemo(() => { const columns = useMemo(() => {
return [ return [
{ {
accessorKey: "machine_id", accessorKey: "machine_id",
header: "کد یکتا", header: "کد یکتا",
id: "machine_id", id: "machine_id",
enableColumnFilter: false, enableColumnFilter: true,
enableSorting: false, filterMode: "equals",
datatype: "numeric", columnFilterModeOptions: ["equals", "contains"],
enableSorting: true,
datatype: "text",
grow: false, grow: false,
size: 50, size: 50,
}, },
@@ -23,7 +30,9 @@ const MachinesReportsList = ({ data, specialFilter }) => {
header: "مدل ماشین", header: "مدل ماشین",
id: "car_name", id: "car_name",
enableColumnFilter: false, enableColumnFilter: false,
enableSorting: false, filterMode: "equals",
columnFilterModeOptions: ["equals", "contains"],
enableSorting: true,
datatype: "text", datatype: "text",
grow: false, grow: false,
size: 50, size: 50,
@@ -32,7 +41,8 @@ const MachinesReportsList = ({ data, specialFilter }) => {
accessorKey: "machine_code", accessorKey: "machine_code",
header: "کد ماشین", header: "کد ماشین",
id: "machine_code", id: "machine_code",
enableColumnFilter: false, enableColumnFilter: true,
columnFilterModeOptions: ["equals", "contains"],
enableSorting: false, enableSorting: false,
datatype: "text", datatype: "text",
grow: false, grow: false,
@@ -43,7 +53,8 @@ const MachinesReportsList = ({ data, specialFilter }) => {
header: "کارکرد", header: "کارکرد",
id: "func", id: "func",
enableColumnFilter: false, enableColumnFilter: false,
enableSorting: false, columnFilterModeOptions: ["equals", "contains"],
enableSorting: true,
datatype: "number", datatype: "number",
grow: false, grow: false,
size: 50, size: 50,
@@ -53,7 +64,7 @@ const MachinesReportsList = ({ data, specialFilter }) => {
header: "تعداد ماموریت", header: "تعداد ماموریت",
id: "missions", id: "missions",
enableColumnFilter: false, enableColumnFilter: false,
enableSorting: false, enableSorting: true,
datatype: "number", datatype: "number",
grow: false, grow: false,
size: 50, size: 50,
@@ -67,11 +78,12 @@ const MachinesReportsList = ({ data, specialFilter }) => {
<DataTableWithAuth <DataTableWithAuth
TableToolbar={Toolbar} TableToolbar={Toolbar}
columns={columns} columns={columns}
data={data.data} table_url={GET_MACHINES_ACTIVITY_REPORT}
page_name={"roadMissionReport"} page_name={"roadMissionReport"}
table_name={"roadMissionReportList"} table_name={"roadMissionReportList"}
enablePagination={false} enablePagination={true}
specialFilter={specialFilter} specialFilter={specialFilter}
need_filter={true}
enableRowActions enableRowActions
RowActions={RowActionsWithRowData} RowActions={RowActionsWithRowData}
/> />

View File

@@ -0,0 +1,70 @@
"use client";
import { EXPORT_GET_MACHINES_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 requestUrl = EXPORT_GET_MACHINES_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 ? (
<IconButton aria-label="خروجی اکسل" color="success" onClick={clickHandler}>
<DescriptionIcon sx={{ fontSize: "25px" }} />
</IconButton>
) : (
<Button
color="success"
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

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

View File

@@ -1,11 +1,52 @@
import CustomSelectByDependency from "@/core/components/DataTable/filter/fieldsType/CustomSelectByDependency";
import DataTableWithAuth from "@/core/components/DataTableWithAuth"; import DataTableWithAuth from "@/core/components/DataTableWithAuth";
import { GET_MACHINE_MISSIONS_DETAILS } from "@/core/utils/routes"; import { GET_MACHINE_MISSIONS_DETAILS } from "@/core/utils/routes";
import useCities from "@/lib/hooks/useCities";
import useProvinces from "@/lib/hooks/useProvince";
import { Box } from "@mui/material"; import { Box } from "@mui/material";
import { useMemo } from "react"; import { useMemo } from "react";
import Toolbar from "./Toolbar";
const MachineMissionsList = ({ row, specialFilter }) => { const MachineMissionsList = ({ row, specialFilter }) => {
const columns = useMemo( const columns = useMemo(() => {
() => [ const dynamicColumns = {
header: "استان",
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: "کل کشور" },
...provinces.map((province) => ({
value: province.id,
label: province.name_fa,
})),
];
}, [provinces, errorProvinces, loadingProvinces]);
return (
<CustomSelectByDependency
{...props}
value={loadingProvinces ? "loading" : props.filterParameters.value}
columnSelectOption={getColumnSelectOptions}
/>
);
},
Cell: ({ renderedCellValue, row }) => {
return <>{row.original.province_name}</>;
},
};
return [
{ {
accessorKey: "id", accessorKey: "id",
header: "کد یکتا", header: "کد یکتا",
@@ -17,27 +58,52 @@ const MachineMissionsList = ({ row, specialFilter }) => {
grow: false, grow: false,
size: 80, size: 80,
}, },
...[dynamicColumns],
{ {
accessorKey: "province_name",
header: "استان",
id: "province_name",
enableColumnFilter: true,
datatype: "text",
filterMode: "equals",
columnFilterModeOptions: ["equals", "contains"],
grow: false,
size: 100,
},
{
accessorKey: "city_name",
header: "شهر", header: "شهر",
id: "city_name", id: "city_id",
enableColumnFilter: true, enableColumnFilter: true,
datatype: "text", datatype: "numeric",
filterMode: "equals", filterMode: "equals",
columnFilterModeOptions: ["equals", "contains"], dependencyId: "province_id",
grow: false, grow: false,
size: 100, size: 120,
ColumnSelectComponent: (props) => {
const { cityList, loadingCityList, errorCityList } = useCities(props.dependencyFieldValue.value);
const getColumnSelectOptions = useMemo(() => {
if (props.dependencyFieldValue.value === "") {
return [{ value: "empty", label: "ابتدا استان را انتخاب کنید" }];
}
if (loadingCityList) {
return [{ value: "loading", label: "در حال بارگذاری..." }];
}
if (errorCityList) {
return [{ value: "error", label: "خطا در بارگذاری" }];
}
return [
{ value: "", label: "کل ادارات" },
...cityList.map((edare) => ({
value: edare.id,
label: edare.name_fa,
})),
];
}, [cityList, loadingCityList, errorCityList]);
return (
<CustomSelectByDependency
{...props}
value={
props.dependencyFieldValue?.value === ""
? "empty"
: loadingCityList
? "loading"
: props.filterParameters.value
}
columnSelectOption={getColumnSelectOptions}
/>
);
},
Cell: ({ row }) => <>{row.original.city_name}</>,
}, },
{ {
accessorKey: "station_name", accessorKey: "station_name",
@@ -83,15 +149,15 @@ const MachineMissionsList = ({ row, specialFilter }) => {
grow: false, grow: false,
size: 100, size: 100,
}, },
], ];
[] }, []);
);
return ( return (
<> <>
<Box sx={{ mt: 3 }}> <Box sx={{ mt: 3 }}>
<DataTableWithAuth <DataTableWithAuth
specialFilter={specialFilter} specialFilter={specialFilter}
TableToolbar={Toolbar}
need_filter={true} need_filter={true}
columns={columns} columns={columns}
sorting={[{ id: "id", desc: true }]} sorting={[{ id: "id", desc: true }]}

View File

@@ -1,11 +1,9 @@
"use client"; "use client";
import PageTitle from "@/core/components/PageTitle"; 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 { useAuth } from "@/lib/contexts/auth";
import { usePermissions } from "@/lib/hooks/usePermissions"; import { usePermissions } from "@/lib/hooks/usePermissions";
import useRequest from "@/lib/hooks/useRequest";
import { yupResolver } from "@hookform/resolvers/yup"; import { yupResolver } from "@hookform/resolvers/yup";
import { LinearProgress, Stack } from "@mui/material"; import { Stack } from "@mui/material";
import moment from "jalali-moment"; import moment from "jalali-moment";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
@@ -14,10 +12,8 @@ import MachinesReportsList from "./MachinesReportsList";
import SearchReportList from "./Search"; import SearchReportList from "./Search";
const MachinesReportsPage = () => { const MachinesReportsPage = () => {
const [data, setData] = useState(null);
const { data: userPermissions } = usePermissions(); const { data: userPermissions } = usePermissions();
const { user } = useAuth(); const { user } = useAuth();
const requestServer = useRequest();
const hasProvincesPermission = userPermissions?.includes("mission-report-country"); const hasProvincesPermission = userPermissions?.includes("mission-report-country");
const defaultValues = { const defaultValues = {
@@ -32,38 +28,32 @@ const MachinesReportsPage = () => {
]; ];
const [specialFilter, setSpecialFilter] = useState(defaultFilter); const [specialFilter, setSpecialFilter] = useState(defaultFilter);
const onSearchSubmit = async (data) => { const onSearchSubmit = (data) => {
const params = new URLSearchParams(); const filters = [
params.set("from_date", `${data.from_date} 00:00:00`); {
params.set("date_to", `${data.date_to} 23:59:59`); value: `${data.from_date} 00:00:00`,
setSpecialFilter([ datatype: "date",
{ value: `${data.province_id}`, datatype: "numeric", id: "province_id", fn: "equals" }, id: "start_time",
{ value: `${data.from_date} 00:00:00`, datatype: "date", id: "start_time", fn: "greaterThan" }, fn: "greaterThan",
{ value: `${data.date_to} 23:59:59`, datatype: "date", id: "finish_time", fn: "lessThan" }, },
]); {
if (data.province_id === "-1") { value: `${data.date_to} 23:59:59`,
try { datatype: "date",
const response = await requestServer(`${GET_MACHINES_COUNTRY_ACTIVITY_REPORT}?${params}`); id: "finish_time",
const result = response.data.data; fn: "lessThan",
},
];
setData({ if (data.province_id !== "-1") {
data: result.activities, filters.unshift({
filters: data, value: data.province_id,
}); datatype: "numeric",
} catch (e) {} id: "province_id",
} else { fn: "equals",
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) {}
} }
setSpecialFilter(filters);
}; };
useEffect(() => { useEffect(() => {
@@ -100,7 +90,7 @@ const MachinesReportsPage = () => {
handleSubmit={handleSubmit} handleSubmit={handleSubmit}
onSearchSubmit={onSearchSubmit} onSearchSubmit={onSearchSubmit}
/> />
{!data ? <LinearProgress /> : <MachinesReportsList specialFilter={specialFilter} data={data} />} <MachinesReportsList specialFilter={specialFilter} />
</Stack> </Stack>
); );
}; };

View File

@@ -1,10 +1,5 @@
"use client"; "use client";
import { import { EXPORT_GET_MACHINES_TYPE_ACTIVITY_REPORT } from "@/core/utils/routes";
EXPORT_GET_MACHINES_COUNTRY_ACTIVITY_REPORT,
EXPORT_GET_MACHINES_PROVINCE_ACTIVITY_REPORT,
EXPORT_GET_MACHINES_TYPE_COUNTRY_ACTIVITY_REPORT,
EXPORT_GET_MACHINES_TYPE_PROVINCE_ACTIVITY_REPORT,
} from "@/core/utils/routes";
import useRequest from "@/lib/hooks/useRequest"; import useRequest from "@/lib/hooks/useRequest";
import { useTheme } from "@emotion/react"; import { useTheme } from "@emotion/react";
import DescriptionIcon from "@mui/icons-material/Description"; import DescriptionIcon from "@mui/icons-material/Description";
@@ -36,16 +31,12 @@ const PrintExcel = ({ table, filterData }) => {
const clickHandler = () => { const clickHandler = () => {
setLoading(true); setLoading(true);
const CountryOrProvince = activeFilters.find((item) => item.id === "province_id"); const requestUrl = EXPORT_GET_MACHINES_TYPE_ACTIVITY_REPORT;
const requestUrl =
CountryOrProvince.value === "-1"
? EXPORT_GET_MACHINES_TYPE_COUNTRY_ACTIVITY_REPORT
: EXPORT_GET_MACHINES_TYPE_PROVINCE_ACTIVITY_REPORT;
requestServer(`${requestUrl}?${filterParams}`, "get", { requestServer(`${requestUrl}?${filterParams}`, "get", {
requestOptions: { responseType: "blob" }, requestOptions: { responseType: "blob" },
}) })
.then((response) => { .then((response) => {
const filename = `خروجی کارتابل گزارشات گشت راهداری تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`; const filename = `خروجی کارتابل گزارشات نوع ماشین تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`;
FileSaver.saveAs(response.data, filename); FileSaver.saveAs(response.data, filename);
}) })
.catch(() => {}) .catch(() => {})
@@ -68,7 +59,7 @@ const PrintExcel = ({ table, filterData }) => {
disabled={loading} disabled={loading}
sx={{ textTransform: "unset", alignSelf: "center" }} sx={{ textTransform: "unset", alignSelf: "center" }}
startIcon={loading ? <CircularProgress size={18} color="inherit" /> : <DescriptionIcon />} startIcon={loading ? <CircularProgress size={18} color="inherit" /> : <DescriptionIcon />}
onClick={clickHandler} // onClick={clickHandler}
> >
خروجی اکسل خروجی اکسل
</Button> </Button>

View File

@@ -3,17 +3,20 @@ import DataTableWithAuth from "@/core/components/DataTableWithAuth";
import { Box } from "@mui/material"; import { Box } from "@mui/material";
import { useMemo } from "react"; import { useMemo } from "react";
import Toolbar from "./Toolbar"; import Toolbar from "./Toolbar";
// import RowActions from "./RowActions"; import { GET_MACHINES_TYPE_ACTIVITY_REPORT } from "@/core/utils/routes";
import RowActions from "./RowActions";
const MachinesReportsList = ({ data, specialFilter }) => { const MachinesReportsList = ({ specialFilter }) => {
const columns = useMemo(() => { const columns = useMemo(() => {
return [ return [
{ {
accessorKey: "car_type", accessorKey: "car_type",
header: "نوع ماشین", header: "نوع ماشین",
id: "car_type", id: "car_type",
enableColumnFilter: false, enableColumnFilter: true,
enableSorting: false, filterMode: "equals",
columnFilterModeOptions: ["equals", "contains"],
enableSorting: true,
datatype: "text", datatype: "text",
grow: false, grow: false,
size: 50, size: 50,
@@ -23,7 +26,7 @@ const MachinesReportsList = ({ data, specialFilter }) => {
header: "کارکرد", header: "کارکرد",
id: "func", id: "func",
enableColumnFilter: false, enableColumnFilter: false,
enableSorting: false, enableSorting: true,
datatype: "number", datatype: "number",
grow: false, grow: false,
size: 50, size: 50,
@@ -33,7 +36,7 @@ const MachinesReportsList = ({ data, specialFilter }) => {
header: "تعداد ماموریت", header: "تعداد ماموریت",
id: "missions", id: "missions",
enableColumnFilter: false, enableColumnFilter: false,
enableSorting: false, enableSorting: true,
datatype: "number", datatype: "number",
grow: false, grow: false,
size: 50, size: 50,
@@ -46,13 +49,14 @@ const MachinesReportsList = ({ data, specialFilter }) => {
<DataTableWithAuth <DataTableWithAuth
TableToolbar={Toolbar} TableToolbar={Toolbar}
columns={columns} columns={columns}
data={data.data} table_url={GET_MACHINES_TYPE_ACTIVITY_REPORT}
page_name={"roadMissionReportMachineTypeReport"} page_name={"roadMissionReportMachineTypeReport"}
table_name={"roadMissionReportMachineTypeReportList"} table_name={"roadMissionReportMachineTypeReportList"}
enablePagination={false} enablePagination={false}
specialFilter={specialFilter} specialFilter={specialFilter}
// enableRowActions need_filter={true}
// RowActions={RowActions} enableRowActions
RowActions={RowActions}
/> />
</Box> </Box>
); );

View File

@@ -0,0 +1,70 @@
"use client";
import { EXPORT_GET_MACHINES_TYPE_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 requestUrl = EXPORT_GET_MACHINES_TYPE_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 ? (
<IconButton aria-label="خروجی اکسل" color="success" onClick={clickHandler}>
<DescriptionIcon sx={{ fontSize: "25px" }} />
</IconButton>
) : (
<Button
color="success"
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

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

View File

@@ -1,7 +1,8 @@
import DataTableWithAuth from "@/core/components/DataTableWithAuth"; import DataTableWithAuth from "@/core/components/DataTableWithAuth";
import { GET_MACHINE_MISSIONS_DETAILS, GET_MACHINE_TYPE_MISSIONS_DETAILS } from "@/core/utils/routes"; import { GET_MACHINE_TYPE_MISSIONS_DETAILS } from "@/core/utils/routes";
import { Box } from "@mui/material"; import { Box } from "@mui/material";
import { useMemo } from "react"; import { useMemo } from "react";
import Toolbar from "./Toolbar";
const MachineMissionsList = ({ row }) => { const MachineMissionsList = ({ row }) => {
const columns = useMemo( const columns = useMemo(
@@ -91,10 +92,14 @@ const MachineMissionsList = ({ row }) => {
<> <>
<Box sx={{ mt: 3 }}> <Box sx={{ mt: 3 }}>
<DataTableWithAuth <DataTableWithAuth
TableToolbar={Toolbar}
need_filter={true} need_filter={true}
columns={columns} columns={columns}
specialQueries={{
car_type: row.car_type,
}}
sorting={[{ id: "id", desc: true }]} sorting={[{ id: "id", desc: true }]}
table_url={`${GET_MACHINE_TYPE_MISSIONS_DETAILS}?car_type=${row.car_type}`} table_url={GET_MACHINE_TYPE_MISSIONS_DETAILS}
page_name={"roadMissionReportMachineType"} page_name={"roadMissionReportMachineType"}
table_name={"roadMissionReportMachineTypeList"} table_name={"roadMissionReportMachineTypeList"}
positionActionsColumn={"first"} positionActionsColumn={"first"}

View File

@@ -1,6 +1,10 @@
// import MissionDetails from "./MissionDitails"; import MissionDetails from "./MissionDitails";
const RowActions = ({ row }) => { const RowActions = ({ row }) => {
return <>{/*<MissionDetails row={row} />*/}</>; return (
<>
<MissionDetails row={row} />
</>
);
}; };
export default RowActions; export default RowActions;

View File

@@ -1,14 +1,9 @@
"use client"; "use client";
import PageTitle from "@/core/components/PageTitle"; import PageTitle from "@/core/components/PageTitle";
import {
GET_MACHINES_TYPE_COUNTRY_ACTIVITY_REPORT,
GET_MACHINES_TYPE_PROVINCE_ACTIVITY_REPORT,
} from "@/core/utils/routes";
import { useAuth } from "@/lib/contexts/auth"; import { useAuth } from "@/lib/contexts/auth";
import { usePermissions } from "@/lib/hooks/usePermissions"; import { usePermissions } from "@/lib/hooks/usePermissions";
import useRequest from "@/lib/hooks/useRequest";
import { yupResolver } from "@hookform/resolvers/yup"; import { yupResolver } from "@hookform/resolvers/yup";
import { LinearProgress, Stack } from "@mui/material"; import { Stack } from "@mui/material";
import moment from "jalali-moment"; import moment from "jalali-moment";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
@@ -17,10 +12,8 @@ import MachinesReportsList from "./MachinesReportsList";
import SearchReportList from "./Search"; import SearchReportList from "./Search";
const MachinesTypeReportsPage = () => { const MachinesTypeReportsPage = () => {
const [data, setData] = useState(null);
const { data: userPermissions } = usePermissions(); const { data: userPermissions } = usePermissions();
const { user } = useAuth(); const { user } = useAuth();
const requestServer = useRequest();
const hasProvincesPermission = userPermissions?.includes("mission-report-country"); const hasProvincesPermission = userPermissions?.includes("mission-report-country");
const defaultValues = { const defaultValues = {
@@ -30,43 +23,37 @@ const MachinesTypeReportsPage = () => {
}; };
const defaultFilter = [ const defaultFilter = [
{ value: `${defaultValues.province_id}`, datatype: "numeric", id: "province_id", fn: "equals" }, { value: `${defaultValues.province_id}`, datatype: "numeric", id: "province_id", fn: "equals" },
{ value: `${defaultValues.from_date}`, datatype: "date", id: "from_date", fn: "between" }, { value: `${defaultValues.from_date} 00:00:00`, datatype: "date", id: "start_time", fn: "greaterThan" },
{ value: `${defaultValues.date_to}`, datatype: "date", id: "date_to", fn: "between" }, { value: `${defaultValues.date_to} 23:59:59`, datatype: "date", id: "finish_time", fn: "lessThan" },
]; ];
const [specialFilter, setSpecialFilter] = useState(defaultFilter); const [specialFilter, setSpecialFilter] = useState(defaultFilter);
const onSearchSubmit = async (data) => { const onSearchSubmit = (data) => {
const params = new URLSearchParams(); const filters = [
params.set("from_date", `${data.from_date} 00:00:00`); {
params.set("date_to", `${data.date_to} 23:59:59`); value: `${data.from_date} 00:00:00`,
setSpecialFilter([ datatype: "date",
{ value: `${data.province_id}`, datatype: "numeric", id: "province_id", fn: "equals" }, id: "start_time",
{ value: `${data.from_date}`, datatype: "date", id: "from_date", fn: "between" }, fn: "greaterThan",
{ value: `${data.date_to}`, datatype: "date", id: "date_to", fn: "between" }, },
]); {
if (data.province_id === "-1") { value: `${data.date_to} 23:59:59`,
try { datatype: "date",
const response = await requestServer(`${GET_MACHINES_TYPE_COUNTRY_ACTIVITY_REPORT}?${params}`); id: "finish_time",
const result = response.data.data; fn: "lessThan",
},
];
setData({ if (data.province_id !== "-1") {
data: result.activities, filters.unshift({
filters: data, value: data.province_id,
}); datatype: "numeric",
} catch (e) {} id: "province_id",
} else { fn: "equals",
try { });
params.set("province_id", `${data.province_id}`);
const response = await requestServer(`${GET_MACHINES_TYPE_PROVINCE_ACTIVITY_REPORT}?${params}`);
const result = response.data.data;
setData({
data: result.activities,
filters: data,
});
} catch (e) {}
} }
setSpecialFilter(filters);
}; };
useEffect(() => { useEffect(() => {
@@ -103,7 +90,7 @@ const MachinesTypeReportsPage = () => {
handleSubmit={handleSubmit} handleSubmit={handleSubmit}
onSearchSubmit={onSearchSubmit} onSearchSubmit={onSearchSubmit}
/> />
{!data ? <LinearProgress /> : <MachinesReportsList specialFilter={specialFilter} data={data} />} <MachinesReportsList specialFilter={specialFilter} />
</Stack> </Stack>
); );
}; };

View File

@@ -0,0 +1,42 @@
import { Button, DialogActions, DialogContent, Stack, Typography } from "@mui/material";
import React, { useState } from "react";
import useRequest from "@/lib/hooks/useRequest";
import { DELETE_VIOLATION } from "@/core/utils/routes";
const DeleteContent = ({ rowId, mutate, setOpenDeleteDialog }) => {
const [submitting, setSubmitting] = useState(false);
const requestServer = useRequest({ notificationSuccess: true });
const handleClick = () => {
setSubmitting(true);
requestServer(`${DELETE_VIOLATION}/${rowId}`, "delete", {
hasSidebarUpdate: true,
})
.then(() => {
mutate();
setOpenDeleteDialog(false);
setSubmitting(false);
})
.catch(() => {
setSubmitting(false);
});
};
return (
<>
<DialogContent>
<Stack alignItems="center" spacing={2}>
<Typography mt={2}>آیا از حذف تخلف اطمینان دارید؟</Typography>
</Stack>
</DialogContent>
<DialogActions sx={{ justifyContent: "center", paddingBottom: 2, width: "100%" }}>
<Button onClick={() => setOpenDeleteDialog(false)} variant="outlined" color="secondary">
خیر !
</Button>
<Button onClick={handleClick} variant="contained" color="error" disabled={submitting}>
{submitting ? "درحال حذف..." : "بله اطمینان دارم"}
</Button>
</DialogActions>
</>
);
};
export default DeleteContent;

View File

@@ -0,0 +1,33 @@
import { useState } from "react";
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import DeleteIcon from "@mui/icons-material/Delete";
import DeleteContent from "./DeleteContent";
const DeleteViolation = ({ mutate, rowId }) => {
const [openDeleteDialog, setOpenDeleteDialog] = useState(false);
return (
<>
<Tooltip title="حذف">
<IconButton color="error" onClick={() => setOpenDeleteDialog(true)}>
<DeleteIcon />
</IconButton>
</Tooltip>
<Dialog
open={openDeleteDialog}
onClose={() => setOpenDeleteDialog(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"}
>
<DialogTitle>حذف تخلف</DialogTitle>
<DeleteContent rowId={rowId} mutate={mutate} setOpenDeleteDialog={setOpenDeleteDialog} />
</Dialog>
</>
);
};
export default DeleteViolation;

View File

@@ -1,5 +1,6 @@
// import CreateWithoutProcess from "../Actions/CreateWithoutProcess"; // import CreateWithoutProcess from "../Actions/CreateWithoutProcess";
import EditViolation from "../Actions/EditViolation"; import EditViolation from "../Actions/EditViolation";
import DeleteViolation from "../Actions/DeleteViolation";
const RowActions = ({ row, mutate }) => { const RowActions = ({ row, mutate }) => {
// const canEdit = row.original.status === 0 && row.original.type === 1; // const canEdit = row.original.status === 0 && row.original.type === 1;
@@ -7,6 +8,7 @@ const RowActions = ({ row, mutate }) => {
<> <>
{!row.original.mileage && <EditViolation row={row} mutate={mutate} rowId={row.getValue("id")} />} {!row.original.mileage && <EditViolation row={row} mutate={mutate} rowId={row.getValue("id")} />}
{/*{canEdit && <CreateWithoutProcess row={row} mutate={mutate} />}*/} {/*{canEdit && <CreateWithoutProcess row={row} mutate={mutate} />}*/}
<DeleteViolation rowId={row.getValue("id")} mutate={mutate} />
</> </>
); );
}; };

View File

@@ -61,23 +61,6 @@ const ViolationsList = () => {
columnFilterModeOptions: ["equals", "contains"], columnFilterModeOptions: ["equals", "contains"],
grow: false, grow: false,
}, },
{
accessorKey: "status",
header: "وضعیت",
id: "status",
enableColumnFilter: true,
datatype: "numeric",
filterMode: "equals",
sortDescFirst: true,
grow: false,
columnSelectOption: () => {
return violationsCategoryStatus.map((category) => ({
value: category.id,
label: category.name_fa,
}));
},
Cell: ({ row }) => (row.original.type === 1 ? "خروج بدون مجوز" : "عدم تحرک"),
},
{ {
accessorKey: "machine_code", accessorKey: "machine_code",
header: "کد خودرو", header: "کد خودرو",
@@ -142,16 +125,6 @@ const ViolationsList = () => {
grow: false, grow: false,
Cell: ({ row }) => row.original.machine?.car_name || "-", Cell: ({ row }) => row.original.machine?.car_name || "-",
}, },
{
accessorKey: "mission_id",
header: "کد ماموریت",
id: "mission_id",
enableColumnFilter: false,
datatype: "numeric",
filterMode: "equals",
grow: false,
Cell: ({ row }) => row.original.mission_id || "-",
},
{ {
accessorKey: "request_date", accessorKey: "request_date",
header: "تاریخ تخلف", header: "تاریخ تخلف",

View File

@@ -38,6 +38,7 @@ const DataTable_Main = (props) => {
RowActions, RowActions,
specific_data, specific_data,
specialFilter, specialFilter,
specialQueries,
} = props; } = props;
const flatColumns = flattenArrayOfObjects(columns, "columns"); const flatColumns = flattenArrayOfObjects(columns, "columns");
const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 }); const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 });
@@ -70,8 +71,15 @@ const DataTable_Main = (props) => {
})) }))
) )
); );
if (specialQueries) {
Object.entries(specialQueries).forEach(([key, value]) => {
if (value !== undefined && value !== null && value !== "") {
params.set(key, String(value));
}
});
}
return `${table_url}?${params}`; return `${table_url}?${params}`;
}, [table_url, filterData, pagination, sortData, specialFilter]); }, [table_url, filterData, pagination, sortData, specialFilter, specialQueries]);
const fetcher = async (url) => { const fetcher = async (url) => {
try { try {
@@ -152,7 +160,12 @@ const DataTable_Main = (props) => {
renderTopToolbarCustomActions: ({ table }) => ( renderTopToolbarCustomActions: ({ table }) => (
<> <>
{TableToolbar && ( {TableToolbar && (
<TableToolbar table={table} mutate={mutate} filterData={specialFilter || filterData} /> <TableToolbar
table={table}
mutate={mutate}
filterData={specialFilter || filterData}
specialFilterData={filterData}
/>
)} )}
</> </>
), ),

View File

@@ -249,24 +249,28 @@ 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_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_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_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_ACTIVITY_REPORT = api + "/api/v3/missions/report_machine/machines_activity";
export const GET_MACHINES_PROVINCE_ACTIVITY_REPORT = api + "/api/v3/missions/report_machine/province_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 = export const EXPORT_GET_MACHINES_COUNTRY_ACTIVITY_REPORT =
api + "/api/v3/missions/report_machine/country_machines_activity_excel"; api + "/api/v3/missions/report_machine/country_machines_activity_excel";
export const EXPORT_GET_MACHINES_TYPE_ACTIVITY_REPORT = api + "/api/v3/missions/report_machine/machines_activity_excel";
export const EXPORT_GET_MACHINES_PROVINCE_ACTIVITY_REPORT = export const EXPORT_GET_MACHINES_PROVINCE_ACTIVITY_REPORT =
api + "/api/v3/missions/report_machine/province_machines_activity_excel"; api + "/api/v3/missions/report_machine/province_machines_activity_excel";
export const EXPORT_GET_MACHINES_ACTIVITY_REPORT = api + "/api/v3/missions/report_machine/machines_activity_excel";
export const GET_DRIVER_COUNTRY_ACTIVITY_REPORT = export const GET_DRIVERS_ACTIVITY_REPORT = api + "/api/v3/missions/report_machine/machine_drivers_activity";
api + "/api/v3/missions/report_machine/country_machine_drivers_activity";
export const GET_DRIVER_PROVINCE_ACTIVITY_REPORT = export const GET_DRIVER_PROVINCE_ACTIVITY_REPORT =
api + "/api/v3/missions/report_machine/province_machine_drivers_activity"; api + "/api/v3/missions/report_machine/province_machine_drivers_activity";
export const EXPORT_GET_DRIVER_COUNTRY_ACTIVITY_REPORT = export const EXPORT_GET_DRIVER_COUNTRY_ACTIVITY_REPORT =
api + "/api/v3/missions/report_machine/country_machine_drivers_activity_excel"; api + "/api/v3/missions/report_machine/country_machine_drivers_activity_excel";
export const EXPORT_GET_DRIVER_ACTIVITY_REPORT = api + "/api/v3/missions/report_machine/machine_drivers_activity_excel";
export const EXPORT_GET_DRIVER_DETAILS_ACTIVITY_REPORT =
api + "/api/v3/missions/report_machine/machine_driver_details_report_excel";
export const EXPORT_GET_DRIVER_PROVINCE_ACTIVITY_REPORT = export const EXPORT_GET_DRIVER_PROVINCE_ACTIVITY_REPORT =
api + "/api/v3/missions/report_machine/province_machine_drivers_activity_excel"; api + "/api/v3/missions/report_machine/province_machine_drivers_activity_excel";
export const GET_MACHINES_TYPE_COUNTRY_ACTIVITY_REPORT = export const GET_MACHINES_TYPE_ACTIVITY_REPORT = api + "/api/v3/missions/report_machine/machine_types_activity";
api + "/api/v3/missions/report_machine/country_machine_types_activity";
export const GET_MACHINES_TYPE_PROVINCE_ACTIVITY_REPORT = export const GET_MACHINES_TYPE_PROVINCE_ACTIVITY_REPORT =
api + "/api/v3/missions/report_machine/province_machine_types_activity"; api + "/api/v3/missions/report_machine/province_machine_types_activity";
export const EXPORT_GET_MACHINES_TYPE_COUNTRY_ACTIVITY_REPORT = export const EXPORT_GET_MACHINES_TYPE_COUNTRY_ACTIVITY_REPORT =
@@ -275,6 +279,7 @@ export const EXPORT_GET_MACHINES_TYPE_PROVINCE_ACTIVITY_REPORT =
api + "/api/v3/missions/report_machine/province_machine_types_activity_excel"; api + "/api/v3/missions/report_machine/province_machine_types_activity_excel";
export const CREATE_VIOLATION = api + "/api/v3/missions/violation_management"; export const CREATE_VIOLATION = api + "/api/v3/missions/violation_management";
export const EDIT_VIOLATION = api + "/api/v3/missions/violation_management"; export const EDIT_VIOLATION = api + "/api/v3/missions/violation_management";
export const DELETE_VIOLATION = api + "/api/v3/missions/violation_management";
export const EXPORT_COUNTRY_ROAD_MISSIONS_REPORTS = api + "/api/v3/missions/report/country_excel_activity"; export const EXPORT_COUNTRY_ROAD_MISSIONS_REPORTS = api + "/api/v3/missions/report/country_excel_activity";
export const EXPORT_PROVINCE_ROAD_MISSIONS_REPORTS = api + "/api/v3/missions/report/province_excel_activity"; export const EXPORT_PROVINCE_ROAD_MISSIONS_REPORTS = api + "/api/v3/missions/report/province_excel_activity";