diff --git a/src/components/dashboard/azmayesh/AzmayeshList.jsx b/src/components/dashboard/azmayesh/AzmayeshList.jsx index a93940c..904c50c 100644 --- a/src/components/dashboard/azmayesh/AzmayeshList.jsx +++ b/src/components/dashboard/azmayesh/AzmayeshList.jsx @@ -21,7 +21,7 @@ const AzmayeshList = () => { datatype: "text", filterMode: "notEquals", grow: false, - size: 100 + size: 100, }, { accessorKey: "province_name", diff --git a/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUChooseLocation.jsx b/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUChooseLocation.jsx index 030eac8..542945b 100644 --- a/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUChooseLocation.jsx +++ b/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUChooseLocation.jsx @@ -23,7 +23,7 @@ import VerifiedIcon from "@mui/icons-material/Verified"; import EditIcon from "@mui/icons-material/Edit"; import { useTheme } from "@emotion/react"; -const MAX_ZOOM_FOR_MARKER = 13 +const MAX_ZOOM_FOR_MARKER = 13; const CandUChooseLocation = ({ mapBoxData, setMapBoxData }) => { const theme = useTheme(); @@ -43,7 +43,7 @@ const CandUChooseLocation = ({ mapBoxData, setMapBoxData }) => { const map = useMapEvents({ move(e) { - setEnableSend(e.target.getZoom() > MAX_ZOOM_FOR_MARKER) + setEnableSend(e.target.getZoom() > MAX_ZOOM_FOR_MARKER); if (!mapBoxData) { mapAzmayeshMarker.current.setLatLng(e.target.getCenter()); } @@ -59,8 +59,8 @@ const CandUChooseLocation = ({ mapBoxData, setMapBoxData }) => { } }, zoom(e) { - setEnableSend(e.target.getZoom() > MAX_ZOOM_FOR_MARKER) - } + setEnableSend(e.target.getZoom() > MAX_ZOOM_FOR_MARKER); + }, }); useEffect(() => { @@ -74,9 +74,8 @@ const CandUChooseLocation = ({ mapBoxData, setMapBoxData }) => { } }, [mapBoxData, mapAzmayeshMarker.current]); - const handleMarkerClick = () => { - if (!enableSend) return + if (!enableSend) return; if (!mapBoxData) { setMapBoxData({ lat: mapAzmayeshMarker.current.getLatLng().lat, @@ -91,44 +90,44 @@ const CandUChooseLocation = ({ mapBoxData, setMapBoxData }) => { return ( <> - + - برای ثبت محل آزمایش، لطفاً نقشه را بیشتر زوم کنید. + + برای ثبت محل آزمایش، لطفاً نقشه را بیشتر زوم کنید. + - + diff --git a/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/FormAndRequest.jsx b/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/FormAndRequest.jsx index 358451d..8421abf 100644 --- a/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/FormAndRequest.jsx +++ b/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/FormAndRequest.jsx @@ -119,8 +119,7 @@ const CandUAzmayesh = ({ setOpen, mutate, updateInfo, rowId }) => { }); mutate(); handleClose(); - } catch (error) { - } + } catch (error) {} }; return ( @@ -191,8 +190,8 @@ const CandUAzmayesh = ({ setOpen, mutate, updateInfo, rowId }) => { ? "در حال ویرایش آزمایش" : "ویرایش آزمایش" : isSubmitting - ? "در حال ثبت آزمایش" - : "ثبت آزمایش"} + ? "در حال ثبت آزمایش" + : "ثبت آزمایش"} )} diff --git a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/index.jsx b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/index.jsx index a369fc9..cc64ec6 100644 --- a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/index.jsx +++ b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/index.jsx @@ -14,7 +14,7 @@ const ShowSampleOfAzmayesh = ({ rowData }) => { .then((response) => { setSampleInfo(response.data.data); }) - .catch(() => { }) + .catch(() => {}) .finally(() => { setOpenShowSampleDialog(true); }); diff --git a/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/RoadSafetyForm/RoadSafetyFormContext.jsx b/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/RoadSafetyForm/RoadSafetyFormContext.jsx index a1492fd..d9cd72d 100644 --- a/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/RoadSafetyForm/RoadSafetyFormContext.jsx +++ b/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/RoadSafetyForm/RoadSafetyFormContext.jsx @@ -57,7 +57,7 @@ const RoadSafetyFormContext = ({ rowId, mutate, setOpenRoadSafetyForm }) => { setOpenRoadSafetyForm(false); mutate(); }) - .catch(() => { }); + .catch(() => {}); }; return ( diff --git a/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/RowActions/Refer/ReferFormContext.jsx b/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/RowActions/Refer/ReferFormContext.jsx index 01127c4..fbc6c47 100644 --- a/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/RowActions/Refer/ReferFormContext.jsx +++ b/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/RowActions/Refer/ReferFormContext.jsx @@ -50,7 +50,7 @@ const ReferFormContext = ({ setOpenReferDialog, rowId, mutate }) => { setOpenReferDialog(false); mutate(); }) - .catch(() => { }); + .catch(() => {}); }; return ( diff --git a/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/RoadSafetyForm/RoadSafetyFormContext.jsx b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/RoadSafetyForm/RoadSafetyFormContext.jsx index 8acd6f7..c480382 100644 --- a/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/RoadSafetyForm/RoadSafetyFormContext.jsx +++ b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/RoadSafetyForm/RoadSafetyFormContext.jsx @@ -57,7 +57,7 @@ const RoadSafetyFormContext = ({ rowId, mutate, setOpenRoadSafetyForm }) => { setOpenRoadSafetyForm(false); mutate(); }) - .catch(() => { }); + .catch(() => {}); }; return ( diff --git a/src/components/dashboard/roadItems/operator/Actions/Create/Forms/CreateFormContent.jsx b/src/components/dashboard/roadItems/operator/Actions/Create/Forms/CreateFormContent.jsx index e05531b..de60a7e 100644 --- a/src/components/dashboard/roadItems/operator/Actions/Create/Forms/CreateFormContent.jsx +++ b/src/components/dashboard/roadItems/operator/Actions/Create/Forms/CreateFormContent.jsx @@ -34,7 +34,7 @@ const defaultValues = { start_date: "", before_image: null, after_image: null, - cmms_machine_id: null, + cmms_machines: null, rahdaran_id: null, start_point: "", end_point: "", @@ -43,7 +43,7 @@ const validationSchema = object({ itemId: string().required("نوع آیتم را مشخص کنید!"), itemSubId: string().required("موضوع مشاهده شده را مشخص کنید!"), amount: string().required("وارد کردن مقدار الزامیست!"), - cmms_machine_id: object().required("وارد کردن کد خودرو الزامیست!"), + cmms_machines: array().required("وارد کردن کد خودرو الزامیست!"), rahdaran_id: array().required("وارد کردن کد راهداران الزامیست!").min(1, "حداقل یک کد راهدار باید وارد شود!"), // بررسی حداقل یک آیتم, action_date: string().required("لطفا زمان فعالیت را انتخاب کنید!"), start_date: string().required("لطفاً تاریخ شروع فعالیت را انتخاب کنید!"), @@ -82,12 +82,11 @@ const validationSchema = object({ }), }); -const CreateFormContent = ({ setOpen, mutate, rowId }) => { +const CreateFormContent = ({ setOpen, mutate, onSubmit }) => { const [tabState, setTabState] = useState(0); const [itemsList, setItemsList] = useState(); const [subItemsList, setSubItemsList] = useState([]); const theme = useTheme(); - const requestServer = useRequest({ notificationSuccess: true }); const isMobile = useMediaQuery(theme.breakpoints.down("sm")); const handleClose = () => { setOpen(false); @@ -98,6 +97,20 @@ const CreateFormContent = ({ setOpen, mutate, rowId }) => { }; const handlePrev = () => { + if (tabState === 2) { + const fieldsToReset = [ + "amount", + "action_date", + "start_date", + "before_image", + "after_image", + "cmms_machines", + "rahdaran_id", + "start_point", + "end_point", + ]; + fieldsToReset.forEach((field) => resetField(field)); + } if (tabState === 0) { handleClose(); } else { @@ -111,6 +124,7 @@ const CreateFormContent = ({ setOpen, mutate, rowId }) => { register, handleSubmit, setValue, + resetField, formState: { errors, isSubmitting }, } = useForm({ defaultValues, @@ -119,32 +133,6 @@ const CreateFormContent = ({ setOpen, mutate, rowId }) => { context: { subItemsList }, }); - const onSubmit = async (data) => { - console.log(data); - let endPoint; - let startPoint = `${data.start_point.lat},${data.start_point.lng}`; - data.end_point !== "" && (endPoint = `${data.end_point.lat},${data.end_point.lng}`); - const formData = new FormData(); - data.rahdaran_id.map((rahdar, index) => formData.append(`rahdaran_id[${index}]`, rahdar.id)); - formData.append("item_id", data.itemId); - formData.append("sub_item_id", data.itemSubId); - formData.append("amount", data.amount); - formData.append("activity_time", data.action_date); - formData.append("activity_date", data.start_date); - formData.append("cmms_machine_id", data.cmms_machine_id.id); - data.before_image !== null && formData.append("before_image", data.before_image); - data.after_image !== null && formData.append("after_image", data.after_image); - data.start_point !== "" && formData.append("start_point", startPoint); - data.end_point !== "" && formData.append("end_point", endPoint); - requestServer(CREATE_ROAD_ITEMS, "post", { - data: formData, - }) - .then((response) => { - mutate(); - setOpen(false); - }) - .catch((error) => {}); - }; return ( { return ( @@ -16,12 +17,14 @@ const GetItemInfo = ({ register, itemsList, subItemsList, control, setValue, err - { return ( field.onChange(value || null)} + carCode={field.value || []} + setCarCode={(value) => field.onChange(value || [])} error={error} + multiple={true} /> ); }} - name={"cmms_machine_id"} + name={"cmms_machines"} /> diff --git a/src/components/dashboard/roadItems/operator/Actions/Create/Forms/index.jsx b/src/components/dashboard/roadItems/operator/Actions/Create/Forms/index.jsx index 52c2d42..d47352a 100644 --- a/src/components/dashboard/roadItems/operator/Actions/Create/Forms/index.jsx +++ b/src/components/dashboard/roadItems/operator/Actions/Create/Forms/index.jsx @@ -1,11 +1,39 @@ "use client"; import { Dialog } from "@mui/material"; import CreateFormContent from "@/components/dashboard/roadItems/operator/Actions/Create/Forms/CreateFormContent"; +import { CREATE_ROAD_ITEMS } from "@/core/utils/routes"; +import useRequest from "@/lib/hooks/useRequest"; const OperatorCreateForm = ({ open, setOpen, mutate, rowId }) => { + const requestServer = useRequest({ notificationSuccess: true }); + const HandleSubmit = async (data) => { + let endPoint; + let startPoint = `${data.start_point.lat},${data.start_point.lng}`; + data.end_point !== "" && (endPoint = `${data.end_point.lat},${data.end_point.lng}`); + const formData = new FormData(); + data.rahdaran_id.map((rahdar, index) => formData.append(`rahdaran_id[${index}]`, rahdar.id)); + formData.append("item_id", data.itemId); + formData.append("sub_item_id", data.itemSubId); + formData.append("amount", data.amount); + formData.append("activity_time", data.action_date); + formData.append("activity_date", data.start_date); + data.cmms_machines.map((machine, index) => formData.append(`machines_id[${index}]`, machine.id)); + data.before_image !== null && formData.append("before_image", data.before_image); + data.after_image !== null && formData.append("after_image", data.after_image); + data.start_point !== "" && formData.append("start_point", startPoint); + data.end_point !== "" && formData.append("end_point", endPoint); + await requestServer(CREATE_ROAD_ITEMS, "post", { + data: formData, + }) + .then((response) => { + mutate(); + setOpen(false); + }) + .catch((error) => {}); + }; return ( - + ); }; diff --git a/src/components/dashboard/roadItems/operator/ExcelPrint/index.jsx b/src/components/dashboard/roadItems/operator/ExcelPrint/index.jsx index 605018e..4cf871f 100644 --- a/src/components/dashboard/roadItems/operator/ExcelPrint/index.jsx +++ b/src/components/dashboard/roadItems/operator/ExcelPrint/index.jsx @@ -39,7 +39,7 @@ const PrintExcel = ({ table, filterData }) => { const filename = `خروجی کارتابل فعالیت روزانه تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`; FileSaver.saveAs(response.data, filename); }) - .catch(() => { }) + .catch(() => {}) .finally(() => { setLoading(false); }); diff --git a/src/components/dashboard/roadItems/operator/OperatorList.jsx b/src/components/dashboard/roadItems/operator/OperatorList.jsx index aed25de..c5cfaba 100644 --- a/src/components/dashboard/roadItems/operator/OperatorList.jsx +++ b/src/components/dashboard/roadItems/operator/OperatorList.jsx @@ -1,16 +1,26 @@ "use client"; -import { useMemo } from "react"; -import { Box, Stack, Typography } from "@mui/material"; +import CustomSelectByDependency from "@/core/components/DataTable/filter/fieldsType/CustomSelectByDependency"; import DataTableWithAuth from "@/core/components/DataTableWithAuth"; -import Toolbar from "./Toolbar"; import { GET_ROAD_ITEMS_OPERATOR_LIST } from "@/core/utils/routes"; +import useRoadItemGetSubItems from "@/lib/hooks/useRoadItemGetISubtems"; +import useRoadItemGetItems from "@/lib/hooks/useRoadItemGetItems"; +import { Box, Stack, Typography } from "@mui/material"; import moment from "jalali-moment"; +import { useMemo } from "react"; import RowActions from "./RowActions"; -import LocationForm from "./RowActions/LocationForm"; import ImageDialog from "./RowActions/ImageForm"; +import LocationForm from "./RowActions/LocationForm"; import RahdaranDialog from "./RowActions/RahdaranForm"; +import Toolbar from "./Toolbar"; +import DescriptionForm from "./RowActions/DescriptionForm"; +import MachinesCodeDialog from "./RowActions/MachinesCodeForm"; const OperatorList = () => { + const statusOptions = [ + { value: 0, label: "درحال بررسی" }, + { value: 1, label: "تایید" }, + { value: 2, label: "عدم تایید" }, + ]; const columns = useMemo( () => [ { @@ -21,24 +31,78 @@ const OperatorList = () => { datatype: "text", filterMode: "equals", columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, }, { accessorKey: "item_fa", header: "آیتم فعالیت", id: "item_fa", enableColumnFilter: true, - datatype: "text", + datatype: "numeric", filterMode: "equals", - columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + ColumnSelectComponent: (props) => { + const { itemsList, loadingItemsList, errorItemsList } = useRoadItemGetItems(); + + const getColumnSelectOptions = () => { + if (loadingItemsList) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorItemsList) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: props.column.header }, + ...itemsList.map((item) => ({ + value: item.id, + label: item.name, + })), + ]; + }; + + const columnSelectOption = getColumnSelectOptions(); + + return ; + }, }, { accessorKey: "sub_item_fa", - header: "موضوع مشاهده شده", // Observed Subject + header: "موضوع مشاهده شده", id: "sub_item_fa", enableColumnFilter: true, - datatype: "text", + datatype: "numeric", filterMode: "equals", - columnFilterModeOptions: ["equals", "contains"], + dependencyId: "item_fa", + ColumnSelectComponent: (props) => { + const { subItemsList, loadingSubItemsList, errorSubItemsList } = useRoadItemGetSubItems( + props.dependencyFieldValue.value + ); + + const getColumnSelectOptions = () => { + if (props.dependencyFieldValue.value === "") { + return [{ value: "empty", label: "ابتدا آیتم فعالیت را انتخاب کنید" }]; + } + if (loadingSubItemsList) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorSubItemsList) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: props.column.header }, + ...subItemsList.map((item) => ({ + value: item.id, + label: item.name, + })), + ]; + }; + + const columnSelectOption = getColumnSelectOptions(); + + return ; + }, }, { accessorKey: "value", @@ -48,11 +112,17 @@ const OperatorList = () => { datatype: "text", filterMode: "equals", columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 120, Cell: ({ renderedCellValue, row }) => { return ( - - {row.original.sub_item_data} - {`(${row.original.unit_fa})`} + + + {(row.original.sub_item_data / 1).toLocaleString()} + + + {`(${row.original.unit_fa})`} + ); }, @@ -64,6 +134,8 @@ const OperatorList = () => { enableColumnFilter: false, enableSorting: false, datatype: "array", + grow: false, + size: 100, muiTableBodyCellProps: { sx: { borderLeft: "1px solid #e1e1e1", @@ -95,6 +167,8 @@ const OperatorList = () => { enableColumnFilter: false, enableSorting: false, datatype: "array", + grow: false, + size: 100, muiTableBodyCellProps: { sx: { borderLeft: "1px solid #e1e1e1", @@ -118,14 +192,35 @@ const OperatorList = () => { }, }, { - accessorKey: "cmms_machine_code", + accessorKey: "cmms_machines", header: "کد خودرو", // Car ID - id: "cmms_machine_code", + id: "cmmsMachines__machine_code", enableColumnFilter: true, datatype: "text", - filterMode: "equals", + filterMode: "contains", enableSorting: false, columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + muiTableBodyCellProps: { + sx: { + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ renderedCellValue }) => { + if (renderedCellValue) { + return ( + + + + ); + } + return کد خودرویی وجود ندارد; + }, }, { accessorKey: "rahdaran", @@ -134,6 +229,8 @@ const OperatorList = () => { enableColumnFilter: false, enableSorting: false, datatype: "array", + grow: false, + size: 100, muiTableBodyCellProps: { sx: { borderLeft: "1px solid #e1e1e1", @@ -162,6 +259,8 @@ const OperatorList = () => { datatype: "date", filterMode: "equals", columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, }, { accessorFn: (row) => moment(row.activity_date_time).locale("fa").format("HH:mm | yyyy/MM/DD"), @@ -171,25 +270,53 @@ const OperatorList = () => { datatype: "date", filterMode: "equals", columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, }, { - accessorKey: "status_fa", + accessorKey: "status", header: "وضعیت", // Status - id: "status_fa", + id: "status", enableColumnFilter: true, - datatype: "text", + datatype: "numeric", filterMode: "equals", sortDescFirst: true, - columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + columnSelectOption: () => { + return statusOptions.map((status) => ({ + value: status.value, + label: status.label, + })); + }, + Cell: ({ renderedCellValue, row }) => <>{row.original.status_fa}, }, { accessorKey: "supervisor_description", - header: "توضیحات", // Description + header: "توضیحات کارشناس", // Description id: "supervisor_description", enableColumnFilter: false, datatype: "text", filterMode: "equals", columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 70, + muiTableBodyCellProps: { + sx: { + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ renderedCellValue }) => { + return ( + + + + ); + }, }, ], [] @@ -202,7 +329,7 @@ const OperatorList = () => { need_filter={true} columns={columns} sorting={[ - { id: "status_fa", desc: true }, + { id: "status", desc: true }, { id: "id", desc: true }, ]} table_url={GET_ROAD_ITEMS_OPERATOR_LIST} diff --git a/src/components/dashboard/roadItems/operator/RowActions/DescriptionForm/index.jsx b/src/components/dashboard/roadItems/operator/RowActions/DescriptionForm/index.jsx new file mode 100644 index 0000000..3f748c9 --- /dev/null +++ b/src/components/dashboard/roadItems/operator/RowActions/DescriptionForm/index.jsx @@ -0,0 +1,51 @@ +import { Dialog, DialogContent, DialogTitle, IconButton, Tooltip, Typography, Card, CardContent } from "@mui/material"; +import { useState } from "react"; +import RemoveRedEyeIcon from "@mui/icons-material/RemoveRedEye"; +import CloseIcon from "@mui/icons-material/Close"; + +const DescriptionForm = ({ description }) => { + const [openOfficerDescriptionDialog, setOpenOfficerDescriptionDialog] = useState(false); + + return ( + <> + + setOpenOfficerDescriptionDialog(true)}> + + + + setOpenOfficerDescriptionDialog(false)} + PaperProps={{ + sx: { + transition: "all .3s", + boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px", + borderRadius: 2, + padding: 1, + }, + }} + maxWidth="sm" + fullWidth + dir="rtl" + > + + + توضیحات کارشناس + + setOpenOfficerDescriptionDialog(false)} size="small"> + + + + + + + {description || "هیچ توضیحی موجود نیست"} + + + + + + ); +}; + +export default DescriptionForm; diff --git a/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditController.jsx b/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditController.jsx new file mode 100644 index 0000000..423bb00 --- /dev/null +++ b/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditController.jsx @@ -0,0 +1,29 @@ +import { LinearProgress, Typography } from "@mui/material"; +import EditFormContent from "./EditFormContent"; +import useRoadItemGetISubtems from "@/lib/hooks/useRoadItemGetISubtems"; + +const EditController = ({ rowId, mutate, setOpenEditDialog, row }) => { + const { subItemsList, loadingSubItemsList, errorSubItemsList } = useRoadItemGetISubtems(row.original?.item); + const subItem = subItemsList.find((SubItem) => SubItem.sub_item === row.original?.sub_item); + + return ( + <> + {errorSubItemsList ? ( + + خطا در دریافت اطلاعات!!! + + ) : loadingSubItemsList ? ( + + ) : ( + + )} + + ); +}; +export default EditController; diff --git a/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormContent.jsx b/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormContent.jsx index 460d64d..92f7432 100644 --- a/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormContent.jsx +++ b/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormContent.jsx @@ -12,10 +12,11 @@ import { UPDATE_ROAD_ITEMS } from "@/core/utils/routes"; import CarCode from "@/core/components/CarCode"; import RahdarCode from "@/core/components/RahdarCode"; import useRoadItemGetISubtems from "@/lib/hooks/useRoadItemGetISubtems"; +import NumberField from "@/core/components/NumberField"; const validationSchema = object({ amount: string().required("وارد کردن مقدار الزامیست!"), - cmms_machine_id: object().required("وارد کردن کد خودرو الزامیست!"), + cmms_machines: array().required("وارد کردن کد خودرو الزامیست!"), rahdaran_id: array().required("وارد کردن کد راهداران الزامیست!").min(1, "حداقل یک کد راهدار باید وارد شود!"), before_image: mixed() .nullable() @@ -59,7 +60,7 @@ const EditFormContent = ({ row, mutate, setOpenEditDialog, rowId, subItem }) => amount: row.original.sub_item_data || null, start_point: { lat: row.original.start_lat || "", lng: row.original.start_lng || "" }, end_point: { lat: row.original.end_lat || "", lng: row.original.end_lng || "" }, - cmms_machine_id: row.original.cmms_machine, + cmms_machines: row.original.cmms_machines || null, rahdaran_id: row.original.rahdaran || null, }; const requestServer = useRequest(); @@ -91,12 +92,12 @@ const EditFormContent = ({ row, mutate, setOpenEditDialog, rowId, subItem }) => data.after_image !== defaultValues.after_image && formData.append("after_image", data.after_image); formData.append("amount", data.amount); - formData.append("cmms_machine_id", data.cmms_machine_id.id); + data.cmms_machines.map((machine, index) => formData.append(`machines_id[${index}]`, machine.id)); data.rahdaran_id.map((rahdar, index) => formData.append(`rahdaran_id[${index}]`, rahdar.id)); formData.append("start_point", startPoint); subItem.needs_end_point === 1 && formData.append("end_point", endPoint); - requestServer(`${UPDATE_ROAD_ITEMS}/${rowId}`, "post", { + await requestServer(`${UPDATE_ROAD_ITEMS}/${rowId}`, "post", { notificationSuccess: true, data: formData, }) @@ -104,8 +105,9 @@ const EditFormContent = ({ row, mutate, setOpenEditDialog, rowId, subItem }) => mutate(); setOpenEditDialog(false); }) - .catch((err) => { }); + .catch((err) => {}); }; + return ( <> @@ -124,11 +126,14 @@ const EditFormContent = ({ row, mutate, setOpenEditDialog, rowId, subItem }) => ) : null} - setValue("amount", watch("amount")); } }} - error={!!errors.amount} helperText={errors.amount ? errors.amount.message : null} variant="outlined" fullWidth @@ -153,14 +157,15 @@ const EditFormContent = ({ row, mutate, setOpenEditDialog, rowId, subItem }) => render={({ field, fieldState: { error } }) => { return ( field.onChange(value || "")} - inputValueDefault={row.original.cmms_machine_code} + carCode={field.value || []} + setCarCode={(value) => field.onChange(value || [])} + inputValueDefault={row.original.cmms_machines} + multiple={true} error={error} // اگر خطا وجود داشته باشد /> ); }} - name={"cmms_machine_id"} + name={"cmms_machines"} /> diff --git a/src/components/dashboard/roadItems/operator/RowActions/EditForm/index.jsx b/src/components/dashboard/roadItems/operator/RowActions/EditForm/index.jsx index 92652e9..888e166 100644 --- a/src/components/dashboard/roadItems/operator/RowActions/EditForm/index.jsx +++ b/src/components/dashboard/roadItems/operator/RowActions/EditForm/index.jsx @@ -1,13 +1,11 @@ -import { Dialog, DialogTitle, IconButton, LinearProgress, Tooltip, Typography } from "@mui/material"; +import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material"; import { useState } from "react"; import BorderColorIcon from "@mui/icons-material/BorderColor"; -import EditFormContent from "@/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormContent"; -import useRoadItemGetISubtems from "@/lib/hooks/useRoadItemGetISubtems"; +import EditController from "./EditController"; const EditForm = ({ row, mutate, rowId }) => { const [openEditDialog, setOpenEditDialog] = useState(false); - const { subItemsList, loadingSubItemsList, errorSubItemsList } = useRoadItemGetISubtems(row.original?.item); - const subItem = subItemsList.find((subItem) => subItem.sub_item === row.original?.sub_item); + return ( <> @@ -32,21 +30,7 @@ const EditForm = ({ row, mutate, rowId }) => { }} > ویرایش اطلاعات - {errorSubItemsList ? ( - - خطا در دریافت اطلاعات!!! - - ) : loadingSubItemsList ? ( - - ) : ( - - )} + ); diff --git a/src/components/dashboard/roadItems/operator/RowActions/MachinesCodeForm/MachinesCodeContent.jsx b/src/components/dashboard/roadItems/operator/RowActions/MachinesCodeForm/MachinesCodeContent.jsx new file mode 100644 index 0000000..1eef774 --- /dev/null +++ b/src/components/dashboard/roadItems/operator/RowActions/MachinesCodeForm/MachinesCodeContent.jsx @@ -0,0 +1,55 @@ +import { DialogContent, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from "@mui/material"; +import ShowPlak from "@/core/components/ShowPlak"; + +const MachinesCodeContent = ({ machinesLists }) => { + return ( + <> + + + + + + + کد ماشین + نام خودرو + پلاک + + + + {machinesLists.map((machine) => { + return ( + + {machine.machine_code} + {machine.car_name} + + {machine.plak_number ? ( + + ) : null} + + + ); + })} + +
+
+
+
+ + ); +}; +export default MachinesCodeContent; diff --git a/src/components/dashboard/roadItems/operator/RowActions/MachinesCodeForm/index.jsx b/src/components/dashboard/roadItems/operator/RowActions/MachinesCodeForm/index.jsx new file mode 100644 index 0000000..d8e8754 --- /dev/null +++ b/src/components/dashboard/roadItems/operator/RowActions/MachinesCodeForm/index.jsx @@ -0,0 +1,43 @@ +import { Button, Dialog, DialogActions, DialogTitle, IconButton, Tooltip } from "@mui/material"; +import DirectionsCarIcon from "@mui/icons-material/DirectionsCar"; +import { useState } from "react"; +import MachinesCodeContent from "./MachinesCodeContent"; + +const MachinesCodeDialog = ({ machinesLists }) => { + const [openMachinesCodeDialog, setOpenMachinesCodeDialog] = useState(false); + return ( + <> + + setOpenMachinesCodeDialog(true)}> + + + + setOpenMachinesCodeDialog(false)} + PaperProps={{ + sx: { + boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px", + }, + }} + dir="rtl" + maxWidth={"md"} + > + کد خودرو + + + + + + + ); +}; +export default MachinesCodeDialog; diff --git a/src/components/dashboard/roadItems/supervisor/RowActions/ConfirmForm/ConfirmContent.jsx b/src/components/dashboard/roadItems/supervisor/RowActions/ConfirmForm/ConfirmContent.jsx index f4be809..ebc2556 100644 --- a/src/components/dashboard/roadItems/supervisor/RowActions/ConfirmForm/ConfirmContent.jsx +++ b/src/components/dashboard/roadItems/supervisor/RowActions/ConfirmForm/ConfirmContent.jsx @@ -28,7 +28,7 @@ const ConfirmContent = ({ rowId, mutate, setOpenConfirmDialog }) => { mutate(); setOpenConfirmDialog(false); }) - .catch(() => { }); + .catch(() => {}); }; return ( diff --git a/src/components/dashboard/roadItems/supervisor/RowActions/MachinesCodeForm/MachinesCodeContent.jsx b/src/components/dashboard/roadItems/supervisor/RowActions/MachinesCodeForm/MachinesCodeContent.jsx new file mode 100644 index 0000000..1eef774 --- /dev/null +++ b/src/components/dashboard/roadItems/supervisor/RowActions/MachinesCodeForm/MachinesCodeContent.jsx @@ -0,0 +1,55 @@ +import { DialogContent, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from "@mui/material"; +import ShowPlak from "@/core/components/ShowPlak"; + +const MachinesCodeContent = ({ machinesLists }) => { + return ( + <> + + + + + + + کد ماشین + نام خودرو + پلاک + + + + {machinesLists.map((machine) => { + return ( + + {machine.machine_code} + {machine.car_name} + + {machine.plak_number ? ( + + ) : null} + + + ); + })} + +
+
+
+
+ + ); +}; +export default MachinesCodeContent; diff --git a/src/components/dashboard/roadItems/supervisor/RowActions/MachinesCodeForm/index.jsx b/src/components/dashboard/roadItems/supervisor/RowActions/MachinesCodeForm/index.jsx new file mode 100644 index 0000000..d8e8754 --- /dev/null +++ b/src/components/dashboard/roadItems/supervisor/RowActions/MachinesCodeForm/index.jsx @@ -0,0 +1,43 @@ +import { Button, Dialog, DialogActions, DialogTitle, IconButton, Tooltip } from "@mui/material"; +import DirectionsCarIcon from "@mui/icons-material/DirectionsCar"; +import { useState } from "react"; +import MachinesCodeContent from "./MachinesCodeContent"; + +const MachinesCodeDialog = ({ machinesLists }) => { + const [openMachinesCodeDialog, setOpenMachinesCodeDialog] = useState(false); + return ( + <> + + setOpenMachinesCodeDialog(true)}> + + + + setOpenMachinesCodeDialog(false)} + PaperProps={{ + sx: { + boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px", + }, + }} + dir="rtl" + maxWidth={"md"} + > + کد خودرو + + + + + + + ); +}; +export default MachinesCodeDialog; diff --git a/src/components/dashboard/roadItems/supervisor/RowActions/RejectForm/RejectContent.jsx b/src/components/dashboard/roadItems/supervisor/RowActions/RejectForm/RejectContent.jsx index 81cc311..5fc6794 100644 --- a/src/components/dashboard/roadItems/supervisor/RowActions/RejectForm/RejectContent.jsx +++ b/src/components/dashboard/roadItems/supervisor/RowActions/RejectForm/RejectContent.jsx @@ -36,7 +36,7 @@ const RejectContent = ({ rowId, mutate, setOpenRejectDialog }) => { mutate(); setOpenRejectDialog(false); }) - .catch(() => { }) + .catch(() => {}) .finally(() => { reset(); }); diff --git a/src/components/dashboard/roadItems/supervisor/SupervisorList.jsx b/src/components/dashboard/roadItems/supervisor/SupervisorList.jsx index 1166ed6..4f3420b 100644 --- a/src/components/dashboard/roadItems/supervisor/SupervisorList.jsx +++ b/src/components/dashboard/roadItems/supervisor/SupervisorList.jsx @@ -8,8 +8,19 @@ import RowActions from "./RowActions"; import LocationForm from "./RowActions/LocationForm"; import ImageDialog from "./RowActions/ImageForm"; import RahdaranDialog from "./RowActions/RahdaranForm"; +import CustomSelectByDependency from "@/core/components/DataTable/filter/fieldsType/CustomSelectByDependency"; +import useProvinces from "@/lib/hooks/useProvince"; +import useRoadItemGetItems from "@/lib/hooks/useRoadItemGetItems"; +import useRoadItemGetSubItems from "@/lib/hooks/useRoadItemGetISubtems"; +import useEdaratLists from "@/lib/hooks/useEdaratLists"; +import MachinesCodeDialog from "./RowActions/MachinesCodeForm"; const SupervisorList = () => { + const statusOptions = [ + { value: 0, label: "درحال بررسی" }, + { value: 1, label: "تایید" }, + { value: 2, label: "عدم تایید" }, + ]; const columns = useMemo( () => [ { @@ -21,42 +32,141 @@ const SupervisorList = () => { filterMode: "equals", sortDescFirst: false, columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, }, { - accessorKey: "province_fa", + accessorKey: "province_id", header: "استان", // Province - id: "province_fa", + id: "province_id", enableColumnFilter: true, - datatype: "text", + datatype: "numeric", filterMode: "equals", - columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 130, + ColumnSelectComponent: (props) => { + const { provinces, errorProvinces, loadingProvinces } = useProvinces(); + const getColumnSelectOptions = () => { + if (loadingProvinces) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorProvinces) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: props.column.header }, + ...provinces.map((province) => ({ + value: province.id, + label: province.name_fa, + })), + ]; + }; + const columnSelectOption = getColumnSelectOptions(); + return ; + }, + Cell: ({ renderedCellValue, row }) => <>{row.original.province_fa}, }, { - accessorKey: "edarat_name", + accessorKey: "edarat_id", header: "اداره", // Office - id: "edarat_name", + id: "edarat_id", enableColumnFilter: true, - datatype: "text", + datatype: "numeric", filterMode: "equals", - columnFilterModeOptions: ["equals", "contains"], + dependencyId: "province_id", + grow: false, + size: 120, + ColumnSelectComponent: (props) => { + const { edaratList, loadingEdaratList, errorEdaratList } = useEdaratLists( + props.dependencyFieldValue.value + ); + + const getColumnSelectOptions = () => { + if (props.dependencyFieldValue.value === "") { + return [{ value: "empty", label: "ابتدا استان را انتخاب کنید" }]; + } + if (loadingEdaratList) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorEdaratList) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: props.column.header }, + ...edaratList.map((edare) => ({ + value: edare.id, + label: edare.name_fa, + })), + ]; + }; + const columnSelectOption = getColumnSelectOptions(); + return ; + }, + Cell: ({ renderedCellValue, row }) => <>{row.original.edarat_name}, }, { accessorKey: "item_fa", header: "آیتم فعالیت", id: "item_fa", enableColumnFilter: true, - datatype: "text", + datatype: "numeric", filterMode: "equals", - columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + ColumnSelectComponent: (props) => { + const { itemsList, loadingItemsList, errorItemsList } = useRoadItemGetItems(); + const getColumnSelectOptions = () => { + if (loadingItemsList) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorItemsList) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: props.column.header }, + ...itemsList.map((item) => ({ + value: item.id, + label: item.name, + })), + ]; + }; + const columnSelectOption = getColumnSelectOptions(); + return ; + }, }, { accessorKey: "sub_item_fa", - header: "موضوع مشاهده شده", // Observed Subject + header: "موضوع مشاهده شده", id: "sub_item_fa", enableColumnFilter: true, - datatype: "text", + datatype: "numeric", filterMode: "equals", - columnFilterModeOptions: ["equals", "contains"], + dependencyId: "item_fa", + ColumnSelectComponent: (props) => { + const { subItemsList, loadingSubItemsList, errorSubItemsList } = useRoadItemGetSubItems( + props.dependencyFieldValue.value + ); + const getColumnSelectOptions = () => { + if (props.dependencyFieldValue.value === "") { + return [{ value: "empty", label: "ابتدا آیتم فعالیت را انتخاب کنید" }]; + } + if (loadingSubItemsList) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorSubItemsList) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: props.column.header }, + ...subItemsList.map((item) => ({ + value: item.id, + label: item.name, + })), + ]; + }; + const columnSelectOption = getColumnSelectOptions(); + return ; + }, }, { accessorKey: "value", @@ -65,12 +175,18 @@ const SupervisorList = () => { enableColumnFilter: false, datatype: "text", filterMode: "equals", + grow: false, + size: 120, columnFilterModeOptions: ["equals", "contains"], Cell: ({ renderedCellValue, row }) => { return ( - - {row.original.sub_item_data} - {`(${row.original.unit_fa})`} + + + {(row.original.sub_item_data / 1).toLocaleString()} + + + {`(${row.original.unit_fa})`} + ); }, @@ -82,6 +198,8 @@ const SupervisorList = () => { enableColumnFilter: false, enableSorting: false, datatype: "array", + grow: false, + size: 100, muiTableBodyCellProps: { sx: { borderLeft: "1px solid #e1e1e1", @@ -113,6 +231,8 @@ const SupervisorList = () => { enableColumnFilter: false, enableSorting: false, datatype: "array", + grow: false, + size: 100, muiTableBodyCellProps: { sx: { borderLeft: "1px solid #e1e1e1", @@ -136,14 +256,35 @@ const SupervisorList = () => { }, }, { - accessorKey: "cmms_machine_code", + accessorKey: "cmms_machines", header: "کد خودرو", // Car ID - id: "cmms_machine_code", + id: "cmmsMachines__machine_code", enableColumnFilter: true, datatype: "text", - filterMode: "equals", + filterMode: "contains", enableSorting: false, columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + muiTableBodyCellProps: { + sx: { + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ renderedCellValue }) => { + if (renderedCellValue) { + return ( + + + + ); + } + return کد خودرویی وجود ندارد; + }, }, { accessorKey: "rahdaran", @@ -152,6 +293,8 @@ const SupervisorList = () => { enableColumnFilter: false, enableSorting: false, datatype: "array", + grow: false, + size: 100, muiTableBodyCellProps: { sx: { borderLeft: "1px solid #e1e1e1", @@ -180,6 +323,8 @@ const SupervisorList = () => { datatype: "date", filterMode: "equals", columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, }, { accessorFn: (row) => moment(row.activity_date_time).locale("fa").format("HH:mm | yyyy/MM/DD"), @@ -189,25 +334,26 @@ const SupervisorList = () => { datatype: "date", filterMode: "equals", columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, }, { - accessorKey: "status_fa", + accessorKey: "status", header: "وضعیت", // Status - id: "status_fa", + id: "status", enableColumnFilter: true, - datatype: "text", + datatype: "numeric", filterMode: "equals", sortDescFirst: true, - columnFilterModeOptions: ["equals", "contains"], - }, - { - accessorKey: "supervisor_description", - header: "توضیحات", // Description - id: "supervisor_description", - enableColumnFilter: false, - datatype: "text", - filterMode: "equals", - columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + columnSelectOption: () => { + return statusOptions.map((status) => ({ + value: status.value, + label: status.label, + })); + }, + Cell: ({ renderedCellValue, row }) => <>{row.original.status_fa}, }, ], [] @@ -220,7 +366,7 @@ const SupervisorList = () => { need_filter={true} columns={columns} sorting={[ - { id: "status_fa", desc: false }, + { id: "status", desc: false }, { id: "id", desc: true }, ]} table_url={GET_ROAD_ITEMS_SUPERVISOR_LIST} diff --git a/src/components/dashboard/roadPatrols/operator/OperatorList.jsx b/src/components/dashboard/roadPatrols/operator/OperatorList.jsx index 05f083b..a68bdcc 100644 --- a/src/components/dashboard/roadPatrols/operator/OperatorList.jsx +++ b/src/components/dashboard/roadPatrols/operator/OperatorList.jsx @@ -18,6 +18,8 @@ const OperatorList = () => { datatype: "text", filterMode: "equals", columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, }, { accessorKey: "operator_name", @@ -29,9 +31,9 @@ const OperatorList = () => { columnFilterModeOptions: ["equals", "contains"], }, { - accessorKey: "phone_number", + accessorKey: "officer_phone_number", header: "تلفن همراه", - id: "phone_number", + id: "officer_phone_number", enableColumnFilter: true, datatype: "text", filterMode: "equals", @@ -47,46 +49,37 @@ const OperatorList = () => { columnFilterModeOptions: ["equals", "contains"], }, { - accessorKey: "start_date", + accessorFn: (row) => moment(row.start_date).locale("fa").format("HH:mm | yyyy/MM/DD"), header: "تاریخ شروع", id: "start_date", enableColumnFilter: true, datatype: "date", filterMode: "equals", columnFilterModeOptions: ["equals", "contains"], - Cell: ({ renderedCellValue }) => ( - - {renderedCellValue ? moment(renderedCellValue).locale("fa").format("YYYY/MM/DD") : "-"} - - ), + grow: false, + size: 100, }, { - accessorKey: "end_date", + accessorFn: (row) => moment(row.end_date).locale("fa").format("HH:mm | yyyy/MM/DD"), header: "تاریخ پایان", id: "end_date", enableColumnFilter: true, datatype: "date", filterMode: "equals", columnFilterModeOptions: ["equals", "contains"], - Cell: ({ renderedCellValue }) => ( - - {renderedCellValue ? moment(renderedCellValue).locale("fa").format("YYYY/MM/DD") : "-"} - - ), + grow: false, + size: 100, }, { - accessorKey: "register_date", + accessorFn: (row) => moment(row.register_date).locale("fa").format("HH:mm | yyyy/MM/DD"), header: "تاریخ ثبت", id: "register_date", enableColumnFilter: true, datatype: "date", filterMode: "equals", columnFilterModeOptions: ["equals", "contains"], - Cell: ({ renderedCellValue }) => ( - - {renderedCellValue ? moment(renderedCellValue).locale("fa").format("YYYY/MM/DD") : "-"} - - ), + grow: false, + size: 100, }, ], [] @@ -99,6 +92,7 @@ const OperatorList = () => { table_title={"عملیات"} need_filter={true} columns={columns} + sorting={[{ id: "id", desc: true }]} table_url={GET_ROAD_PATROL_OPERATOR_LIST} page_name={"operator"} table_name={"operatorList"} diff --git a/src/components/dashboard/roadPatrols/operator/RowActions/ReportForm/index.jsx b/src/components/dashboard/roadPatrols/operator/RowActions/ReportForm/index.jsx index 38c98f2..8abb152 100644 --- a/src/components/dashboard/roadPatrols/operator/RowActions/ReportForm/index.jsx +++ b/src/components/dashboard/roadPatrols/operator/RowActions/ReportForm/index.jsx @@ -2,7 +2,7 @@ import { Tooltip, IconButton } from "@mui/material"; import PrintIcon from "@mui/icons-material/Print"; const ReportForm = ({ rowId }) => { - const reportUrl = "https://rms.rmto.ir/v2/road_patrols/operator/report/97314"; // TODO replace id here + const reportUrl = "https://rms.rmto.ir/v2/road_patrols/operator/report/96872"; // TODO replace id here return ( diff --git a/src/components/dashboard/roadPatrols/supervisor/RowActions/ReportForm/index.jsx b/src/components/dashboard/roadPatrols/supervisor/RowActions/ReportForm/index.jsx index ec373f6..8abb152 100644 --- a/src/components/dashboard/roadPatrols/supervisor/RowActions/ReportForm/index.jsx +++ b/src/components/dashboard/roadPatrols/supervisor/RowActions/ReportForm/index.jsx @@ -2,7 +2,7 @@ import { Tooltip, IconButton } from "@mui/material"; import PrintIcon from "@mui/icons-material/Print"; const ReportForm = ({ rowId }) => { - const reportUrl = "https://rms.rmto.ir/v2/road_patrols/operator/report/541938"; // TODO replace id here + const reportUrl = "https://rms.rmto.ir/v2/road_patrols/operator/report/96872"; // TODO replace id here return ( diff --git a/src/components/dashboard/roadPatrols/supervisor/SupervisorList.jsx b/src/components/dashboard/roadPatrols/supervisor/SupervisorList.jsx index a5e15f4..5d71669 100644 --- a/src/components/dashboard/roadPatrols/supervisor/SupervisorList.jsx +++ b/src/components/dashboard/roadPatrols/supervisor/SupervisorList.jsx @@ -7,10 +7,11 @@ import { GET_ROAD_PATROL_SUPERVISOR_LIST } from "@/core/utils/routes"; import moment from "jalali-moment"; import RowActions from "./RowActions"; import useProvinces from "@/lib/hooks/useProvince"; +import useRoadItemGetItems from "@/lib/hooks/useRoadItemGetItems"; +import CustomSelectByDependency from "@/core/components/DataTable/filter/fieldsType/CustomSelectByDependency"; +import useEdaratLists from "@/lib/hooks/useEdaratLists"; const OperatorList = () => { - const { provinces, errorProvinces, loadingProvinces } = useProvinces(); - const citiesListApi = "https://rms.rmto.ir/public/contents/edarate_shahri_by_province"; const columns = useMemo( () => [ { @@ -21,44 +22,74 @@ const OperatorList = () => { datatype: "text", filterMode: "equals", columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, }, { - accessorKey: "province", + accessorKey: "province_id", header: "استان", - id: "province", + id: "province_id", enableColumnFilter: true, datatype: "numeric", filterMode: "equals", - columnSelectOption: () => { - if (loadingProvinces) { - return [{ value: "", label: "در حال بارگذاری..." }]; - } - - if (errorProvinces) { - return [{ value: "", label: "خطا در بارگذاری" }]; - } - - return provinces.map((province) => ({ - value: province.id, - label: province.name_fa, - })); + ColumnSelectComponent: (props) => { + const { provinces, errorProvinces, loadingProvinces } = useProvinces(); + const getColumnSelectOptions = () => { + if (loadingProvinces) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorProvinces) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: props.column.header }, + ...provinces.map((province) => ({ + value: province.id, + label: province.name_fa, + })), + ]; + }; + const columnSelectOption = getColumnSelectOptions(); + return ; }, + Cell: ({ renderedCellValue, row }) => <>{row.original.province_fa}, }, { - accessorKey: "office", + accessorKey: "edare_id", header: "اداره", - id: "office", + id: "edare_id", enableColumnFilter: true, datatype: "numeric", filterMode: "equals", - dependencyId: "province", - columnSelectOption: (dependencyField) => { - if (dependencyField.value === "") { - return [{ value: "", label: "ابتدا استان را انتخاب کنید" }]; - } - - return [{ value: dependencyField.value, label: dependencyField.value }]; + dependencyId: "province_id", + grow: false, + size: 120, + ColumnSelectComponent: (props) => { + const { edaratList, loadingEdaratList, errorEdaratList } = useEdaratLists( + props.dependencyFieldValue.value + ); + const getColumnSelectOptions = () => { + if (props.dependencyFieldValue.value === "") { + return [{ value: "empty", label: "ابتدا استان را انتخاب کنید" }]; + } + if (loadingEdaratList) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorEdaratList) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: props.column.header }, + ...edaratList.map((edare) => ({ + value: edare.id, + label: edare.name_fa, + })), + ]; + }; + const columnSelectOption = getColumnSelectOptions(); + return ; }, + Cell: ({ renderedCellValue, row }) => <>{row.original.edare_name}, }, { accessorKey: "operator_name", @@ -70,9 +101,9 @@ const OperatorList = () => { columnFilterModeOptions: ["equals", "contains"], }, { - accessorKey: "phone_number", + accessorKey: "officer_phone_number", header: "تلفن همراه", - id: "phone_number", + id: "officer_phone_number", enableColumnFilter: true, datatype: "text", filterMode: "equals", @@ -88,49 +119,40 @@ const OperatorList = () => { columnFilterModeOptions: ["equals", "contains"], }, { - accessorKey: "start_date", + accessorFn: (row) => moment(row.start_date).locale("fa").format("HH:mm | yyyy/MM/DD"), header: "تاریخ شروع", id: "start_date", enableColumnFilter: true, datatype: "date", filterMode: "equals", columnFilterModeOptions: ["equals", "contains"], - Cell: ({ renderedCellValue }) => ( - - {renderedCellValue ? moment(renderedCellValue).locale("fa").format("YYYY/MM/DD") : "-"} - - ), + grow: false, + size: 100, }, { - accessorKey: "end_date", + accessorFn: (row) => moment(row.end_date).locale("fa").format("HH:mm | yyyy/MM/DD"), header: "تاریخ پایان", id: "end_date", enableColumnFilter: true, datatype: "date", filterMode: "equals", columnFilterModeOptions: ["equals", "contains"], - Cell: ({ renderedCellValue }) => ( - - {renderedCellValue ? moment(renderedCellValue).locale("fa").format("YYYY/MM/DD") : "-"} - - ), + grow: false, + size: 100, }, { - accessorKey: "register_date", + accessorFn: (row) => moment(row.register_date).locale("fa").format("HH:mm | yyyy/MM/DD"), header: "تاریخ ثبت", id: "register_date", enableColumnFilter: true, datatype: "date", filterMode: "equals", columnFilterModeOptions: ["equals", "contains"], - Cell: ({ renderedCellValue }) => ( - - {renderedCellValue ? moment(renderedCellValue).locale("fa").format("YYYY/MM/DD") : "-"} - - ), + grow: false, + size: 100, }, ], - [provinces] + [] ); return ( @@ -140,6 +162,7 @@ const OperatorList = () => { table_title={"ارزیابی"} need_filter={true} columns={columns} + sorting={[{ id: "id", desc: true }]} table_url={GET_ROAD_PATROL_SUPERVISOR_LIST} page_name={"supervisor"} table_name={"supervisorList"} diff --git a/src/core/components/CarCode.jsx b/src/core/components/CarCode.jsx index 32a4c20..e765d24 100644 --- a/src/core/components/CarCode.jsx +++ b/src/core/components/CarCode.jsx @@ -4,11 +4,12 @@ import useRequest from "@/lib/hooks/useRequest"; import { debounce } from "@mui/material/utils"; import { GET_CAR_LIST_SEARCH } from "@/core/utils/routes"; -const CarCode = ({ carCode, setCarCode, inputValueDefault = "", error }) => { +const CarCode = ({ carCode, setCarCode, inputValueDefault = "", error, multiple = false }) => { const [inputValue, setInputValue] = useState(inputValueDefault); const [options, setOptions] = useState([]); const [loading, setLoading] = useState(false); const requestServer = useRequest(); + const fetchCarCodes = (inputValue, controller) => { const debouncer = debounce((query) => { if (!query || query?.length < 3) { @@ -40,20 +41,32 @@ const CarCode = ({ carCode, setCarCode, inputValueDefault = "", error }) => { return ( { - setCarCode(newValue || null); // Set an empty string if no value is selected + setCarCode(multiple ? newValue || [] : newValue || null); }} inputValue={inputValue} onInputChange={(event, newInputValue) => { setInputValue(newInputValue || ""); // Prevent inputValue from being null or undefined }} options={options} - getOptionLabel={(option) => (typeof option === "string" ? option : option.machine_code)} + getOptionLabel={(option) => { + if (typeof option === "string") return option; + const { machine_code, car_name, plak_number } = option; + let label = `${machine_code || ""}`; + if (car_name) { + label += ` | ${car_name}`; + } + if (plak_number) { + label += ` | ${plak_number}`; + } + return label; + }} isOptionEqualToValue={(option, value) => { - if (!value) return false; // Handle null/undefined values - if (value === "") return option.machine_code === ""; // Handle empty string case + if (!value) return false; + if (value === "") return option.machine_code === ""; return option.machine_code === (value?.machine_code || value); }} loading={loading} @@ -65,8 +78,8 @@ const CarCode = ({ carCode, setCarCode, inputValueDefault = "", error }) => { {...params} label="کد خودرو" fullWidth - error={!!error} // نمایش خطا - helperText={error?.message} // پیام خطا + error={!!error} + helperText={error?.message} InputProps={{ ...params.InputProps, endAdornment: ( diff --git a/src/core/components/DataTable/Main.js b/src/core/components/DataTable/Main.js index a530987..14d8788 100644 --- a/src/core/components/DataTable/Main.js +++ b/src/core/components/DataTable/Main.js @@ -44,7 +44,7 @@ const DataTable_Main = (props) => { .filter((filter) => !isValueEmpty(filter.value)) .map(({ filterMode, id, ...rest }) => ({ ...rest, - id: id.replace(/__/g, '.'), + id: id.replace(/__/g, "."), fn: filterMode, })); diff --git a/src/core/components/DataTable/filter/FilterBodyController.jsx b/src/core/components/DataTable/filter/FilterBodyController.jsx index df3ba62..c3f70ad 100644 --- a/src/core/components/DataTable/filter/FilterBodyController.jsx +++ b/src/core/components/DataTable/filter/FilterBodyController.jsx @@ -2,7 +2,7 @@ import { Controller, useWatch } from "react-hook-form"; import FilterBodyField from "./FilterBodyField"; const FilterBodyController = ({ column, control, reset, errors }) => { - const dependencyField = useWatch({ control, name: column?.dependencyId }); + const dependencyField = useWatch({ control, name: column.dependencyId }); return ( { filterParameters={value} handleChange={onChange} handleBlur={onBlur} - dependencyFieldValue={dependencyField || null} + dependencyFieldValue={column.dependencyId ? dependencyField : null} resetForm={() => reset()} errors={errors} /> diff --git a/src/core/components/DataTable/filter/FilterBodyField.jsx b/src/core/components/DataTable/filter/FilterBodyField.jsx index 4783f13..869c354 100644 --- a/src/core/components/DataTable/filter/FilterBodyField.jsx +++ b/src/core/components/DataTable/filter/FilterBodyField.jsx @@ -54,10 +54,13 @@ function FilterBodyField({ return ; } if (filterParameters.filterMode === "equals") { - return ; + return column.ColumnSelectComponent ? ( + + ) : ( + + ); } break; - case "date": if (filterParameters.filterMode === "equals") { return ; diff --git a/src/core/components/DataTable/filter/fieldsType/CustomSelectByDependency.jsx b/src/core/components/DataTable/filter/fieldsType/CustomSelectByDependency.jsx new file mode 100644 index 0000000..5658bdd --- /dev/null +++ b/src/core/components/DataTable/filter/fieldsType/CustomSelectByDependency.jsx @@ -0,0 +1,53 @@ +"use client"; + +import { FormControl, FormHelperText, InputLabel, MenuItem, OutlinedInput, Select, Typography } from "@mui/material"; +import { useCallback, useEffect } from "react"; + +function CustomSelectByDependency({ + column, + filterParameters, + defaultFilterTranslation, + handleChange, + columnSelectOption, +}) { + const isValidValue = columnSelectOption.some((option) => option.value === filterParameters.value); + + const handleInvalidValue = useCallback(() => { + if (!isValidValue && filterParameters.value !== "") { + handleChange({ ...filterParameters, value: columnSelectOption[0]?.value || "" }); + } + }, [isValidValue, filterParameters, handleChange, columnSelectOption]); + + useEffect(() => { + handleInvalidValue(); + }, [handleInvalidValue]); + + const selectedValue = isValidValue ? filterParameters.value : columnSelectOption[0]?.value || ""; + + return ( + + {column.header} + + + + نوع فیلتر: {defaultFilterTranslation} + + + + ); +} + +export default CustomSelectByDependency; diff --git a/src/core/components/DataTable/filter/index.jsx b/src/core/components/DataTable/filter/index.jsx index 32a09a8..8399857 100644 --- a/src/core/components/DataTable/filter/index.jsx +++ b/src/core/components/DataTable/filter/index.jsx @@ -9,14 +9,16 @@ function FilterColumn({ columns, user_id, page_name, table_name }) { return ( <> - + {open && ( + + )} ); } diff --git a/src/core/components/DataTable/reset/ResetStorage.jsx b/src/core/components/DataTable/reset/ResetStorage.jsx index 8e83d3f..7994867 100644 --- a/src/core/components/DataTable/reset/ResetStorage.jsx +++ b/src/core/components/DataTable/reset/ResetStorage.jsx @@ -6,7 +6,7 @@ import useDataTable from "@/lib/hooks/useDataTable"; function ResetStorage({ user_id, page_name, table_name }) { const { resetAction } = useTableSetting(); - const { isDirty } = useDataTable(); + const { isAnyDirty } = useDataTable(); const reset = () => { resetAction(user_id, page_name, table_name); }; @@ -14,7 +14,7 @@ function ResetStorage({ user_id, page_name, table_name }) { return ( - {isDirty ? ( + {isAnyDirty ? ( { }; console.log(itemInfo); - const label = itemInfo.unit ? `${itemInfo.name} (${itemInfo.unit})` : itemInfo.name + const label = itemInfo.unit ? `${itemInfo.name} (${itemInfo.unit})` : itemInfo.name; return ( diff --git a/src/core/components/FormMaker/SelectType.jsx b/src/core/components/FormMaker/SelectType.jsx index c9f8221..3292b65 100644 --- a/src/core/components/FormMaker/SelectType.jsx +++ b/src/core/components/FormMaker/SelectType.jsx @@ -9,7 +9,7 @@ const SelectType = ({ itemInfo, defaultValues, setDefaultValues }) => { [itemInfo.id]: newValue, })); }; - const label = itemInfo.unit ? `${itemInfo.name} (${itemInfo.unit})` : itemInfo.name + const label = itemInfo.unit ? `${itemInfo.name} (${itemInfo.unit})` : itemInfo.name; return ( {label} diff --git a/src/core/components/MapInfoOneMarker.jsx b/src/core/components/MapInfoOneMarker.jsx index 7132d5d..95ccc2b 100644 --- a/src/core/components/MapInfoOneMarker.jsx +++ b/src/core/components/MapInfoOneMarker.jsx @@ -2,7 +2,7 @@ import React, { useEffect, useRef, useState } from "react"; import { Marker, useMapEvents } from "react-leaflet"; import "leaflet/dist/leaflet.css"; import L from "leaflet"; -import { Box, Button, Typography } from "@mui/material"; +import { Alert, Box, Button, Stack, Typography, Zoom } from "@mui/material"; import dynamic from "next/dynamic"; import MapLoading from "@/core/components/MapLayer/Loading"; import HereIcon from "@/assets/images/examine_marker_active.png"; @@ -40,9 +40,11 @@ const createCustomIcon = (size, iconUrl, labelText) => { popupAnchor: [0, -size[1]], }); }; +const MAX_ZOOM_FOR_MARKER = 13; const MapInteraction = ({ setValue, startLat, startLng }) => { const [isMarkerLocked, setIsMarkerLocked] = useState(!!(startLat && startLng)); // وضعیت قفل مارکر + const [enableSend, setEnableSend] = useState(false); const [markerPosition, setMarkerPosition] = useState( startLat && startLng ? { lat: startLat, lng: startLng } : null ); @@ -50,11 +52,13 @@ const MapInteraction = ({ setValue, startLat, startLng }) => { const map = useMapEvents({ move(e) { + setEnableSend(e.target.getZoom() > MAX_ZOOM_FOR_MARKER); if (!isMarkerLocked && markerRef.current) { markerRef.current.setLatLng(e.target.getCenter()); } }, zoom(e) { + setEnableSend(e.target.getZoom() > MAX_ZOOM_FOR_MARKER); if (!isMarkerLocked && markerRef.current) { markerRef.current.setLatLng(e.target.getCenter()); } @@ -69,6 +73,7 @@ const MapInteraction = ({ setValue, startLat, startLng }) => { }, [startLat, startLng, map]); const handleMarkerClick = () => { + if (!enableSend) return; if (!isMarkerLocked) { const center = map.getCenter(); setValue("start_point", { lat: center.lat.toString(), lng: center.lng.toString() }); @@ -93,6 +98,23 @@ const MapInteraction = ({ setValue, startLat, startLng }) => { click: handleMarkerClick, }} /> + + + + برای ثبت محل فعالیت، لطفاً نقشه را بیشتر زوم کنید. + + + {isMarkerLocked && ( { popupAnchor: [0, -size[1]], }); }; +const MAX_ZOOM_FOR_MARKER = 13; const MapInteraction = ({ setValue, startLat, startLng, endLat, endLng }) => { const [isStartLocked, setIsStartLocked] = useState(!!(startLat && startLng)); // وضعیت قفل نقطه آغاز const [isEndLocked, setIsEndLocked] = useState(!!(endLat && endLng)); // وضعیت قفل نقطه پایان const [startPosition, setStartPosition] = useState(startLat && startLng ? { lat: startLat, lng: startLng } : null); const [endPosition, setEndPosition] = useState(endLat && endLng ? { lat: endLat, lng: endLng } : null); + const [enableSend, setEnableSend] = useState(false); const startRef = useRef(); const endRef = useRef(); const map = useMapEvents({ move(e) { + setEnableSend(e.target.getZoom() > MAX_ZOOM_FOR_MARKER); if (!isStartLocked && startRef.current) { startRef.current.setLatLng(e.target.getCenter()); } else if (isStartLocked && !isEndLocked && endRef.current) { @@ -58,6 +61,7 @@ const MapInteraction = ({ setValue, startLat, startLng, endLat, endLng }) => { } }, zoom(e) { + setEnableSend(e.target.getZoom() > MAX_ZOOM_FOR_MARKER); if (!isStartLocked && startRef.current) { startRef.current.setLatLng(e.target.getCenter()); } else if (isStartLocked && !isEndLocked && endRef.current) { @@ -101,6 +105,7 @@ const MapInteraction = ({ setValue, startLat, startLng, endLat, endLng }) => { icon={createCustomIcon([35, 35], StartIcon.src, "نقطه شروع")} eventHandlers={{ click: () => { + if (!enableSend) return; if (!isStartLocked) { const center = map.getCenter(); setValue("start_point", { lat: center.lat.toString(), lng: center.lng.toString() }); @@ -110,6 +115,23 @@ const MapInteraction = ({ setValue, startLat, startLng, endLat, endLng }) => { }, }} /> + + + + برای ثبت محل فعالیت، لطفاً نقشه را بیشتر زوم کنید. + + + {isStartLocked && !isEndLocked && ( { )} {isStartLocked && ( - { - if (!isEndLocked) { - const center = map.getCenter(); - setValue("end_point", { lat: center.lat.toString(), lng: center.lng.toString() }); - setEndPosition({ lat: center.lat, lng: center.lng }); - setIsEndLocked(true); - } - }, - }} - /> + <> + + + + برای ثبت محل فعالیت، لطفاً نقشه را بیشتر زوم کنید. + + + + { + if (!enableSend) return; + if (!isEndLocked) { + const center = map.getCenter(); + setValue("end_point", { lat: center.lat.toString(), lng: center.lng.toString() }); + setEndPosition({ lat: center.lat, lng: center.lng }); + setIsEndLocked(true); + } + }, + }} + /> + )} {isEndLocked && ( { + return ( + + + + {(props.value / 1).toLocaleString()} + + + {props.unit} + + + + ), + }} + /> + ); +}); +NumberField.displayName = "NumberField"; +export default NumberField; diff --git a/src/core/components/RahdarCode.jsx b/src/core/components/RahdarCode.jsx index 9dfeeb7..76592ef 100644 --- a/src/core/components/RahdarCode.jsx +++ b/src/core/components/RahdarCode.jsx @@ -5,7 +5,7 @@ import useRequest from "@/lib/hooks/useRequest"; import { debounce } from "@mui/material/utils"; import { GET_RAHDARANS_LIST_SEARCH } from "@/core/utils/routes"; -const RahdarCode = ({ rahdarsCode, setRahdarsCode, error }) => { +const RahdarCode = ({ rahdarsCode, setRahdarsCode, error, multiple = true }) => { const [inputValue, setInputValue] = useState(""); // مدیریت مقدار تایپ‌شده const [options, setOptions] = useState([]); const [loading, setLoading] = useState(false); @@ -42,11 +42,11 @@ const RahdarCode = ({ rahdarsCode, setRahdarsCode, error }) => { return ( { - setRahdarsCode(newValue || []); // به‌روزرسانی موارد انتخاب‌شده + setRahdarsCode(multiple ? newValue || [] : newValue || null); // مدیریت حالت چندگانه و تک‌گانه }} inputValue={inputValue} // مقدار تایپ‌شده onInputChange={(event, newInputValue) => { @@ -86,5 +86,4 @@ const RahdarCode = ({ rahdarsCode, setRahdarsCode, error }) => { /> ); }; - export default RahdarCode; diff --git a/src/core/components/ShowPlak.jsx b/src/core/components/ShowPlak.jsx new file mode 100644 index 0000000..04548f1 --- /dev/null +++ b/src/core/components/ShowPlak.jsx @@ -0,0 +1,62 @@ +import { Stack } from "@mui/material"; + +const ShowPlak = ({ plak_number }) => { + const processPlak = (plak_number) => { + const parts = plak_number.match(/^([\u0600-\u06FF]+)(\d+)-(\d+)([^\d]*)(\d+)$/); + if (!parts) return {}; + + return { + region: parts[1], // "ايران" + mainNumber: parts[2], // "13" + serial: parts[3], // "189" + letter: parts[4], // "الف" + number: parts[5], // "15" + }; + }; + const plakParts = processPlak(plak_number); + + return ( + + + {plakParts.region} {plakParts.mainNumber} + + + + {plakParts.serial} + + + {plakParts.letter} + + + {plakParts.number} + + + + ); +}; +export default ShowPlak; diff --git a/src/core/utils/pageMenu.js b/src/core/utils/pageMenu.js index 798d28b..f77574f 100644 --- a/src/core/utils/pageMenu.js +++ b/src/core/utils/pageMenu.js @@ -124,13 +124,6 @@ export const pageMenu = [ hasSubitems: true, badges: ["road_items.operation_cnt"], Subitems: [ - { - id: "roadItemManagmentOparationCreate", - label: "ثبت فعالیت", - type: "page", - route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_items/operator/create", - permissions: ["create-road-item"], - }, { id: "roadItemManagmentOparationCartable", label: "کارتابل", @@ -186,7 +179,7 @@ export const pageMenu = [ id: "roadPatrolManagmentSupervisorCartable", label: "کارتابل", type: "page", - route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_patrols/supervisor/cartable", + route: "/dashboard/road-patrols/supervisor", permissions: [ "show-road-patrol-supervise-cartable", "show-road-patrol-supervise-cartable-province", @@ -206,14 +199,14 @@ export const pageMenu = [ id: "roadPatrolManagmentOparationCreate", label: "ثبت اقدام", type: "page", - route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_patrols/operator/create", + route: "/dashboard/road-patrols/operator", permissions: ["add-road-patrol"], }, { id: "roadPatrolManagmentOparationCartable", label: "کارتابل", type: "page", - route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_patrols/operator/cartable", + route: "/dashboard/road-patrols/operator", permissions: ["add-road-patrol"], }, ], diff --git a/src/core/utils/routes.js b/src/core/utils/routes.js index 9548f91..db6c244 100644 --- a/src/core/utils/routes.js +++ b/src/core/utils/routes.js @@ -29,9 +29,9 @@ export const ADD_AZMAYESH_TYPE = api + "/api/v3/azmayesh_types/store"; export const UPDATE_AZMAYESH_TYPE = api + "/api/v3/azmayesh_types/update"; //road patrol -export const GET_ROAD_PATROL_OPERATOR_LIST = "/v3/api/fake-road-patrol/operator"; +export const GET_ROAD_PATROL_OPERATOR_LIST = api + "/api/v3/road_patrols/operator_index"; export const EXPORT_ROAD_PATROL_OPERATOR_LIST = "https://rms.rmto.ir/v2/road_patrols/operator/cartable/report"; -export const GET_ROAD_PATROL_SUPERVISOR_LIST = "/v3/api/fake-road-patrol/supervisor"; +export const GET_ROAD_PATROL_SUPERVISOR_LIST = api + "/api/v3/road_patrols/supervisor_index"; export const EXPORT_ROAD_PATROL_SUPERVISOR_LIST = "https://rms.rmto.ir/v2/road_patrols/supervisor/cartable/report"; // road items @@ -41,6 +41,7 @@ export const GET_ROAD_ITEMS_OPERATOR_LIST = api + "/api/v3/road_items/operator_i export const EXPORT_ROAD_ITEMS_OPERATOR_LIST = api + "/api/v3/road_items/operator_report"; export const GET_ROAD_ITEMS_ITEM = "https://rms.witel.ir/v2/items"; export const GET_ROAD_ITEMS_SUB_ITEM = "https://rms.witel.ir/v2/sub_items"; +export const GET_EDARAT_LISTS = "https://rms.witel.ir/public/contents/edarate_shahri_by_province"; export const CREATE_ROAD_ITEMS = api + "/api/v3/road_items/store"; export const UPDATE_ROAD_ITEMS = api + "/api/v3/road_items/update"; export const VERIFY_BY_SUPERVISOR = api + "/api/v3/road_items/verify_by_supervisor"; diff --git a/src/lib/contexts/DataTable.js b/src/lib/contexts/DataTable.js index ec22020..f283da7 100644 --- a/src/lib/contexts/DataTable.js +++ b/src/lib/contexts/DataTable.js @@ -18,14 +18,23 @@ const DataTableProvider = ({ children, user_id, page_name, table_name, columns, const [initHide, setInitHide] = useState({}); const [hideData, setHideData] = useState({}); const [isDirty, setIsDirty] = useState(false); + const [isAnyDirty, setIsAnyDirty] = useState(false); useEffect(() => { + let hasAnyConflict = false; const hasConflict = JSON.stringify(hideData) !== JSON.stringify(initHide) || JSON.stringify(sortData) !== JSON.stringify(initSort) || JSON.stringify(filterData) !== JSON.stringify(initFilter); + const CheckFilterValues = Object.values(filterData).every((innerObject) => innerObject.value === ""); + const CheckHideValues = Object.values(hideData).every((value) => value === true); + + hasAnyConflict = + !CheckHideValues || JSON.stringify(sortData) !== JSON.stringify(initialSort) || !CheckFilterValues; + setIsDirty(hasConflict); + setIsAnyDirty(hasAnyConflict); }, [hideData, sortData, filterData, initHide, initSort, initFilter]); useEffect(() => { @@ -136,7 +145,7 @@ const DataTableProvider = ({ children, user_id, page_name, table_name, columns, return ( {children} diff --git a/src/lib/hooks/useDataTable.js b/src/lib/hooks/useDataTable.js index 9026caa..d1254cb 100644 --- a/src/lib/hooks/useDataTable.js +++ b/src/lib/hooks/useDataTable.js @@ -2,9 +2,9 @@ import { useContext } from "react"; import { DataTableContext } from "@/lib/contexts/DataTable"; const useTableSetting = () => { - const { filterData, setFilterData, sortData, setSortData, hideData, setHideData, isDirty } = + const { filterData, setFilterData, sortData, setSortData, hideData, setHideData, isDirty, isAnyDirty } = useContext(DataTableContext); - return { filterData, setFilterData, sortData, setSortData, hideData, setHideData, isDirty }; + return { filterData, setFilterData, sortData, setSortData, hideData, setHideData, isDirty, isAnyDirty }; }; export default useTableSetting; diff --git a/src/lib/hooks/useEdaratLists.js b/src/lib/hooks/useEdaratLists.js new file mode 100644 index 0000000..ad0bc53 --- /dev/null +++ b/src/lib/hooks/useEdaratLists.js @@ -0,0 +1,62 @@ +import { useEffect, useReducer } from "react"; +import { GET_EDARAT_LISTS } from "@/core/utils/routes"; +import useRequest from "@/lib/hooks/useRequest"; + +const ACTIONS = { + LOADING: "loading", + SUCCESS: "success", + ERROR: "error", + RESET: "reset", +}; + +const initialState = { + data: [], + loading: true, + error: null, +}; + +function reducer(state, action) { + switch (action.type) { + case ACTIONS.LOADING: + return { ...state, loading: true, error: null }; + case ACTIONS.SUCCESS: + return { ...state, loading: false, data: action.payload }; + case ACTIONS.ERROR: + return { ...state, loading: false, error: action.payload }; + case ACTIONS.RESET: + return { ...initialState, loading: false }; + default: + return state; + } +} + +const useEdaratLists = (id) => { + const requestServer = useRequest({ notificationShow: false }); + const [state, dispatch] = useReducer(reducer, initialState); + useEffect(() => { + if (!id) { + dispatch({ type: ACTIONS.RESET }); + return; + } + + const fetchEdaratLists = async () => { + dispatch({ type: ACTIONS.LOADING }); + try { + const response = await requestServer(`${GET_EDARAT_LISTS}/${id}`); + dispatch({ type: ACTIONS.SUCCESS, payload: response.data.data }); + } catch (error) { + dispatch({ type: ACTIONS.ERROR, payload: error }); + } + }; + + fetchEdaratLists(); + }, [id]); + + return { + edaratList: state.data, + loadingEdaratList: state.loading, + errorEdaratList: state.error, + }; +}; + +export default useEdaratLists; diff --git a/src/lib/hooks/useRequest.js b/src/lib/hooks/useRequest.js index ef17e84..f160f53 100644 --- a/src/lib/hooks/useRequest.js +++ b/src/lib/hooks/useRequest.js @@ -10,7 +10,7 @@ const defaultOptions = { }, notificationShow: true, notificationSuccess: false, - notificationFailed: true + notificationFailed: true, }; const useRequest = (initOptions) => { diff --git a/src/lib/hooks/useRoadItemGetISubtems.js b/src/lib/hooks/useRoadItemGetISubtems.js index f315fd3..b0e3264 100644 --- a/src/lib/hooks/useRoadItemGetISubtems.js +++ b/src/lib/hooks/useRoadItemGetISubtems.js @@ -1,29 +1,62 @@ -import { useEffect, useState } from "react"; +import { useEffect, useReducer } from "react"; import { GET_ROAD_ITEMS_SUB_ITEM } from "@/core/utils/routes"; import useRequest from "@/lib/hooks/useRequest"; -const useRoadItemGetItems = (id) => { - const requestServer = useRequest(); - const [subItemsList, setSubItemsList] = useState([]); - const [loadingSubItemsList, setLoadingSubItemsList] = useState(true); - const [errorSubItemsList, setErrorSubItemsList] = useState(null); +const ACTIONS = { + LOADING: "loading", + SUCCESS: "success", + ERROR: "error", + RESET: "reset", +}; +const initialState = { + data: [], + loading: true, + error: null, +}; + +function reducer(state, action) { + switch (action.type) { + case ACTIONS.LOADING: + return { ...state, loading: true, error: null }; + case ACTIONS.SUCCESS: + return { ...state, loading: false, data: action.payload }; + case ACTIONS.ERROR: + return { ...state, loading: false, error: action.payload }; + case ACTIONS.RESET: + return { ...initialState, loading: false }; + default: + return state; + } +} + +const useRoadItemGetItems = (id) => { + const requestServer = useRequest({ notificationShow: false }); + const [state, dispatch] = useReducer(reducer, initialState); useEffect(() => { + if (!id) { + dispatch({ type: ACTIONS.RESET }); + return; + } + const fetchSubItems = async () => { + dispatch({ type: ACTIONS.LOADING }); try { const response = await requestServer(`${GET_ROAD_ITEMS_SUB_ITEM}/${id}`); - setSubItemsList(response.data.data); - setLoadingSubItemsList(false); - } catch (e) { - setErrorSubItemsList(e); - setLoadingSubItemsList(false); + dispatch({ type: ACTIONS.SUCCESS, payload: response.data.data }); + } catch (error) { + dispatch({ type: ACTIONS.ERROR, payload: error }); } }; fetchSubItems(); - }, []); + }, [id]); - return { subItemsList, loadingSubItemsList, errorSubItemsList }; + return { + subItemsList: state.data, + loadingSubItemsList: state.loading, + errorSubItemsList: state.error, + }; }; export default useRoadItemGetItems; diff --git a/src/lib/hooks/useRoadItemGetItems.js b/src/lib/hooks/useRoadItemGetItems.js index 523f7c9..1528735 100644 --- a/src/lib/hooks/useRoadItemGetItems.js +++ b/src/lib/hooks/useRoadItemGetItems.js @@ -14,6 +14,7 @@ const useRoadItemGetItems = () => { const response = await requestServer(`${GET_ROAD_ITEMS_ITEM}`); setItemsList(response.data.data); setLoadingItemsList(false); + setErrorItemsList(false); } catch (e) { setErrorItemsList(e); setLoadingItemsList(false);