diff --git a/.env.local.example b/.env.local.example index 8f5293b..fe53ba8 100644 --- a/.env.local.example +++ b/.env.local.example @@ -1,3 +1,3 @@ -NEXT_PUBLIC_VERSION="0.11.1" +NEXT_PUBLIC_VERSION="0.12.0" NEXT_PUBLIC_API_URL="https://rms.witel.ir" NEXT_PUBLIC_MAPTILE_ENDPOINT="https://rmsmap.rmto.ir/141map" \ No newline at end of file diff --git a/src/components/dashboard/azmayesh/AzmayeshList.jsx b/src/components/dashboard/azmayesh/AzmayeshList.jsx index 5e6d68c..904c50c 100644 --- a/src/components/dashboard/azmayesh/AzmayeshList.jsx +++ b/src/components/dashboard/azmayesh/AzmayeshList.jsx @@ -8,6 +8,7 @@ import { GET_AZMAYESH_LIST } from "@/core/utils/routes"; import ShowLocation from "./ShowLocation"; import moment from "jalali-moment"; import RowActions from "./RowActions"; +import ShowSampleOfAzmayesh from "./RowActions/ShowSampleOfAzmayesh"; const AzmayeshList = () => { const columns = useMemo( @@ -19,6 +20,16 @@ const AzmayeshList = () => { enableColumnFilter: false, datatype: "text", filterMode: "notEquals", + grow: false, + size: 100, + }, + { + accessorKey: "province_name", + header: "استان", + id: "province_name", + enableColumnFilter: false, + datatype: "text", + filterMode: "notEquals", }, { accessorKey: "azmayesh_type_name", @@ -28,6 +39,14 @@ const AzmayeshList = () => { datatype: "text", filterMode: "notEquals", }, + { + accessorKey: "contract_subitem_id", + header: "کد یکتا پروژه", + id: "contract_subitem_id", + enableColumnFilter: false, + datatype: "text", + filterMode: "equals", + }, { accessorKey: "project_name", header: "پروژه", @@ -37,13 +56,24 @@ const AzmayeshList = () => { filterMode: "equals", }, { - accessorKey: "lat", + accessorKey: "location", header: "نمایش مختصات", - id: "lat", + id: "location", enableColumnFilter: false, datatype: "text", enableSorting: false, filterMode: "equals", + grow: false, + size: 100, + muiTableBodyCellProps: { + sx: { + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, Cell: ({ row }) => , }, { @@ -101,6 +131,8 @@ const AzmayeshList = () => { enableColumnFilter: false, datatype: "date", filterMode: "equals", + grow: false, + size: 100, Cell: ({ renderedCellValue }) => ( {renderedCellValue ? moment(renderedCellValue).locale("fa").format("YYYY/MM/DD") : "-"} @@ -114,6 +146,8 @@ const AzmayeshList = () => { enableColumnFilter: false, datatype: "date", filterMode: "equals", + grow: false, + size: 100, Cell: ({ renderedCellValue }) => ( {renderedCellValue ? moment(renderedCellValue).locale("fa").format("YYYY/MM/DD") : "-"} @@ -127,12 +161,35 @@ const AzmayeshList = () => { enableColumnFilter: false, datatype: "date", filterMode: "equals", + grow: false, + size: 100, Cell: ({ renderedCellValue }) => ( {renderedCellValue ? moment(renderedCellValue).locale("fa").format("HH:mm | YYYY/MM/DD") : "-"} ), }, + { + accessorKey: "samples", + header: "نمونه ها", + id: "samples", + enableColumnFilter: false, + datatype: "text", + enableSorting: false, + filterMode: "equals", + grow: false, + size: 100, + muiTableBodyCellProps: { + sx: { + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ row }) => , + }, ], [] ); diff --git a/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUChooseLocation.jsx b/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUChooseLocation.jsx index 469b1f5..afd329f 100644 --- a/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUChooseLocation.jsx +++ b/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUChooseLocation.jsx @@ -1,11 +1,12 @@ "use client"; import { Marker, useMapEvents } from "react-leaflet"; -import { useEffect, useRef } from "react"; +import { useEffect, useRef, useState } from "react"; import L from "leaflet"; import AzmayeshIcon from "@/assets/images/examine_marker.png"; import AzmayeshActiveIcon from "@/assets/images/examine_marker_active.png"; import { + Alert, Box, Button, FormControl, @@ -14,6 +15,7 @@ import { OutlinedInput, Stack, Tooltip, + Zoom, useMediaQuery, } from "@mui/material"; import NewReleasesIcon from "@mui/icons-material/NewReleases"; @@ -21,9 +23,12 @@ 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 CandUChooseLocation = ({ mapBoxData, setMapBoxData }) => { const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down("sm")); + const [enableSend, setEnableSend] = useState(false); const mapAzmayeshMarker = useRef(); const defaultIconSize = [35, 35]; @@ -38,6 +43,7 @@ const CandUChooseLocation = ({ mapBoxData, setMapBoxData }) => { const map = useMapEvents({ move(e) { + setEnableSend(e.target.getZoom() > MAX_ZOOM_FOR_MARKER); if (!mapBoxData) { mapAzmayeshMarker.current.setLatLng(e.target.getCenter()); } @@ -52,22 +58,24 @@ const CandUChooseLocation = ({ mapBoxData, setMapBoxData }) => { mapAzmayeshMarker.current.setIcon(createCustomIcon(defaultIconSize, AzmayeshIcon.src)); } }, + zoom(e) { + setEnableSend(e.target.getZoom() > MAX_ZOOM_FOR_MARKER); + }, }); useEffect(() => { - if (mapAzmayeshMarker.current) { - const newIcon = mapBoxData - ? createCustomIcon([45, 45], AzmayeshActiveIcon.src) - : createCustomIcon(defaultIconSize, AzmayeshIcon.src); - mapAzmayeshMarker.current.setIcon(newIcon); - } + if (!mapAzmayeshMarker.current) return; if (mapBoxData) { + mapAzmayeshMarker.current.setIcon(createCustomIcon([45, 45], AzmayeshActiveIcon.src)); mapAzmayeshMarker.current.setLatLng(mapBoxData); - map.flyTo(mapBoxData, 14); + map.setView(mapBoxData, 14); + } else { + mapAzmayeshMarker.current.setIcon(createCustomIcon(defaultIconSize, AzmayeshIcon.src)); } - }, [mapBoxData]); + }, [mapBoxData, mapAzmayeshMarker.current]); const handleMarkerClick = () => { + if (!enableSend) return; if (!mapBoxData) { setMapBoxData({ lat: mapAzmayeshMarker.current.getLatLng().lat, @@ -86,93 +94,118 @@ const CandUChooseLocation = ({ mapBoxData, setMapBoxData }) => { position={map.getCenter()} ref={mapAzmayeshMarker} eventHandlers={{ click: handleMarkerClick }} - icon={createCustomIcon(defaultIconSize, AzmayeshIcon.src)} + icon={L.divIcon({ className: "" })} /> - - - - - - طول جغرافیایی - - - {mapBoxData ? ( - - ) : ( - - )} - - } - label="طول جغرافیایی" - /> - - - - - - عرض جغرافیایی - - - {mapBoxData ? ( - - ) : ( - - )} - - } - label="عرض جغرافیایی" - /> - - - - - + + + برای ثبت محل آزمایش، لطفاً نقشه را بیشتر زوم کنید. + + + + + + + + + + طول جغرافیایی + + + {mapBoxData ? ( + + ) : ( + + )} + + } + label="طول جغرافیایی" + /> + + + + + + عرض جغرافیایی + + + {mapBoxData ? ( + + ) : ( + + )} + + } + label="عرض جغرافیایی" + /> + + + + + + ); }; diff --git a/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUGeneralInfo.jsx b/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUGeneralInfo.jsx index 24f4493..359e5b9 100644 --- a/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUGeneralInfo.jsx +++ b/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUGeneralInfo.jsx @@ -66,6 +66,11 @@ const CandUGeneralInfo = ({ control, register, setValue, errors }) => { label="نوع آزمایش" /> )} + renderOption={(props, option) => ( +
  • + {option.name} +
  • + )} /> )} @@ -122,6 +127,23 @@ const CandUGeneralInfo = ({ control, register, setValue, errors }) => { )} /> + + + کد یکتا پروژه + + + {errors.contract_subitem_id ? errors.contract_subitem_id.message : null} + + + پروژه @@ -252,6 +274,7 @@ const CandUGeneralInfo = ({ control, register, setValue, errors }) => { onChange={(newValue) => { onChange(newValue); }} + closeOnSelect slotProps={{ textField: { size: "small", @@ -305,6 +328,7 @@ const CandUGeneralInfo = ({ control, register, setValue, errors }) => { onChange={(newValue) => { onChange(newValue); }} + closeOnSelect slotProps={{ textField: { size: "small", diff --git a/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/FormAndRequest.jsx b/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/FormAndRequest.jsx index f74dd22..f397229 100644 --- a/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/FormAndRequest.jsx +++ b/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/FormAndRequest.jsx @@ -33,6 +33,7 @@ function TabPanel(props) { const validationSchema = object({ azmayesh_type_id: string().required("نوع آزمایش را مشخص کنید!"), province_id: string().required("استان را وارد کنید!"), + contract_subitem_id: string().required("کد یکتا پروژه را وارد کنید!"), project_name: string().required("عنوان پروژه را وارد کنید!"), employer: string().required("کارفرما را وارد کنید!"), consultant: string().required("مشاور را وارد کنید!"), @@ -46,7 +47,7 @@ const validationSchema = object({ const CandUAzmayesh = ({ setOpen, mutate, updateInfo, rowId }) => { const theme = useTheme(); - const requestServer = useRequest({ auth: true }); + const requestServer = useRequest({ notificationSuccess: true }); const isMobile = useMediaQuery(theme.breakpoints.down("sm")); const [tabState, setTabState] = useState(0); const [mapBoxData, setMapBoxData] = useState(updateInfo ? { lat: updateInfo.lat, lng: updateInfo.lng } : null); @@ -72,6 +73,7 @@ const CandUAzmayesh = ({ setOpen, mutate, updateInfo, rowId }) => { azmayesh_type_name: updateInfo ? updateInfo.azmayesh_type_name : "", province_id: updateInfo ? updateInfo.province_id : "", province_name: updateInfo ? updateInfo.province_name : "", + contract_subitem_id: updateInfo ? updateInfo.contract_subitem_id : "", project_name: updateInfo ? updateInfo.project_name : "", employer: updateInfo ? updateInfo.employer : "", consultant: updateInfo ? updateInfo.consultant : "", @@ -88,7 +90,7 @@ const CandUAzmayesh = ({ setOpen, mutate, updateInfo, rowId }) => { register, handleSubmit, setValue, - formState: { isSubmitting, errors, touchedFields }, + formState: { isSubmitting, errors }, } = useForm({ defaultValues, resolver: yupResolver(validationSchema), mode: "onBlur" }); const onSubmit = async (data) => { @@ -99,6 +101,7 @@ const CandUAzmayesh = ({ setOpen, mutate, updateInfo, rowId }) => { formData.append("azmayesh_type_name", data.azmayesh_type_name); formData.append("province_id", data.province_id); formData.append("province_name", data.province_name); + formData.append("contract_subitem_id", data.contract_subitem_id); formData.append("project_name", data.project_name); formData.append("employer", data.employer); formData.append("consultant", data.consultant); @@ -109,14 +112,13 @@ const CandUAzmayesh = ({ setOpen, mutate, updateInfo, rowId }) => { formData.append("request_date", moment(new Date(data.request_date)).format("YYYY-MM-DD")); formData.append("report_date", moment(new Date(data.report_date)).format("YYYY-MM-DD")); - requestServer(updateInfo ? `${UPDATE_AZMAYESH}/${rowId}` : CREATE_AZMAYESH, "post", { - data: formData, - }) - .then(() => { - mutate(); - handleClose(); - }) - .catch(() => {}); + try { + await requestServer(updateInfo ? `${UPDATE_AZMAYESH}/${rowId}` : CREATE_AZMAYESH, "post", { + data: formData, + }); + mutate(); + handleClose(); + } catch (error) {} }; return ( diff --git a/src/components/dashboard/azmayesh/RowActions/AzmayeshUpdate/index.jsx b/src/components/dashboard/azmayesh/RowActions/AzmayeshUpdate/index.jsx index f36bbae..d1dc7b6 100644 --- a/src/components/dashboard/azmayesh/RowActions/AzmayeshUpdate/index.jsx +++ b/src/components/dashboard/azmayesh/RowActions/AzmayeshUpdate/index.jsx @@ -6,7 +6,7 @@ import { GET_AZMAYESH_LIST } from "@/core/utils/routes"; import CandUAzmayesh from "@/components/dashboard/azmayesh/Forms/CandUAzmayesh"; const AzmayeshUpdate = ({ rowId, mutate }) => { - const requestServer = useRequest({ auth: true }); + const requestServer = useRequest(); const [openUpdateDialog, setOpenUpdateDialog] = useState(false); const [updateInfo, setUpdateInfo] = useState(null); const [loadingOpen, setLoadingOpen] = useState(false); diff --git a/src/components/dashboard/azmayesh/RowActions/DeleteAzmayesh/index.jsx b/src/components/dashboard/azmayesh/RowActions/DeleteAzmayesh/index.jsx index c424e8e..ed25f23 100644 --- a/src/components/dashboard/azmayesh/RowActions/DeleteAzmayesh/index.jsx +++ b/src/components/dashboard/azmayesh/RowActions/DeleteAzmayesh/index.jsx @@ -14,7 +14,7 @@ import DeleteIcon from "@mui/icons-material/Delete"; import { DELETE_AZMAYESH } from "@/core/utils/routes"; const DeleteAzmayesh = ({ rowId, mutate }) => { - const requestServer = useRequest({ auth: true }); + const requestServer = useRequest({ notificationSuccess: true }); const [openDeleteDialog, setOpenDeleteDialog] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false); diff --git a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Actions/Create/index.jsx b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Actions/Create/index.jsx index 3cecfb6..2139d22 100644 --- a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Actions/Create/index.jsx +++ b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Actions/Create/index.jsx @@ -7,7 +7,7 @@ import { useTheme } from "@emotion/react"; import CandUSampleOfAzmayesh from "@/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Forms/CandUSampleOfAzmayesh"; const AddSampleToAzmayesh = ({ azmayeshTypeId, mutate, rowId }) => { - const requestServer = useRequest({ auth: true }); + const requestServer = useRequest(); const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down("sm")); const [sampleInfo, setSampleInfo] = useState(null); diff --git a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Forms/CandUSampleOfAzmayesh/FormAndRequest.jsx b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Forms/CandUSampleOfAzmayesh/FormAndRequest.jsx index 682c13c..a6c89fa 100644 --- a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Forms/CandUSampleOfAzmayesh/FormAndRequest.jsx +++ b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Forms/CandUSampleOfAzmayesh/FormAndRequest.jsx @@ -15,10 +15,10 @@ const CandUSampleOfAzmayesh = ({ isUpdate, azmayesh_id, }) => { - const requestServer = useRequest({ auth: true }); + const requestServer = useRequest({ notificationSuccess: true }); const [isSubmitting, setIsSubmitting] = useState(false); - const handleSubmit = () => { + const handleSubmit = async () => { const data = {}; setIsSubmitting(true); const formData = new FormData(); @@ -27,17 +27,20 @@ const CandUSampleOfAzmayesh = ({ data[key] = value; }); formData.append("data", JSON.stringify(data)); - requestServer(isUpdate ? `${UPDATE_SAMPLE_OF_AZMAYESH}/${rowId}` : `${ADD_SAMPLE_TO_AZMAYESH}`, "post", { - data: formData, - }) - .then(() => { - mutate(); - }) - .catch(() => {}) - .finally(() => { - setOpenSampleDialog(false); - setIsSubmitting(false); - }); + try { + await requestServer( + isUpdate ? `${UPDATE_SAMPLE_OF_AZMAYESH}/${rowId}` : `${ADD_SAMPLE_TO_AZMAYESH}`, + "post", + { + data: formData, + } + ); + mutate(); + setOpenSampleDialog(false); + setIsSubmitting(false); + } catch (error) { + setIsSubmitting(false); + } }; return ( diff --git a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Forms/CandUSampleOfAzmayesh/index.jsx b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Forms/CandUSampleOfAzmayesh/index.jsx index 7709eda..5cabf7c 100644 --- a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Forms/CandUSampleOfAzmayesh/index.jsx +++ b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Forms/CandUSampleOfAzmayesh/index.jsx @@ -16,7 +16,7 @@ const CandUSampleOfAzmayesh = ({ isUpdate, azmayesh_id, }) => { - const requestServer = useRequest({ auth: true }); + const requestServer = useRequest({ notificationSuccess: true }); const [isSubmitting, setIsSubmitting] = useState(false); const handleSubmit = () => { diff --git a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/RowActions/DeleteSample.jsx b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/RowActions/DeleteSample.jsx index 477afeb..b382fa1 100644 --- a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/RowActions/DeleteSample.jsx +++ b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/RowActions/DeleteSample.jsx @@ -14,7 +14,7 @@ import DeleteIcon from "@mui/icons-material/Delete"; import { DELETE_SAMPLE_LIST } from "@/core/utils/routes"; const DeleteSample = ({ rowId, mutate }) => { - const requestServer = useRequest({ auth: true }); + const requestServer = useRequest({ notificationSuccess: true }); const [openDeleteDialog, setOpenDeleteDialog] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false); diff --git a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/RowActions/UpdateSample.jsx b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/RowActions/UpdateSample.jsx index f16253a..3516f47 100644 --- a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/RowActions/UpdateSample.jsx +++ b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/RowActions/UpdateSample.jsx @@ -6,7 +6,7 @@ import CandUSampleOfAzmayesh from "@/components/dashboard/azmayesh/RowActions/Sh import EditIcon from "@mui/icons-material/Edit"; const UpdateSample = ({ azmayeshTypeId, mutate, rowId, azmayesh_id }) => { - const requestServer = useRequest({ auth: true }); + const requestServer = useRequest(); const [sampleInfo, setSampleInfo] = useState(null); const [openUpdateSampleDialog, setOpenUpdateSampleDialog] = useState(false); const [defaultValues, setDefaultValues] = useState({}); diff --git a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/ShowSampleList.jsx b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/ShowSampleList.jsx index 2c11f67..e55d9ab 100644 --- a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/ShowSampleList.jsx +++ b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/ShowSampleList.jsx @@ -24,10 +24,12 @@ const ShowSampleList = ({ sampleInfo, rowData }) => { id: "id", enableColumnFilter: false, datatype: "text", + grow: false, + size: 100, }, ...sampleInfo.map((item) => ({ accessorKey: item.id.toString(), - header: item.name, + header: item.unit ? `${item.name} (${item.unit})` : item.name, id: item.id.toString(), enableColumnFilter: false, datatype: "text", @@ -38,6 +40,8 @@ const ShowSampleList = ({ sampleInfo, rowData }) => { id: "updated_at", enableColumnFilter: false, datatype: "date", + grow: false, + size: 100, Cell: ({ renderedCellValue }) => ( {renderedCellValue ? moment(renderedCellValue).locale("fa").format("HH:mm | YYYY/MM/DD") : "-"} diff --git a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/index.jsx b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/index.jsx index 1677d82..a3ba7e9 100644 --- a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/index.jsx +++ b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/index.jsx @@ -1,4 +1,4 @@ -import { Button, Dialog, DialogActions, DialogContent, IconButton, Tooltip } from "@mui/material"; +import { Box, Button, Dialog, DialogActions, DialogContent, IconButton, Tooltip } from "@mui/material"; import AssignmentIcon from "@mui/icons-material/Assignment"; import { useState } from "react"; import ShowSampleList from "./ShowSampleList"; @@ -6,7 +6,7 @@ import { GET_AZMAYESH_SAMPLE_FIELDS } from "@/core/utils/routes"; import useRequest from "@/lib/hooks/useRequest"; const ShowSampleOfAzmayesh = ({ rowData }) => { - const requestServer = useRequest({ auth: true }); + const requestServer = useRequest(); const [openShowSampleDialog, setOpenShowSampleDialog] = useState(false); const [sampleInfo, setSampleInfo] = useState(null); const handleGetSampleFields = () => { @@ -20,7 +20,7 @@ const ShowSampleOfAzmayesh = ({ rowData }) => { }); }; return ( - <> + { - + @@ -40,7 +40,7 @@ const ShowSampleOfAzmayesh = ({ rowData }) => { - + ); }; export default ShowSampleOfAzmayesh; diff --git a/src/components/dashboard/azmayesh/RowActions/index.jsx b/src/components/dashboard/azmayesh/RowActions/index.jsx index 19447cb..7f6440d 100644 --- a/src/components/dashboard/azmayesh/RowActions/index.jsx +++ b/src/components/dashboard/azmayesh/RowActions/index.jsx @@ -7,7 +7,6 @@ const RowActions = ({ row, mutate }) => { return ( - ); diff --git a/src/components/dashboard/azmayeshType/Forms/CandUAzmayeshType/FormAndRequest.jsx b/src/components/dashboard/azmayeshType/Forms/CandUAzmayeshType/FormAndRequest.jsx index 79a8d5b..a794154 100644 --- a/src/components/dashboard/azmayeshType/Forms/CandUAzmayeshType/FormAndRequest.jsx +++ b/src/components/dashboard/azmayeshType/Forms/CandUAzmayeshType/FormAndRequest.jsx @@ -42,9 +42,8 @@ const validationSchema = object({ }); const FormAndRequest = ({ setOpen, mutate, rowId, updateInfo }) => { - const requestServer = useRequest({ auth: true }); + const requestServer = useRequest({ notificationSuccess: true }); const [selectedListItem, setSelectedListItem] = useState(null); - const [isSubmitting, setIsSubmitting] = useState(false); const handleClose = () => { setOpen(false); @@ -68,7 +67,7 @@ const FormAndRequest = ({ setOpen, mutate, rowId, updateInfo }) => { handleSubmit, setValue, watch, - formState: { errors }, + formState: { errors, isSubmitting }, } = useForm({ defaultValues, resolver: yupResolver(validationSchema), mode: "onBlur" }); const { fields, append, remove } = useFieldArray({ @@ -90,25 +89,22 @@ const FormAndRequest = ({ setOpen, mutate, rowId, updateInfo }) => { }; const onSubmit = async (data) => { - setIsSubmitting(true); const formData = new FormData(); formData.append("name", data.name); data.fields.map((field, index) => { formData.append(`fields[${index}][name]`, field.name); - formData.append(`fields[${index}][unit]`, field.unit); + if (field.unit !== "") formData.append(`fields[${index}][unit]`, field.unit); formData.append(`fields[${index}][type]`, field.type); if (field.options.length !== 0) formData.append(`fields[${index}][option]`, JSON.stringify(field.options)); }); - requestServer(updateInfo ? `${UPDATE_AZMAYESH_TYPE}/${rowId}` : ADD_AZMAYESH_TYPE, "post", { - data: formData, - }) - .then(() => { - mutate(); - handleClose(); - }) - .catch(() => {}) - .finally(() => setIsSubmitting(false)); + try { + await requestServer(updateInfo ? `${UPDATE_AZMAYESH_TYPE}/${rowId}` : ADD_AZMAYESH_TYPE, "post", { + data: formData, + }); + mutate(); + handleClose(); + } catch (error) {} }; return ( diff --git a/src/components/dashboard/azmayeshType/RowActions/DeleteAzmayeshType/index.jsx b/src/components/dashboard/azmayeshType/RowActions/DeleteAzmayeshType/index.jsx index 888ab6d..78d400d 100644 --- a/src/components/dashboard/azmayeshType/RowActions/DeleteAzmayeshType/index.jsx +++ b/src/components/dashboard/azmayeshType/RowActions/DeleteAzmayeshType/index.jsx @@ -14,7 +14,7 @@ import { useState } from "react"; import { DELETE_AZMAYESH_TYPE_LIST } from "@/core/utils/routes"; const DeleteAzmayeshType = ({ rowId, mutate }) => { - const requestServer = useRequest({ auth: true }); + const requestServer = useRequest({ notificationSuccess: true }); const [openDeleteDialog, setOpenDeleteDialog] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false); diff --git a/src/components/dashboard/azmayeshType/RowActions/UpdateAzmayeshType/index.jsx b/src/components/dashboard/azmayeshType/RowActions/UpdateAzmayeshType/index.jsx index b94dcf6..7c7099f 100644 --- a/src/components/dashboard/azmayeshType/RowActions/UpdateAzmayeshType/index.jsx +++ b/src/components/dashboard/azmayeshType/RowActions/UpdateAzmayeshType/index.jsx @@ -6,7 +6,7 @@ import useRequest from "@/lib/hooks/useRequest"; import CandUAzmayeshType from "@/components/dashboard/azmayeshType/Forms/CandUAzmayeshType"; const UpdateAzmayeshType = ({ rowId, mutate }) => { - const requestServer = useRequest({ auth: true }); + const requestServer = useRequest(); const [openUpdateDialog, setOpenUpdateDialog] = useState(false); const [updateInfo, setUpdateInfo] = useState(null); const [loadingOpen, setLoadingOpen] = useState(false); 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 c6d82d5..14d8788 100644 --- a/src/core/components/DataTable/Main.js +++ b/src/core/components/DataTable/Main.js @@ -42,8 +42,9 @@ const DataTable_Main = (props) => { const filteredFilterData = Object.values(filterData) .filter((filter) => !isValueEmpty(filter.value)) - .map(({ filterMode, ...rest }) => ({ + .map(({ filterMode, id, ...rest }) => ({ ...rest, + 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 ? ( { [itemInfo.id]: value, })); }; + const label = itemInfo.unit ? `${itemInfo.name} (${itemInfo.unit})` : itemInfo.name; return ( - {itemInfo.name} + {label} { [itemInfo.id]: newValue, })); }; - + const label = itemInfo.unit ? `${itemInfo.name} (${itemInfo.unit})` : itemInfo.name; return ( - {itemInfo.name} + {label}