From 58cd380c649f05224aa6dfe5440fbbb8e4430ef9 Mon Sep 17 00:00:00 2001 From: Amirhossein Mahmoodi Date: Sun, 5 Jan 2025 14:22:50 +0330 Subject: [PATCH 1/6] better performance --- src/core/components/ActivityCodeLog.jsx | 34 +++++++++++++++---------- src/core/middlewares/withPermission.js | 12 +++++++-- src/lib/hooks/usePermissions.js | 2 +- src/lib/hooks/useSidebarBadge.js | 2 +- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/core/components/ActivityCodeLog.jsx b/src/core/components/ActivityCodeLog.jsx index ef53b42..cf284e6 100644 --- a/src/core/components/ActivityCodeLog.jsx +++ b/src/core/components/ActivityCodeLog.jsx @@ -1,30 +1,36 @@ "use client"; + +import { useEffect, useState, memo } from "react"; import useRequest from "@/lib/hooks/useRequest"; -import { useEffect } from "react"; import { ACTIVITY_LOG } from "@/core/utils/routes"; -const ActivityCodeLog = ({ activity_code }) => { +const ActivityCodeLog = memo(({ activity_code }) => { const requestServer = useRequest({ notificationShow: false }); + const [hasLogged, setHasLogged] = useState(false); useEffect(() => { - if (!activity_code) return; + if (!activity_code || hasLogged) return; - const fetchSubItems = async () => { + const controller = new AbortController(); + + const fetchActivityLog = async () => { try { await requestServer(ACTIVITY_LOG, "post", { - data: { - activityCode: activity_code, - }, + data: { activityCode: activity_code }, + signal: controller.signal, }); - } catch (error) { - console.error(error); // Always helpful to log the error for debugging. - } + setHasLogged(true); + } catch (error) {} }; - fetchSubItems(); - }, [activity_code, requestServer]); + fetchActivityLog(); - return null; // Ensure the component still renders something. -}; + return () => { + controller.abort(); + }; + }, [activity_code, hasLogged, requestServer]); + + return null; +}); export default ActivityCodeLog; diff --git a/src/core/middlewares/withPermission.js b/src/core/middlewares/withPermission.js index c6e3661..0da81c9 100644 --- a/src/core/middlewares/withPermission.js +++ b/src/core/middlewares/withPermission.js @@ -2,16 +2,24 @@ import { Box, Typography } from "@mui/material"; import { usePermissions } from "@/lib/hooks/usePermissions"; +import { useEffect, useState } from "react"; function WithPermission({ children, permission_name }) { const { data, error, isLoading } = usePermissions(); + const [cachedData, setCachedData] = useState(null); - if (error || isLoading || !data || !permission_name) { + useEffect(() => { + if (data) { + setCachedData(data); + } + }, [data]); + + if (error || isLoading || !cachedData || !permission_name) { return null; } const hasPermission = - permission_name.includes("all") || permission_name.some((permission) => data.includes(permission)); + permission_name.includes("all") || permission_name.some((permission) => cachedData.includes(permission)); if (!hasPermission) { return ( diff --git a/src/lib/hooks/usePermissions.js b/src/lib/hooks/usePermissions.js index 004ff6d..3fb4921 100644 --- a/src/lib/hooks/usePermissions.js +++ b/src/lib/hooks/usePermissions.js @@ -14,5 +14,5 @@ export const usePermissions = () => { } }; - return useSWR(GET_PERMISSIONS_ROUTE, fetcher, { keepPreviousData: true }); + return useSWR(GET_PERMISSIONS_ROUTE, fetcher, { keepPreviousData: true, dedupingInterval: 30000 }); }; diff --git a/src/lib/hooks/useSidebarBadge.js b/src/lib/hooks/useSidebarBadge.js index 621ce55..2befed2 100644 --- a/src/lib/hooks/useSidebarBadge.js +++ b/src/lib/hooks/useSidebarBadge.js @@ -14,5 +14,5 @@ export const useSidebarBadge = () => { } }; - return useSWR(GET_SIDEBAR_BADGE_ROUTE, fetcher, { keepPreviousData: true }); + return useSWR(GET_SIDEBAR_BADGE_ROUTE, fetcher, { keepPreviousData: true, dedupingInterval: 30000 }); }; From fa79ee736fb1e5d7d6fda9c77016cf92c2c6a71c Mon Sep 17 00:00:00 2001 From: Amirhossein Mahmoodi Date: Mon, 6 Jan 2025 10:51:57 +0330 Subject: [PATCH 2/6] change icon size --- src/core/components/MapInfoTwoMarker.jsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/core/components/MapInfoTwoMarker.jsx b/src/core/components/MapInfoTwoMarker.jsx index daac893..5034cb7 100644 --- a/src/core/components/MapInfoTwoMarker.jsx +++ b/src/core/components/MapInfoTwoMarker.jsx @@ -23,8 +23,8 @@ const createCustomIcon = (size, iconUrl, labelText, color) => {
`, - iconSize: [100, 50], // Adjust icon size to fit your content - iconAnchor: [50, 25], // Adjust to position the marker correctly + iconSize: [50, 50], + iconAnchor: [25, 50], }); } return L.icon({ @@ -111,6 +111,7 @@ const MapInteraction = ({ setValue, startLat, startLng, endLat, endLng }) => { setStartPosition({ lat: center.lat, lng: center.lng }); setIsStartLocked(true); setStartIconColor("#1CAC66"); + map.panBy([25, 25]) } }, }} @@ -182,6 +183,13 @@ const MapInteraction = ({ setValue, startLat, startLng, endLat, endLng }) => { setEndPosition({ lat: center.lat, lng: center.lng }); setIsEndLocked(true); setEndIconColor("#D13131"); + map.fitBounds( + [ + startPosition, + map.getCenter(), + ], + { paddingTopLeft: [16, 16], paddingBottomRight: [16, 16] } + ); } }, }} From 3f32a65cdbdad36be36339efbdd472eee078fad6 Mon Sep 17 00:00:00 2001 From: Amirhossein Mahmoodi Date: Mon, 6 Jan 2025 10:52:39 +0330 Subject: [PATCH 3/6] change icon size --- src/core/components/MapInfoOneMarker.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/components/MapInfoOneMarker.jsx b/src/core/components/MapInfoOneMarker.jsx index e456244..a0817bf 100644 --- a/src/core/components/MapInfoOneMarker.jsx +++ b/src/core/components/MapInfoOneMarker.jsx @@ -23,8 +23,8 @@ const createCustomIcon = (size, iconUrl, labelText, color) => {
`, - iconSize: [100, 50], // Adjust icon size to fit your content - iconAnchor: [50, 25], // Adjust to position the marker correctly + iconSize: [50, 50], + iconAnchor: [25, 50], }); } From 4747802e8aad987c8d7fb17f5ce3098ede65686a Mon Sep 17 00:00:00 2001 From: Amirhossein Mahmoodi Date: Mon, 6 Jan 2025 10:55:51 +0330 Subject: [PATCH 4/6] change dedupingInterval to 10s --- src/lib/hooks/useSidebarBadge.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/hooks/useSidebarBadge.js b/src/lib/hooks/useSidebarBadge.js index 2befed2..29e5fed 100644 --- a/src/lib/hooks/useSidebarBadge.js +++ b/src/lib/hooks/useSidebarBadge.js @@ -14,5 +14,5 @@ export const useSidebarBadge = () => { } }; - return useSWR(GET_SIDEBAR_BADGE_ROUTE, fetcher, { keepPreviousData: true, dedupingInterval: 30000 }); + return useSWR(GET_SIDEBAR_BADGE_ROUTE, fetcher, { keepPreviousData: true, dedupingInterval: 10000 }); }; From ae9b4787c58d218bfddae96430e862abf85c5828 Mon Sep 17 00:00:00 2001 From: Amin Ghasempoor Date: Mon, 6 Jan 2025 08:53:41 +0000 Subject: [PATCH 5/6] Feature/observed gasht create --- .../Create/Forms/CreateFormContent.jsx | 9 +- .../Actions/Create/Forms/GetItemInfo.jsx | 1 - .../ObservedGashtCreate/GashtCreate.jsx | 6 - .../GashtCreateContent.jsx | 123 +++++++--- .../LocationForm/LocationFormContent.jsx | 31 +++ .../LocationForm/index.jsx | 36 +++ .../RowActions/CompleteItem.jsx | 231 ++++++++++++++++++ .../RowActions/GetItemInfo.jsx | 28 +++ .../RowActions/ImageUpload.jsx | 131 ++++++++++ .../RowActions/PreviousStatesInfo.jsx | 43 ++++ .../RowActions/SubItemForm/index.jsx | 21 ++ .../ObservedGashtCreate/RowActions/index.jsx | 11 + .../ObservedGashtCreate/SearchItemInfo.jsx | 42 ++++ .../ObservedGashtCreate/SearchItems.jsx | 96 ++++++++ .../Actions/ObservedGashtCreate/TableInfo.jsx | 115 +++++++++ .../Actions/ObservedGashtCreate/index.jsx | 6 +- .../roadItems/operator/OperatorList.jsx | 41 ++-- .../RowActions/DescriptionForm/index.jsx | 2 +- .../RowActions/EditForm/EditFormContent.jsx | 4 +- .../RowActions/EditForm/EditFormCreate.jsx | 2 +- .../LocationForm/LocationFormContent.jsx | 2 +- .../dashboard/roadItems/operator/Toolbar.jsx | 2 +- .../RowActions/DeleteForm/DeleteContent.jsx | 4 +- .../LocationForm/LocationFormContent.jsx | 2 +- .../roadItems/supervisor/SupervisorList.jsx | 14 +- .../roadPatrols/operator/OperatorList.jsx | 75 ++++-- .../MachinesCodeForm/MachinesCodeContent.jsx | 55 +++++ .../RowActions/MachinesCodeForm/index.jsx | 43 ++++ .../RahdaranForm/RahdaranContent.jsx | 48 ++++ .../RowActions/RahdaranForm/index.jsx | 38 +++ .../MachinesCodeForm/MachinesCodeContent.jsx | 55 +++++ .../RowActions/MachinesCodeForm/index.jsx | 43 ++++ .../RahdaranForm/RahdaranContent.jsx | 48 ++++ .../RowActions/RahdaranForm/index.jsx | 38 +++ .../roadPatrols/supervisor/SupervisorList.jsx | 77 ++++-- src/core/components/DataTable/Main.js | 35 +-- src/core/components/MuiDatePicker.jsx | 8 +- src/core/components/MuiTimePicker.jsx | 8 +- src/core/utils/routes.js | 1 + 39 files changed, 1427 insertions(+), 148 deletions(-) create mode 100644 src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/LocationForm/LocationFormContent.jsx create mode 100644 src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/LocationForm/index.jsx create mode 100644 src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/CompleteItem.jsx create mode 100644 src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/GetItemInfo.jsx create mode 100644 src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/ImageUpload.jsx create mode 100644 src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/PreviousStatesInfo.jsx create mode 100644 src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/SubItemForm/index.jsx create mode 100644 src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/index.jsx create mode 100644 src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/SearchItemInfo.jsx create mode 100644 src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/SearchItems.jsx create mode 100644 src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/TableInfo.jsx create mode 100644 src/components/dashboard/roadPatrols/operator/RowActions/MachinesCodeForm/MachinesCodeContent.jsx create mode 100644 src/components/dashboard/roadPatrols/operator/RowActions/MachinesCodeForm/index.jsx create mode 100644 src/components/dashboard/roadPatrols/operator/RowActions/RahdaranForm/RahdaranContent.jsx create mode 100644 src/components/dashboard/roadPatrols/operator/RowActions/RahdaranForm/index.jsx create mode 100644 src/components/dashboard/roadPatrols/supervisor/RowActions/MachinesCodeForm/MachinesCodeContent.jsx create mode 100644 src/components/dashboard/roadPatrols/supervisor/RowActions/MachinesCodeForm/index.jsx create mode 100644 src/components/dashboard/roadPatrols/supervisor/RowActions/RahdaranForm/RahdaranContent.jsx create mode 100644 src/components/dashboard/roadPatrols/supervisor/RowActions/RahdaranForm/index.jsx 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 7f47a7d..db106e3 100644 --- a/src/components/dashboard/roadItems/operator/Actions/Create/Forms/CreateFormContent.jsx +++ b/src/components/dashboard/roadItems/operator/Actions/Create/Forms/CreateFormContent.jsx @@ -133,7 +133,7 @@ const CreateFormContent = ({ setOpen, onSubmit }) => { mode: "onBlur", context: { subItemsList }, }); - const onSubmitBase = (data) => { + const onSubmitBase = async (data) => { let result = { ...data }; if (result.before_image === null) { @@ -170,7 +170,7 @@ const CreateFormContent = ({ setOpen, onSubmit }) => { }); delete result.cmms_machines; - onSubmit({ + await onSubmit({ result, data: { ...data, @@ -190,7 +190,8 @@ const CreateFormContent = ({ setOpen, onSubmit }) => { variant={`${isMobile ? "scrollable" : "fullWidth"}`} sx={{ display: "flex", - justifyContent: "space-around", + justifyContent: "center", + alignItems: "center", width: "100%", backgroundColor: "#efefef", }} @@ -237,7 +238,7 @@ const CreateFormContent = ({ setOpen, onSubmit }) => { - ); }; diff --git a/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/GashtCreateContent.jsx b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/GashtCreateContent.jsx index d2ff576..a37e36f 100644 --- a/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/GashtCreateContent.jsx +++ b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/GashtCreateContent.jsx @@ -1,28 +1,46 @@ -import { Box, Button, DialogActions, DialogContent, Grid, Stack, Tab, Tabs } from "@mui/material"; +import { Box, Button, DialogActions, DialogContent, Tab, Tabs } from "@mui/material"; import { useForm } from "react-hook-form"; import { yupResolver } from "@hookform/resolvers/yup"; import * as yup from "yup"; -import MuiDatePicker from "@/core/components/MuiDatePicker"; import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile"; import FileCopyIcon from "@mui/icons-material/FileCopy"; -import InfoIcon from "@mui/icons-material/Info"; -import GetItemsForm from "@/components/dashboard/roadItems/operator/Actions/Create/Forms/GetItemsForm"; -import GetSubItemsForm from "@/components/dashboard/roadItems/operator/Actions/Create/Forms/GetSubItemsForm"; -import GetItemInfo from "@/components/dashboard/roadItems/operator/Actions/Create/Forms/GetItemInfo"; import ExitToAppIcon from "@mui/icons-material/ExitToApp"; import KeyboardDoubleArrowRightIcon from "@mui/icons-material/KeyboardDoubleArrowRight"; import BeenhereIcon from "@mui/icons-material/Beenhere"; import StyledForm from "@/core/components/StyledForm"; -import React from "react"; -import { TabPanel } from "@mui/lab"; +import React, { useState } from "react"; +import SearchItemInfo from "./SearchItemInfo"; +import moment from "jalali-moment"; +import GetItemInfo from "./RowActions/GetItemInfo"; + +function TabPanel(props) { + const { children, value, index } = props; + return ( + + ); +} + +const defaultValues = { + start_date: moment(new Date()).format("YYYY-MM-DD"), + end_date: moment(new Date()).format("YYYY-MM-DD"), + item_id: "", + road_patrol_id: "", +}; + +const defaultFilter = [ + { value: `${defaultValues.item_id}`, datatype: "text", id: "item_id", fn: "equals" }, + { value: `${defaultValues.road_patrol_id}`, datatype: "text", id: "road_patrol_id", fn: "equals" }, + { value: `${defaultValues.start_date}`, datatype: "date", id: "roadPatrol.start_time", fn: "equals" }, + { value: `${defaultValues.end_date}`, datatype: "date", id: "roadPatrol.end_time", fn: "equals" }, +]; const GashtCreateContent = ({ mutate, setOpen }) => { - const defaultValues = { - start_date: null, - end_date: null, - item_id: null, - road_patrol_id: null, - }; + const [tabState, setTabState] = useState(0); + const [itemInfo, setItemInfo] = useState(null); + const [submitCompleteForm, setSubmitCompleteForm] = useState(false); + const [specialFilter, setSpecialFilter] = useState(defaultFilter); const validationSchema = yup .object() @@ -36,6 +54,21 @@ const GashtCreateContent = ({ mutate, setOpen }) => { return (!!values.start_date && !!values.end_date) || !!values.item_id || !!values.road_patrol_id; }); + const handleChangeTab = (event, newValue) => { + setTabState(newValue); + }; + const handleClose = () => { + setOpen(false); + }; + + const handlePrev = () => { + if (tabState === 0) { + handleClose(); + } else { + setTabState(tabState - 1); + } + }; + const { control, getValues, @@ -49,41 +82,53 @@ const GashtCreateContent = ({ mutate, setOpen }) => { resolver: yupResolver(validationSchema), mode: "onBlur", }); + const onSearchSubmit = async (data) => { + setSpecialFilter([ + { value: `${data.item_id}`, datatype: "text", id: "item_id", fn: "equals" }, + { value: `${data.road_patrol_id}`, datatype: "text", id: "road_patrol_id", fn: "equals" }, + { value: `${data.start_date}`, datatype: "date", id: "roadPatrol.start_time", fn: "equals" }, + { value: `${data.end_date}`, datatype: "date", id: "roadPatrol.end_time", fn: "equals" }, + ]); + }; return ( - + <> - } label="انتخاب آیتم" /> - } label="انتخاب موضوع مشاهده شده" /> + } label="انتخاب مورد مشاهده شده" /> + } label="اطلاعات مورد مشاهده شده" /> - + + + - @@ -98,19 +143,21 @@ const GashtCreateContent = ({ mutate, setOpen }) => { > {tabState === 0 ? "بستن" : "مرحله قبل"} - {tabState === 2 && ( + {tabState === 1 && ( )} - + ); }; export default GashtCreateContent; diff --git a/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/LocationForm/LocationFormContent.jsx b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/LocationForm/LocationFormContent.jsx new file mode 100644 index 0000000..f012434 --- /dev/null +++ b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/LocationForm/LocationFormContent.jsx @@ -0,0 +1,31 @@ +"use client"; +import { Box, Button, DialogActions, DialogContent, Stack } from "@mui/material"; +import React from "react"; +import dynamic from "next/dynamic"; +import MapLoading from "@/core/components/MapLayer/Loading"; +import ShowLocationMarker from "@/core/components/ShowLocationMarker"; +const MapLayer = dynamic(() => import("@/core/components/MapLayer"), { + loading: () => , + ssr: false, +}); + +const LocationFormContent = ({ setOpenLocationDialog, start_lat, start_lng }) => { + return ( + <> + + + + + + + + + + + + ); +}; + +export default LocationFormContent; diff --git a/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/LocationForm/index.jsx b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/LocationForm/index.jsx new file mode 100644 index 0000000..09df6ad --- /dev/null +++ b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/LocationForm/index.jsx @@ -0,0 +1,36 @@ +import React, { useState } from "react"; +import { Tooltip, IconButton, Dialog, DialogTitle } from "@mui/material"; +import ExploreIcon from "@mui/icons-material/Explore"; +import LocationFormContent from "./LocationFormContent"; +const LocationForm = ({ start_lat, start_lng }) => { + const [openLocationDialog, setOpenLocationDialog] = useState(false); + + return ( + <> + + setOpenLocationDialog(true)}> + + + + setOpenLocationDialog(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 LocationForm; diff --git a/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/CompleteItem.jsx b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/CompleteItem.jsx new file mode 100644 index 0000000..059aac9 --- /dev/null +++ b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/CompleteItem.jsx @@ -0,0 +1,231 @@ +import { Button, DialogActions, Grid, Stack } from "@mui/material"; +import PreviousStatesInfo from "./PreviousStatesInfo"; +import NumberField from "@/core/components/NumberField"; +import { Controller, useForm } from "react-hook-form"; +import CarCode from "@/core/components/CarCode"; +import RahdarCode from "@/core/components/RahdarCode"; +import ImageUpload from "@/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/ImageUpload"; +import MuiDatePicker from "@/core/components/MuiDatePicker"; +import MuiTimePicker from "@/core/components/MuiTimePicker"; +import MapInfoTwoMarker from "@/core/components/MapInfoTwoMarker"; +import MapInfoOneMarker from "@/core/components/MapInfoOneMarker"; +import { yupResolver } from "@hookform/resolvers/yup"; +import StyledForm from "@/core/components/StyledForm"; +import { array, mixed, number, object, string } from "yup"; +import useRequest from "@/lib/hooks/useRequest"; +import BeenhereIcon from "@mui/icons-material/Beenhere"; +import React, { useEffect } from "react"; +import { CREATE_ROAD_ITEMS } from "@/core/utils/routes"; + +const CompleteItem = ({ subItem, itemInfo, setSubmitCompleteForm, mutate, setOpen }) => { + const requestServer = useRequest({ notificationSuccess: true }); + + const defaultValues = { + item_id: itemInfo?.item_id || null, + sub_item_id: itemInfo?.sub_item_id || null, + amount: "", + activity_time: "", + activity_date: "", + before_image: null, + after_image: null, + cmms_machines: null, + rahdaran_id: null, + start_point: { lat: itemInfo?.start_lat || "", lng: itemInfo?.start_lon || "" }, + end_point: { lat: itemInfo?.end_lat || "", lng: itemInfo?.end_lon || "" }, + }; + + const validationSchema = object({ + item_id: number().required("نوع آیتم را مشخص کنید!"), + sub_item_id: number().required("موضوع مشاهده شده را مشخص کنید!"), + amount: string().required("وارد کردن مقدار الزامیست!"), + cmms_machines: array().required("وارد کردن کد خودرو الزامیست!"), + rahdaran_id: array().required("وارد کردن کد راهداران الزامیست!").min(1, "حداقل یک کد راهدار باید وارد شود!"), // بررسی حداقل یک آیتم, + activity_time: string().required("لطفا زمان فعالیت را انتخاب کنید!"), + activity_date: string().required("لطفاً تاریخ شروع فعالیت را انتخاب کنید!"), + before_image: mixed() + .nullable() + .test("before-image-required", "لطفا عکس قبل از اقدام را بارگذاری کنید!", function (value) { + const { subItem } = this.options.context; + const needsImage = subItem?.needs_image === 1; + if (needsImage) { + return !!value; + } + return true; + }), + after_image: mixed() + .nullable() + .test("after-image-required", "لطفا عکس بعد از اقدام را بارگذاری کنید!", function (value) { + const { subItem } = this.options.context; + const needsImage = subItem?.needs_image === 1; + if (needsImage) { + return !!value; + } + return true; + }), + start_point: mixed() + .test("start-point-required", "لطفاً نقطه شروع را مشخص کنید!", function (value) { + return !!value; // چک می‌کند که مقدار موجود است + }) + .required("لطفاً نقطه شروع را مشخص کنید!"), + end_point: mixed().test("end-point-required", "لطفاً نقطه پایان را مشخص کنید!", function (value) { + const { subItem } = this.options.context; + const needsEndPoint = subItem?.needs_end_point === 1; + if (needsEndPoint) { + return !!value; // چک می‌کند که مقدار موجود است + } + return true; + }), + }); + + const { + control, + watch, + getValues, + register, + handleSubmit, + setValue, + resetField, + formState: { errors, isSubmitting }, + } = useForm({ + defaultValues, + resolver: yupResolver(validationSchema), + mode: "onBlur", + context: { subItem }, + }); + + useEffect(() => { + setSubmitCompleteForm(isSubmitting); + }, [isSubmitting]); + const onSubmit = async (data) => { + let endPoint; + let startPoint = `${data.start_point.lat},${data.start_point.lng}`; + if (subItem.needs_end_point === 1) { + endPoint = `${data.end_point.lat},${data.end_point.lng}`; + } + const formData = new FormData(); + data.after_image !== null && formData.append("after_image", data.after_image); + data.before_image !== null && formData.append("before_image", data.before_image); + subItem.needs_end_point === 1 && formData.append("end_point", endPoint); + formData.append("start_point", startPoint); + formData.append("activity_time", data.activity_time); + formData.append("activity_date", data.activity_date); + formData.append("amount", data.amount); + formData.append("item_id", data.item_id); + formData.append("sub_item_id", data.sub_item_id); + data.cmms_machines.forEach((machine, index) => formData.append(`machines_id[${index}]`, machine.id)); + data.rahdaran_id.forEach((rahdar, index) => formData.append(`rahdaran_id[${index}]`, rahdar.id)); + + await requestServer(CREATE_ROAD_ITEMS, "post", { + data: formData, + }) + .then((response) => { + mutate(); + setOpen(false); + }) + .catch((error) => {}); + }; + + return ( + + + + + + + { + if (!isNaN(event.target.value)) { + setValue("amount", event.target.value); + } else { + setValue("amount", watch("amount")); + } + }} + helperText={errors.amount ? errors.amount.message : null} + variant="outlined" + fullWidth + /> + + + { + return ( + field.onChange(value || [])} + error={error} + multiple={true} + /> + ); + }} + name={"cmms_machines"} + /> + + + { + return ( + field.onChange(value || [])} + error={error} + /> + ); + }} + name={"rahdaran_id"} + /> + + + {subItem.needs_image ? ( + + ) : null} + + + + + + + + + + + + + {subItem?.needs_end_point === 1 ? ( + + ) : ( + + )} + + + + ); +}; +export default CompleteItem; diff --git a/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/GetItemInfo.jsx b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/GetItemInfo.jsx new file mode 100644 index 0000000..e11fbd3 --- /dev/null +++ b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/GetItemInfo.jsx @@ -0,0 +1,28 @@ +import { LinearProgress, Typography } from "@mui/material"; +import useRoadItemGetISubtems from "@/lib/hooks/useRoadItemGetISubtems"; +import CompleteItem from "./CompleteItem"; + +const GetItemInfo = ({ itemInfo, setSubmitCompleteForm, mutate, setOpen }) => { + const { subItemsList, loadingSubItemsList, errorSubItemsList } = useRoadItemGetISubtems(itemInfo?.item_id); + const subItem = subItemsList.find((SubItem) => SubItem.sub_item === itemInfo?.sub_item_id); + return ( + <> + {loadingSubItemsList ? ( + + ) : errorSubItemsList ? ( + + خطا در دریافت اطلاعات!!! + + ) : ( + + )} + + ); +}; +export default GetItemInfo; diff --git a/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/ImageUpload.jsx b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/ImageUpload.jsx new file mode 100644 index 0000000..3efd1d9 --- /dev/null +++ b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/ImageUpload.jsx @@ -0,0 +1,131 @@ +import { FormControl, FormHelperText, Grid } from "@mui/material"; +import UploadSystem from "@/core/components/UploadSystem"; +import { Controller } from "react-hook-form"; +import React, { useEffect, useState } from "react"; + +const ImageUpload = ({ control, setValue, errors, getValues, beforeImage = null, afterImage = null }) => { + const [beforeImg, setBeforeImg] = useState(beforeImage ? beforeImage : null); + const [beforeFileType, setBeforeFileType] = useState(beforeImage ? "image/" : null); + const [beforeFileName, setBeforeFileName] = useState(null); + const [showBeforeImage, setShowBeforeImage] = useState(!beforeImage); + + const [afterImg, setAfterImg] = useState(afterImage ? afterImage : null); + const [afterFileType, setAfterFileType] = useState(afterImage ? "image/" : null); + const [afterFileName, setAfterFileName] = useState(null); + const [showAfterImage, setShowAfterImage] = useState(!afterImage); + + useEffect(() => { + if (getValues("before_image")) { + setShowBeforeImage(false); + setBeforeImg(getValues("before_image")); + setBeforeFileType("image/"); + } + if (getValues("after_image")) { + setShowAfterImage(false); + setAfterImg(getValues("after_image")); + setAfterFileType("image/"); + } + }, [getValues]); + + const handleBeforeFileChange = (event) => { + const uploadedFile = event.target?.files?.[0]; + if (uploadedFile) { + const fileType = event.target?.files?.[0].type; + const fileName = event.target?.files?.[0].name; + setBeforeImg(URL.createObjectURL(uploadedFile)); + setBeforeFileType(fileType); + setBeforeFileName(fileName); + setValue("before_image", uploadedFile); + setShowBeforeImage(false); + } + }; + const handleAfterFileChange = (event) => { + const uploadedFile = event.target?.files?.[0]; + if (uploadedFile) { + const fileType = event.target?.files?.[0].type; + const fileName = event.target?.files?.[0].name; + setAfterImg(URL.createObjectURL(uploadedFile)); + setAfterFileType(fileType); + setAfterFileName(fileName); + setValue("after_image", uploadedFile); + setShowAfterImage(false); + } + }; + return ( + + + { + return ( + + + عکس قبل از اقدام + + + + {errors.before_image ? errors.before_image.message : null} + + + ); + }} + /> + + + { + return ( + + + عکس بعد از اقدام + + + + {errors.after_image ? errors.after_image.message : null} + + + ); + }} + /> + + + ); +}; +export default ImageUpload; diff --git a/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/PreviousStatesInfo.jsx b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/PreviousStatesInfo.jsx new file mode 100644 index 0000000..57c8839 --- /dev/null +++ b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/PreviousStatesInfo.jsx @@ -0,0 +1,43 @@ +import { Box, Chip, Divider, Grid, Typography } from "@mui/material"; +import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile"; +import FileCopyIcon from "@mui/icons-material/FileCopy"; + +const PreviousStatesInfo = ({ itemInfo }) => { + return ( + + + + } + label={ + + آیتم انتخاب ‌شده + + } + /> + + + + {itemInfo.item_name || "هیچ آیتمی انتخاب نشده است"} + + + + + } + label={ + + موضوع مشاهده‌شده + + } + /> + + + + {itemInfo?.sub_item_name || "هیچ موضوعی انتخاب نشده است"} + + + + ); +}; +export default PreviousStatesInfo; diff --git a/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/SubItemForm/index.jsx b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/SubItemForm/index.jsx new file mode 100644 index 0000000..ba8a902 --- /dev/null +++ b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/SubItemForm/index.jsx @@ -0,0 +1,21 @@ +import React from "react"; +import { Tooltip, IconButton } from "@mui/material"; +import UndoIcon from "@mui/icons-material/Undo"; +const SubItemForm = ({ row, setTabState, setItemInfo }) => { + return ( + <> + + { + setTabState(1); + setItemInfo(row.original); + }} + > + + + + + ); +}; +export default SubItemForm; diff --git a/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/index.jsx b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/index.jsx new file mode 100644 index 0000000..84e8a31 --- /dev/null +++ b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/RowActions/index.jsx @@ -0,0 +1,11 @@ +import { Box } from "@mui/material"; +import SubItemForm from "./SubItemForm"; + +const RowActions = ({ row, mutate, setTabState, setItemInfo }) => { + return ( + + + + ); +}; +export default RowActions; diff --git a/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/SearchItemInfo.jsx b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/SearchItemInfo.jsx new file mode 100644 index 0000000..611e7d8 --- /dev/null +++ b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/SearchItemInfo.jsx @@ -0,0 +1,42 @@ +import { LinearProgress, Typography } from "@mui/material"; +import useRoadItemGetItems from "@/lib/hooks/useRoadItemGetItems"; +import React from "react"; +import SearchItems from "./SearchItems"; +import TableInfo from "./TableInfo"; + +const SearchItemInfo = ({ + watch, + errors, + setValue, + register, + specialFilter, + setTabState, + setItemInfo, + isSubmitting, +}) => { + const { itemsList, loadingItemsList, errorItemsList } = useRoadItemGetItems(); + return ( + <> + {loadingItemsList ? ( + + ) : errorItemsList ? ( + + خطا در دریافت اطلاعات!!! + + ) : ( + <> + + + + )} + + ); +}; +export default SearchItemInfo; diff --git a/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/SearchItems.jsx b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/SearchItems.jsx new file mode 100644 index 0000000..775b933 --- /dev/null +++ b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/SearchItems.jsx @@ -0,0 +1,96 @@ +import { Button, FormControl, FormHelperText, InputLabel, MenuItem, Select, Stack, TextField } from "@mui/material"; +import MuiDatePicker from "@/core/components/MuiDatePicker"; +import SearchIcon from "@mui/icons-material/Search"; +import React from "react"; + +const SearchItems = ({ setValue, itemsList, watch, errors, register, isSubmitting }) => { + const disabledButton = + (!!watch("start_date") && !!watch("end_date")) || !!watch("item_id") || !!watch("road_patrol_id"); + + return ( + + + + + + + + + + آیتم فعالیت + + {/*{errors.item_id ? (*/} + {/* */} + {/* errors.item_id.message*/} + {/* */} + {/*) : null}*/} + + + + { + if (!isNaN(event.target.value)) { + setValue("road_patrol_id", event.target.value); + } else { + setValue("road_patrol_id", watch("road_patrol_id")); + } + }} + helperText={errors.road_patrol_id ? errors.road_patrol_id.message : null} + variant="outlined" + /> + + + + + + ); +}; +export default SearchItems; diff --git a/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/TableInfo.jsx b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/TableInfo.jsx new file mode 100644 index 0000000..c16dba4 --- /dev/null +++ b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/TableInfo.jsx @@ -0,0 +1,115 @@ +import { useMemo } from "react"; +import { Box, Stack } from "@mui/material"; +import DataTableWithAuth from "@/core/components/DataTableWithAuth"; +import RowActions from "./RowActions"; +import { GET_OBSERVED_GASHT_LIST } from "@/core/utils/routes"; +import LocationForm from "./LocationForm"; + +const TableInfo = ({ specialFilter, setTabState, setItemInfo }) => { + const columns = useMemo( + () => [ + { + accessorKey: "road_patrol_id", + header: "کد یکتا گشت", + id: "road_patrol_id", + enableColumnFilter: false, + datatype: "text", + filterMode: "equals", + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 50, + }, + { + accessorKey: "priority_fa", + header: "اولویت", + id: "priority_fa", + enableColumnFilter: false, + datatype: "text", + filterMode: "equals", + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 80, + }, + { + accessorKey: "local_name", + header: "نام محلی", + id: "local_name", + enableColumnFilter: false, + datatype: "text", + filterMode: "equals", + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + }, + { + accessorKey: "item_name", + header: "نام ایتم", + id: "item_name", + enableColumnFilter: false, + datatype: "text", + filterMode: "equals", + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + }, + { + accessorKey: "sub_item_name", + header: "موضوع مشاهده شده", + id: "sub_item_name", + enableColumnFilter: false, + datatype: "text", + filterMode: "equals", + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + }, + { + accessorKey: "location", + header: "موقعیت", // Location + id: "location", + enableColumnFilter: false, + enableSorting: false, + datatype: "array", + grow: false, + size: 50, + muiTableBodyCellProps: { + sx: { + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ renderedCellValue, row }) => { + return ( + + + + ); + }, + }, + ], + [] + ); + return ( + <> + + ( + + )} + /> + + + ); +}; +export default TableInfo; diff --git a/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/index.jsx b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/index.jsx index ae14476..4379040 100644 --- a/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/index.jsx +++ b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/index.jsx @@ -17,7 +17,11 @@ const ObservedGashtCreate = ({ mutate }) => { return ( <> {isMobile ? ( - + ) : ( diff --git a/src/components/dashboard/roadItems/operator/OperatorList.jsx b/src/components/dashboard/roadItems/operator/OperatorList.jsx index c5cfaba..9f818e8 100644 --- a/src/components/dashboard/roadItems/operator/OperatorList.jsx +++ b/src/components/dashboard/roadItems/operator/OperatorList.jsx @@ -193,7 +193,7 @@ const OperatorList = () => { }, { accessorKey: "cmms_machines", - header: "کد خودرو", // Car ID + header: "خودرو ها", // Car ID id: "cmmsMachines__machine_code", enableColumnFilter: true, datatype: "text", @@ -241,20 +241,17 @@ const OperatorList = () => { }, }, Cell: ({ renderedCellValue }) => { - if (renderedCellValue) { - return ( - - - - ); - } - return بدون شخص; + return ( + + + + ); }, }, { - accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"), - header: "تاریخ ثبت", // Register Date - id: "created_at", + accessorFn: (row) => moment(row.activity_date_time).locale("fa").format("HH:mm | yyyy/MM/DD"), + header: "تاریخ فعالیت", // Start Date + id: "activity_date_time", enableColumnFilter: true, datatype: "date", filterMode: "equals", @@ -263,9 +260,9 @@ const OperatorList = () => { size: 100, }, { - accessorFn: (row) => moment(row.activity_date_time).locale("fa").format("HH:mm | yyyy/MM/DD"), - header: "تاریخ فعالیت", // Start Date - id: "activity_date_time", + accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"), + header: "تاریخ ثبت", // Register Date + id: "created_at", enableColumnFilter: true, datatype: "date", filterMode: "equals", @@ -296,6 +293,7 @@ const OperatorList = () => { header: "توضیحات کارشناس", // Description id: "supervisor_description", enableColumnFilter: false, + enableSorting: false, datatype: "text", filterMode: "equals", columnFilterModeOptions: ["equals", "contains"], @@ -311,11 +309,14 @@ const OperatorList = () => { }, }, Cell: ({ renderedCellValue }) => { - return ( - - - - ); + if (renderedCellValue) { + return ( + + + + ); + } + return بدون توضیحات; }, }, ], diff --git a/src/components/dashboard/roadItems/operator/RowActions/DescriptionForm/index.jsx b/src/components/dashboard/roadItems/operator/RowActions/DescriptionForm/index.jsx index 3f748c9..481e2d6 100644 --- a/src/components/dashboard/roadItems/operator/RowActions/DescriptionForm/index.jsx +++ b/src/components/dashboard/roadItems/operator/RowActions/DescriptionForm/index.jsx @@ -37,7 +37,7 @@ const DescriptionForm = ({ description }) => { - + {description || "هیچ توضیحی موجود نیست"} diff --git a/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormContent.jsx b/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormContent.jsx index 620f052..164a07a 100644 --- a/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormContent.jsx +++ b/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormContent.jsx @@ -17,7 +17,7 @@ const EditFormContent = ({ setOpenEditDialog, onSubmit, defaultData }) => { rahdaran_id: defaultData?.rahdaran || null, }; - const onSubmitBase = (data) => { + const onSubmitBase = async (data) => { let result = { ...data }; (result.before_image === null || result.before_image === defaultValues.before_image) && delete result.before_image; @@ -40,7 +40,7 @@ const EditFormContent = ({ setOpenEditDialog, onSubmit, defaultData }) => { }); delete result.cmms_machines; - onSubmit({ + await onSubmit({ result, data: { ...data, diff --git a/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormCreate.jsx b/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormCreate.jsx index 4bd9a9c..7f2b6d8 100644 --- a/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormCreate.jsx +++ b/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormCreate.jsx @@ -158,7 +158,7 @@ const EditFormCreate = ({ defaultData, subItem, onSubmitBase, defaultValues, set - diff --git a/src/components/dashboard/roadItems/operator/Toolbar.jsx b/src/components/dashboard/roadItems/operator/Toolbar.jsx index ae6691f..d8c6fad 100644 --- a/src/components/dashboard/roadItems/operator/Toolbar.jsx +++ b/src/components/dashboard/roadItems/operator/Toolbar.jsx @@ -8,7 +8,7 @@ const Toolbar = ({ table, filterData, mutate }) => { - {/**/} + ); }; diff --git a/src/components/dashboard/roadItems/supervisor/RowActions/DeleteForm/DeleteContent.jsx b/src/components/dashboard/roadItems/supervisor/RowActions/DeleteForm/DeleteContent.jsx index 18198a8..485ac40 100644 --- a/src/components/dashboard/roadItems/supervisor/RowActions/DeleteForm/DeleteContent.jsx +++ b/src/components/dashboard/roadItems/supervisor/RowActions/DeleteForm/DeleteContent.jsx @@ -28,10 +28,10 @@ const DeleteContent = ({ rowId, mutate, setOpenDeleteDialog }) => { - - diff --git a/src/components/dashboard/roadItems/supervisor/RowActions/LocationForm/LocationFormContent.jsx b/src/components/dashboard/roadItems/supervisor/RowActions/LocationForm/LocationFormContent.jsx index 6c17f3a..1e20921 100644 --- a/src/components/dashboard/roadItems/supervisor/RowActions/LocationForm/LocationFormContent.jsx +++ b/src/components/dashboard/roadItems/supervisor/RowActions/LocationForm/LocationFormContent.jsx @@ -25,7 +25,7 @@ const LocationFormContent = ({ setOpenLocationDialog, start_lat, start_lng, end_ - diff --git a/src/components/dashboard/roadItems/supervisor/SupervisorList.jsx b/src/components/dashboard/roadItems/supervisor/SupervisorList.jsx index 4f3420b..8ef88db 100644 --- a/src/components/dashboard/roadItems/supervisor/SupervisorList.jsx +++ b/src/components/dashboard/roadItems/supervisor/SupervisorList.jsx @@ -257,7 +257,7 @@ const SupervisorList = () => { }, { accessorKey: "cmms_machines", - header: "کد خودرو", // Car ID + header: "خودرو ها", // Car ID id: "cmmsMachines__machine_code", enableColumnFilter: true, datatype: "text", @@ -316,9 +316,9 @@ const SupervisorList = () => { }, }, { - accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"), - header: "تاریخ ثبت", // Register Date - id: "created_at", + accessorFn: (row) => moment(row.activity_date_time).locale("fa").format("HH:mm | yyyy/MM/DD"), + header: "تاریخ فعالیت", // Start Date + id: "activity_date_time", enableColumnFilter: true, datatype: "date", filterMode: "equals", @@ -327,9 +327,9 @@ const SupervisorList = () => { size: 100, }, { - accessorFn: (row) => moment(row.activity_date_time).locale("fa").format("HH:mm | yyyy/MM/DD"), - header: "تاریخ فعالیت", // Start Date - id: "activity_date_time", + accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"), + header: "تاریخ ثبت", // Register Date + id: "created_at", enableColumnFilter: true, datatype: "date", filterMode: "equals", diff --git a/src/components/dashboard/roadPatrols/operator/OperatorList.jsx b/src/components/dashboard/roadPatrols/operator/OperatorList.jsx index 589ba5d..c5e8d7a 100644 --- a/src/components/dashboard/roadPatrols/operator/OperatorList.jsx +++ b/src/components/dashboard/roadPatrols/operator/OperatorList.jsx @@ -7,6 +7,8 @@ import { GET_ROAD_PATROL_OPERATOR_LIST } from "@/core/utils/routes"; import moment from "jalali-moment"; import RowActions from "./RowActions"; import ReportForm from "./RowActions/ReportForm"; +import MachinesCodeDialog from "./RowActions/MachinesCodeForm"; +import RahdaranDialog from "./RowActions/RahdaranForm"; const OperatorList = () => { const columns = useMemo( @@ -23,31 +25,64 @@ const OperatorList = () => { size: 100, }, { - accessorKey: "operator_name", - header: "نام مامور", - id: "operator_name", + accessorKey: "cmms_machines", + header: "خودرو", // Car ID + 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: "officer_phone_number", - header: "تلفن همراه", - id: "officer_phone_number", - enableColumnFilter: true, - datatype: "text", - filterMode: "equals", - columnFilterModeOptions: ["equals", "contains"], - }, - { - accessorKey: "car_id", - header: "کد خودرو", - id: "car_id", - enableColumnFilter: true, - datatype: "text", - filterMode: "equals", - columnFilterModeOptions: ["equals", "contains"], + accessorKey: "rahdaran", + header: "راهداران", + id: "rahdaran", + enableColumnFilter: false, + enableSorting: false, + datatype: "array", + grow: false, + size: 100, + muiTableBodyCellProps: { + sx: { + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ renderedCellValue }) => { + if (renderedCellValue) { + return ( + + + + ); + } + return بدون شخص; + }, }, { accessorFn: (row) => moment(row.start_date).locale("fa").format("HH:mm | yyyy/MM/DD"), diff --git a/src/components/dashboard/roadPatrols/operator/RowActions/MachinesCodeForm/MachinesCodeContent.jsx b/src/components/dashboard/roadPatrols/operator/RowActions/MachinesCodeForm/MachinesCodeContent.jsx new file mode 100644 index 0000000..1eef774 --- /dev/null +++ b/src/components/dashboard/roadPatrols/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/roadPatrols/operator/RowActions/MachinesCodeForm/index.jsx b/src/components/dashboard/roadPatrols/operator/RowActions/MachinesCodeForm/index.jsx new file mode 100644 index 0000000..d8e8754 --- /dev/null +++ b/src/components/dashboard/roadPatrols/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/roadPatrols/operator/RowActions/RahdaranForm/RahdaranContent.jsx b/src/components/dashboard/roadPatrols/operator/RowActions/RahdaranForm/RahdaranContent.jsx new file mode 100644 index 0000000..d1e9b15 --- /dev/null +++ b/src/components/dashboard/roadPatrols/operator/RowActions/RahdaranForm/RahdaranContent.jsx @@ -0,0 +1,48 @@ +import { DialogContent, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from "@mui/material"; + +const RahdaranContent = ({ rahdarLists }) => { + return ( + <> + + + + + + + کد راهدار + نام + + + + {rahdarLists.map((rahdar) => { + return ( + + {rahdar.code} + {rahdar.name} + + ); + })} + +
+
+
+
+ + ); +}; +export default RahdaranContent; diff --git a/src/components/dashboard/roadPatrols/operator/RowActions/RahdaranForm/index.jsx b/src/components/dashboard/roadPatrols/operator/RowActions/RahdaranForm/index.jsx new file mode 100644 index 0000000..2c73d80 --- /dev/null +++ b/src/components/dashboard/roadPatrols/operator/RowActions/RahdaranForm/index.jsx @@ -0,0 +1,38 @@ +import { Button, Dialog, DialogActions, DialogTitle, IconButton, Tooltip } from "@mui/material"; +import GroupsIcon from "@mui/icons-material/Groups"; +import { useState } from "react"; +import RahdaranContent from "./RahdaranContent"; + +const RahdaranDialog = ({ rahdarLists }) => { + const [openRahdaranDialog, setOpenRahdaranDialog] = useState(false); + return ( + <> + + setOpenRahdaranDialog(true)}> + + + + setOpenRahdaranDialog(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 RahdaranDialog; diff --git a/src/components/dashboard/roadPatrols/supervisor/RowActions/MachinesCodeForm/MachinesCodeContent.jsx b/src/components/dashboard/roadPatrols/supervisor/RowActions/MachinesCodeForm/MachinesCodeContent.jsx new file mode 100644 index 0000000..1eef774 --- /dev/null +++ b/src/components/dashboard/roadPatrols/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/roadPatrols/supervisor/RowActions/MachinesCodeForm/index.jsx b/src/components/dashboard/roadPatrols/supervisor/RowActions/MachinesCodeForm/index.jsx new file mode 100644 index 0000000..9696333 --- /dev/null +++ b/src/components/dashboard/roadPatrols/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; \ No newline at end of file diff --git a/src/components/dashboard/roadPatrols/supervisor/RowActions/RahdaranForm/RahdaranContent.jsx b/src/components/dashboard/roadPatrols/supervisor/RowActions/RahdaranForm/RahdaranContent.jsx new file mode 100644 index 0000000..d1e9b15 --- /dev/null +++ b/src/components/dashboard/roadPatrols/supervisor/RowActions/RahdaranForm/RahdaranContent.jsx @@ -0,0 +1,48 @@ +import { DialogContent, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from "@mui/material"; + +const RahdaranContent = ({ rahdarLists }) => { + return ( + <> + + + + + + + کد راهدار + نام + + + + {rahdarLists.map((rahdar) => { + return ( + + {rahdar.code} + {rahdar.name} + + ); + })} + +
+
+
+
+ + ); +}; +export default RahdaranContent; diff --git a/src/components/dashboard/roadPatrols/supervisor/RowActions/RahdaranForm/index.jsx b/src/components/dashboard/roadPatrols/supervisor/RowActions/RahdaranForm/index.jsx new file mode 100644 index 0000000..2c73d80 --- /dev/null +++ b/src/components/dashboard/roadPatrols/supervisor/RowActions/RahdaranForm/index.jsx @@ -0,0 +1,38 @@ +import { Button, Dialog, DialogActions, DialogTitle, IconButton, Tooltip } from "@mui/material"; +import GroupsIcon from "@mui/icons-material/Groups"; +import { useState } from "react"; +import RahdaranContent from "./RahdaranContent"; + +const RahdaranDialog = ({ rahdarLists }) => { + const [openRahdaranDialog, setOpenRahdaranDialog] = useState(false); + return ( + <> + + setOpenRahdaranDialog(true)}> + + + + setOpenRahdaranDialog(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 RahdaranDialog; diff --git a/src/components/dashboard/roadPatrols/supervisor/SupervisorList.jsx b/src/components/dashboard/roadPatrols/supervisor/SupervisorList.jsx index d653f21..5ec3369 100644 --- a/src/components/dashboard/roadPatrols/supervisor/SupervisorList.jsx +++ b/src/components/dashboard/roadPatrols/supervisor/SupervisorList.jsx @@ -1,6 +1,6 @@ "use client"; import { useMemo } from "react"; -import { Box, Stack } from "@mui/material"; +import {Box, Stack, Typography} from "@mui/material"; import DataTableWithAuth from "@/core/components/DataTableWithAuth"; import Toolbar from "./Toolbar"; import { GET_ROAD_PATROL_SUPERVISOR_LIST } from "@/core/utils/routes"; @@ -11,6 +11,8 @@ import CustomSelectByDependency from "@/core/components/DataTable/filter/fieldsT import useEdaratLists from "@/lib/hooks/useEdaratLists"; import OfficerDescriptionForm from "./RowActions/OfficerDescription"; import ReportForm from "./RowActions/ReportForm"; +import MachinesCodeDialog from "./RowActions/MachinesCodeForm"; +import RahdaranDialog from "./RowActions/RahdaranForm"; const OperatorList = () => { const columns = useMemo( @@ -93,31 +95,64 @@ const OperatorList = () => { Cell: ({ renderedCellValue, row }) => <>{row.original.edare_name}, }, { - accessorKey: "operator_name", - header: "نام مامور", - id: "operator_name", + accessorKey: "cmms_machines", + header: "خودرو", // Car ID + 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: "officer_phone_number", - header: "تلفن همراه", - id: "officer_phone_number", - enableColumnFilter: true, - datatype: "text", - filterMode: "equals", - columnFilterModeOptions: ["equals", "contains"], - }, - { - accessorKey: "car_id", - header: "کد خودرو", - id: "car_id", - enableColumnFilter: true, - datatype: "text", - filterMode: "equals", - columnFilterModeOptions: ["equals", "contains"], + accessorKey: "rahdaran", + header: "راهداران", + id: "rahdaran", + enableColumnFilter: false, + enableSorting: false, + datatype: "array", + grow: false, + size: 100, + muiTableBodyCellProps: { + sx: { + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ renderedCellValue }) => { + if (renderedCellValue) { + return ( + + + + ); + } + return بدون شخص; + }, }, { accessorFn: (row) => moment(row.start_date).locale("fa").format("HH:mm | yyyy/MM/DD"), diff --git a/src/core/components/DataTable/Main.js b/src/core/components/DataTable/Main.js index 14d8788..00d59d2 100644 --- a/src/core/components/DataTable/Main.js +++ b/src/core/components/DataTable/Main.js @@ -23,6 +23,7 @@ const DataTable_Main = (props) => { table_title, RowActions, specific_data, + specialFilter, } = props; const flatColumns = flattenArrayOfObjects(columns, "columns"); const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 }); @@ -33,29 +34,34 @@ const DataTable_Main = (props) => { }; const fetchUrl = useMemo(() => { + const params = new URLSearchParams(); + params.set("start", `${pagination.pageIndex * pagination.pageSize}`); + params.set("size", pagination.pageSize); const isValueEmpty = (value) => { if (Array.isArray(value)) { return value.length === 0 || value.every((v) => v === ""); } return value === "" || value === null || value === undefined; }; + if (specialFilter) { + const filteredSpecialFilterData = Object.values(specialFilter).filter( + (filter) => !isValueEmpty(filter.value) + ); + params.set("filters", JSON.stringify(filteredSpecialFilterData || [])); + } else { + const filteredFilterData = Object.values(filterData) + .filter((filter) => !isValueEmpty(filter.value)) + .map(({ filterMode, id, ...rest }) => ({ + ...rest, + id: id.replace(/__/g, "."), + fn: filterMode, + })); - const filteredFilterData = Object.values(filterData) - .filter((filter) => !isValueEmpty(filter.value)) - .map(({ filterMode, id, ...rest }) => ({ - ...rest, - id: id.replace(/__/g, "."), - fn: filterMode, - })); - - const params = new URLSearchParams(); - params.set("start", `${pagination.pageIndex * pagination.pageSize}`); - params.set("size", pagination.pageSize); - params.set("filters", JSON.stringify(filteredFilterData.length === 0 ? [] : filteredFilterData)); + params.set("filters", JSON.stringify(filteredFilterData.length === 0 ? [] : filteredFilterData)); + } params.set("sorting", JSON.stringify(sortData)); return `${table_url}?${params}`; - }, [table_url, filterData, pagination, columns, sortData]); - + }, [table_url, filterData, pagination, columns, sortData, specialFilter]); const fetcher = async (url) => { try { const response = await request(url); @@ -143,5 +149,4 @@ const DataTable_Main = (props) => { /> ); }; - export default DataTable_Main; diff --git a/src/core/components/MuiDatePicker.jsx b/src/core/components/MuiDatePicker.jsx index 78ffe58..10d5dff 100644 --- a/src/core/components/MuiDatePicker.jsx +++ b/src/core/components/MuiDatePicker.jsx @@ -59,9 +59,11 @@ function MuiDatePicker({ value, setFieldValue, name, minDate, maxDate, helperTex }, }} /> - - {helperText ? helperText : ""} - + {helperText ? ( + + {helperText} + + ) : null} ); diff --git a/src/core/components/MuiTimePicker.jsx b/src/core/components/MuiTimePicker.jsx index 35532fd..8aeace6 100644 --- a/src/core/components/MuiTimePicker.jsx +++ b/src/core/components/MuiTimePicker.jsx @@ -64,9 +64,11 @@ function MuiTimePicker({ value, setFieldValue, name, minTime, maxTime, helperTex }, }} /> - - {helperText ? helperText : ""} - + {helperText ? ( + + {helperText} + + ) : null} ); diff --git a/src/core/utils/routes.js b/src/core/utils/routes.js index 6c26cd2..cea920d 100644 --- a/src/core/utils/routes.js +++ b/src/core/utils/routes.js @@ -51,6 +51,7 @@ export const DELETE_BY_SUPERVISOR = api + "/api/v3/road_items/delete"; export const RESTORE_BY_SUPERVISOR = api + "/api/v3/road_items/restore"; export const GET_CAR_LIST_SEARCH = api + "/api/v3/cmms_machines/search"; export const GET_RAHDARANS_LIST_SEARCH = api + "/api/v3/rahdaran/search"; +export const GET_OBSERVED_GASHT_LIST = api + "/api/v3/observed_items/filter"; // activity code log export const ACTIVITY_LOG = api + "/api/v3/profile/add_activity"; From f37e8aea5fbeb000ee4d5692f4fefb1eb7714c08 Mon Sep 17 00:00:00 2001 From: Amirhossein Mahmoodi Date: Mon, 6 Jan 2025 12:40:09 +0330 Subject: [PATCH 6/6] add secondary color --- src/core/utils/theme.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/utils/theme.js b/src/core/utils/theme.js index 85c8f68..7cde9e0 100644 --- a/src/core/utils/theme.js +++ b/src/core/utils/theme.js @@ -1,5 +1,6 @@ "use client"; import { createTheme } from "@mui/material"; +import { grey } from '@mui/material/colors'; const theme = createTheme({ direction: "rtl", @@ -16,6 +17,9 @@ const theme = createTheme({ main: "#015688", contrastText: "#fff", }, + secondary: { + main: grey[700], + } }, components: { MuiBackdrop: {