diff --git a/.env.local.example b/.env.local.example index 94a14f9..37b65ca 100644 --- a/.env.local.example +++ b/.env.local.example @@ -1,4 +1,4 @@ HOST="rms.witel.ir" -NEXT_PUBLIC_VERSION="0.17.0" +NEXT_PUBLIC_VERSION="0.18.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/app/(withAuth)/dashboard/azmayesh/page.js b/src/app/(withAuth)/dashboard/azmayesh/page.js index 164a4b6..2ef1bbb 100644 --- a/src/app/(withAuth)/dashboard/azmayesh/page.js +++ b/src/app/(withAuth)/dashboard/azmayesh/page.js @@ -2,6 +2,10 @@ import AzmayeshPage from "@/components/dashboard/azmayesh"; import WithPermission from "@/core/middlewares/withPermission"; import ActivityCodeLog from "@/core/components/ActivityCodeLog"; +export const metadata = { + title: "کارتابل آزمایشات", +}; + const Page = () => { return ( diff --git a/src/app/(withAuth)/dashboard/azmayesh_type/page.js b/src/app/(withAuth)/dashboard/azmayesh_type/page.js index 77a604a..91acd5b 100644 --- a/src/app/(withAuth)/dashboard/azmayesh_type/page.js +++ b/src/app/(withAuth)/dashboard/azmayesh_type/page.js @@ -1,7 +1,9 @@ import AzmayeshTypePage from "@/components/dashboard/azmayeshType"; import WithPermission from "@/core/middlewares/withPermission"; import ActivityCodeLog from "@/core/components/ActivityCodeLog"; - +export const metadata = { + title: "کارتابل نوع آزمایشات", +}; const Page = () => { return ( diff --git a/src/app/(withAuth)/dashboard/damage-items/page.js b/src/app/(withAuth)/dashboard/damage-items/page.js index 1a222ae..16459f9 100644 --- a/src/app/(withAuth)/dashboard/damage-items/page.js +++ b/src/app/(withAuth)/dashboard/damage-items/page.js @@ -1,6 +1,8 @@ import DamagesPage from "@/components/dashboard/damageItems"; import WithPermission from "@/core/middlewares/withPermission"; - +export const metadata = { + title: "آیتم خسارات", +}; const Page = () => { return ( diff --git a/src/app/(withAuth)/dashboard/damages/operator/page.js b/src/app/(withAuth)/dashboard/damages/operator/page.js index 8715b11..ce06298 100644 --- a/src/app/(withAuth)/dashboard/damages/operator/page.js +++ b/src/app/(withAuth)/dashboard/damages/operator/page.js @@ -1,6 +1,9 @@ import WithPermission from "@/core/middlewares/withPermission"; import ActivityCodeLog from "@/core/components/ActivityCodeLog"; import OperatorPage from "@/components/dashboard/damages/operator"; +export const metadata = { + title: "کارتابل عملیات خسارات وارد بر ابنیه فنی", +}; const Page = () => { return ( diff --git a/src/app/(withAuth)/dashboard/damages/report/page.js b/src/app/(withAuth)/dashboard/damages/report/page.js index d6bfd78..1ffbf85 100644 --- a/src/app/(withAuth)/dashboard/damages/report/page.js +++ b/src/app/(withAuth)/dashboard/damages/report/page.js @@ -1,6 +1,8 @@ import DamagesReportPage from "@/components/dashboard/damages/report"; import WithPermission from "@/core/middlewares/withPermission"; - +export const metadata = { + title: "کارتابل گزارش خسارات وارد بر ابنیه فنی", +}; const Page = () => { return ( diff --git a/src/app/(withAuth)/dashboard/fast-react/operator/page.js b/src/app/(withAuth)/dashboard/fast-react/operator/page.js index 89fe922..a3c82ba 100644 --- a/src/app/(withAuth)/dashboard/fast-react/operator/page.js +++ b/src/app/(withAuth)/dashboard/fast-react/operator/page.js @@ -1,5 +1,8 @@ import OperatorPage from "@/components/dashboard/fastReact/operator"; import WithPermission from "@/core/middlewares/withPermission"; +export const metadata = { + title: "کارتابل عملیات واکنش سریع", +}; const Page = () => { return ( diff --git a/src/app/(withAuth)/dashboard/fast-react/supervisor/page.js b/src/app/(withAuth)/dashboard/fast-react/supervisor/page.js index 820c1af..e5f8ce8 100644 --- a/src/app/(withAuth)/dashboard/fast-react/supervisor/page.js +++ b/src/app/(withAuth)/dashboard/fast-react/supervisor/page.js @@ -1,6 +1,9 @@ import WithPermission from "@/core/middlewares/withPermission"; import SupervisorPage from "@/components/dashboard/fastReact/supervisor"; import ActivityCodeLog from "@/core/components/ActivityCodeLog"; +export const metadata = { + title: "کارتابل ارزیابی واکنش سریع", +}; const Page = () => { return ( diff --git a/src/app/(withAuth)/dashboard/permissions/page.js b/src/app/(withAuth)/dashboard/permissions/page.js new file mode 100644 index 0000000..1dcd0b2 --- /dev/null +++ b/src/app/(withAuth)/dashboard/permissions/page.js @@ -0,0 +1,13 @@ +import WithPermission from "@/core/middlewares/withPermission"; +import PermissionTablePage from "@/components/dashboard/permissionTable"; +export const metadata = { + title: "سطح دسترسی ها", +}; +const Page = () => { + return ( + + + + ); +}; +export default Page; diff --git a/src/app/(withAuth)/dashboard/road-items/operator/page.js b/src/app/(withAuth)/dashboard/road-items/operator/page.js index 324c997..daade12 100644 --- a/src/app/(withAuth)/dashboard/road-items/operator/page.js +++ b/src/app/(withAuth)/dashboard/road-items/operator/page.js @@ -1,6 +1,9 @@ import WithPermission from "@/core/middlewares/withPermission"; import OperatorPage from "@/components/dashboard/roadItems/operator"; import ActivityCodeLog from "@/core/components/ActivityCodeLog"; +export const metadata = { + title: "کارتابل عملیات فعالیت روزانه", +}; const Page = () => { return ( diff --git a/src/app/(withAuth)/dashboard/road-items/reports/items-report/page.js b/src/app/(withAuth)/dashboard/road-items/reports/items-report/page.js index ab991b0..ab16926 100644 --- a/src/app/(withAuth)/dashboard/road-items/reports/items-report/page.js +++ b/src/app/(withAuth)/dashboard/road-items/reports/items-report/page.js @@ -1,6 +1,8 @@ import WithPermission from "@/core/middlewares/withPermission"; import ReportPage from "@/components/dashboard/roadItems/reports/ItemsReports"; - +export const metadata = { + title: "کارتابل گزارش تعداد فعالیت ها به تفکیک آیتم", +}; const Page = () => { return ( { return ; diff --git a/src/app/(withAuth)/dashboard/road-items/reports/sub-items-report/page.js b/src/app/(withAuth)/dashboard/road-items/reports/sub-items-report/page.js index d605501..a83d75f 100644 --- a/src/app/(withAuth)/dashboard/road-items/reports/sub-items-report/page.js +++ b/src/app/(withAuth)/dashboard/road-items/reports/sub-items-report/page.js @@ -1,5 +1,8 @@ import WithPermission from "@/core/middlewares/withPermission"; import SubItemsReports from "@/components/dashboard/roadItems/reports/SubItemsReports"; +export const metadata = { + title: "کارتابل گزارش تعداد فعالیت ها به تفکیک موارد مشاهده شده", +}; const Page = () => { return ( { return ( { return ( diff --git a/src/app/(withAuth)/dashboard/road-patrols/reports/page.js b/src/app/(withAuth)/dashboard/road-patrols/reports/page.js index 5f6cfcf..48e1056 100644 --- a/src/app/(withAuth)/dashboard/road-patrols/reports/page.js +++ b/src/app/(withAuth)/dashboard/road-patrols/reports/page.js @@ -1,6 +1,8 @@ import WithPermission from "@/core/middlewares/withPermission"; import ReportPage from "@/components/dashboard/roadPatrols/reports"; - +export const metadata = { + title: "کارتابل گزارش گشت راهداری", +}; const Page = () => { return ( { return ( { + return ; +}; +export default Loading; diff --git a/src/app/(withAuth)/dashboard/road-safety/operator/page.js b/src/app/(withAuth)/dashboard/road-safety/operator/page.js new file mode 100644 index 0000000..3ce87a7 --- /dev/null +++ b/src/app/(withAuth)/dashboard/road-safety/operator/page.js @@ -0,0 +1,22 @@ +import WithPermission from "@/core/middlewares/withPermission"; +import OperatorPage from "@/components/dashboard/roadSafety/operator"; +// import ActivityCodeLog from "@/core/components/ActivityCodeLog"; +export const metadata = { + title: "کارتابل عملیات نگهداری حریم", +}; +const Page = () => { + return ( + + + {/**/} + + ); +}; + +export default Page; diff --git a/src/app/(withAuth)/dashboard/road-safety/report/page.js b/src/app/(withAuth)/dashboard/road-safety/report/page.js new file mode 100644 index 0000000..26681da --- /dev/null +++ b/src/app/(withAuth)/dashboard/road-safety/report/page.js @@ -0,0 +1,19 @@ +import ReportPage from "@/components/dashboard/roadSafety/report"; +import WithPermission from "@/core/middlewares/withPermission"; +export const metadata = { + title: "کارتابل گزارش نگهداری حریم", +}; +const Page = () => { + return ( + + + + ); +}; +export default Page; diff --git a/src/app/(withAuth)/dashboard/user-activities/page.js b/src/app/(withAuth)/dashboard/user-activities/page.js new file mode 100644 index 0000000..c671c77 --- /dev/null +++ b/src/app/(withAuth)/dashboard/user-activities/page.js @@ -0,0 +1,13 @@ +import UserActivitiesPage from "@/components/dashboard/userActivities"; +import WithPermission from "@/core/middlewares/withPermission"; +export const metadata = { + title: "انواع فعالیت کاربران", +}; +const Page = () => { + return ( + + + + ); +}; +export default Page; diff --git a/src/app/layout.js b/src/app/layout.js index f0786a8..089cb8d 100644 --- a/src/app/layout.js +++ b/src/app/layout.js @@ -3,7 +3,10 @@ import { AuthProvider } from "@/lib/contexts/auth"; import { TableSettingProvider } from "@/lib/contexts/tableSetting"; export const metadata = { - title: "سامانه جامع راهداری", + title: { + template: "%s | سامانه جامع راهداری", + default: "سامانه جامع راهداری", + }, }; export default function RootLayout({ children }) { diff --git a/src/components/dashboard/azmayesh/index.jsx b/src/components/dashboard/azmayesh/index.jsx index a7f49de..1b142c2 100644 --- a/src/components/dashboard/azmayesh/index.jsx +++ b/src/components/dashboard/azmayesh/index.jsx @@ -7,7 +7,7 @@ import AzmayeshList from "./AzmayeshList"; const AzmayeshPage = () => { return ( - + ); diff --git a/src/components/dashboard/azmayeshType/AzmayeshTypeList.jsx b/src/components/dashboard/azmayeshType/AzmayeshTypeList.jsx index eef84f9..8aa0f4b 100644 --- a/src/components/dashboard/azmayeshType/AzmayeshTypeList.jsx +++ b/src/components/dashboard/azmayeshType/AzmayeshTypeList.jsx @@ -52,7 +52,7 @@ const AzmayeshTypeList = () => { columns={columns} sorting={[{ id: "id", desc: true }]} table_url={GET_AZMAYESH_TYPE_LIST_TABLE} - page_name={"azmayesh_type"} + page_name={"azmayeshType"} table_name={"azmayeshTypeList"} TableToolbar={Toolbar} enableRowActions diff --git a/src/components/dashboard/azmayeshType/index.jsx b/src/components/dashboard/azmayeshType/index.jsx index b7ec580..12c4aa9 100644 --- a/src/components/dashboard/azmayeshType/index.jsx +++ b/src/components/dashboard/azmayeshType/index.jsx @@ -7,7 +7,7 @@ import AzmayeshTypeList from "./AzmayeshTypeList"; const AzmayeshTypePage = () => { return ( - + ); diff --git a/src/components/dashboard/damageItems/DamagesList.jsx b/src/components/dashboard/damageItems/DamagesList.jsx index e93d216..2050359 100644 --- a/src/components/dashboard/damageItems/DamagesList.jsx +++ b/src/components/dashboard/damageItems/DamagesList.jsx @@ -70,8 +70,8 @@ const DamagesList = () => { columns={columns} sorting={[{ id: "id", desc: true }]} table_url={GET_RECEIPT_DAMAGE_ITEMS_LIST} - page_name={"receiptDamanagePage"} - table_name={"damanageList"} + page_name={"receiptDamagePage"} + table_name={"receiptDamageList"} TableToolbar={Toolbar} enableRowActions positionActionsColumn={"last"} diff --git a/src/components/dashboard/damages/operator/Actions/create/Forms/CreateFormContent.jsx b/src/components/dashboard/damages/operator/Actions/create/Forms/CreateFormContent.jsx index 11ec3b4..2123236 100644 --- a/src/components/dashboard/damages/operator/Actions/create/Forms/CreateFormContent.jsx +++ b/src/components/dashboard/damages/operator/Actions/create/Forms/CreateFormContent.jsx @@ -80,6 +80,7 @@ const CreateFormContent = ({ setOpen, SubmitDamage, defaultData }) => { accident_type: defaultData.accident_type, province_id: defaultData.province_id, city_id: defaultData.city_id, + is_province: defaultData.is_province, axis_name: defaultData.axis_name, driver_name: defaultData.driver_name, phone_number: defaultData.phone_number, diff --git a/src/components/dashboard/damages/operator/Actions/create/Forms/DamageInfo.jsx b/src/components/dashboard/damages/operator/Actions/create/Forms/DamageInfo.jsx index 797610c..7f823a5 100644 --- a/src/components/dashboard/damages/operator/Actions/create/Forms/DamageInfo.jsx +++ b/src/components/dashboard/damages/operator/Actions/create/Forms/DamageInfo.jsx @@ -3,66 +3,18 @@ import { Grid, Stack, TextField } from "@mui/material"; import MuiDatePicker from "@/core/components/MuiDatePicker"; import MuiTimePicker from "@/core/components/MuiTimePicker"; import SelectBox from "@/core/components/SelectBox"; -import useProvinces from "@/lib/hooks/useProvince"; import PlateNumber from "@/core/components/PlateNumber"; import ImageUpload from "./ImageUpload"; import MapInfoOneMarker from "@/core/components/MapInfoOneMarker"; -import CityController from "@/components/dashboard/damages/operator/Actions/create/Forms/CityController"; import PersianTextField from "@/core/components/PersianTextField"; +import LogesticController from "./LogesticController"; const DamageInfo = ({ control, setValue, errors }) => { const StartPoint = useWatch({ control, name: "start_point" }); - const { provinces, errorProvinces, loadingProvinces } = useProvinces(); return ( - - - { - return ( - - ); - }} - /> - - - - - - ( - - )} - /> - - + { value={field.value} variant="outlined" name="driver_name" - fieldOnChange={field.onChange} + onChange={field.onChange} label="نام و نام خانوادگی راننده" placeholder={"نام و نام خانوادگی فارسی را وارد کنید"} fullWidth diff --git a/src/components/dashboard/damages/operator/Actions/create/Forms/LogesticController.jsx b/src/components/dashboard/damages/operator/Actions/create/Forms/LogesticController.jsx new file mode 100644 index 0000000..a53059b --- /dev/null +++ b/src/components/dashboard/damages/operator/Actions/create/Forms/LogesticController.jsx @@ -0,0 +1,64 @@ +import { Controller, useWatch } from "react-hook-form"; +import SelectBox from "@/core/components/SelectBox"; +import useProvinces from "@/lib/hooks/useProvince"; +import { Grid } from "@mui/material"; +import CityController from "./CityController"; +import PersianTextField from "@/core/components/PersianTextField"; + +const LogesticController = ({ control }) => { + const { provinces, errorProvinces, loadingProvinces } = useProvinces(); + const isProvince = useWatch({ control, name: "is_province" }); + return ( + + {!isProvince ? ( + + { + return ( + + ); + }} + /> + + ) : null} + + + + + ( + + )} + /> + + + ); +}; +export default LogesticController; diff --git a/src/components/dashboard/damages/operator/Actions/create/Forms/index.jsx b/src/components/dashboard/damages/operator/Actions/create/Forms/index.jsx index ab50184..01d0141 100644 --- a/src/components/dashboard/damages/operator/Actions/create/Forms/index.jsx +++ b/src/components/dashboard/damages/operator/Actions/create/Forms/index.jsx @@ -5,9 +5,14 @@ import { format } from "date-fns"; import { CREATE_DAMAGE } from "@/core/utils/routes"; import useRequest from "@/lib/hooks/useRequest"; import CloseIcon from "@mui/icons-material/Close"; +import { usePermissions } from "@/lib/hooks/usePermissions"; +import { useAuth } from "@/lib/contexts/auth"; const OperatorCreateForm = ({ open, setOpen, mutate }) => { const requestServer = useRequest({ notificationSuccess: true }); + const { user } = useAuth(); + const { data: userPermissions } = usePermissions(); + const hasCreateProvincePermission = userPermissions.some((item) => ["add-receipt"].includes(item)); const SubmitCreateDamage = async (result) => { const PlateNumber = `${result.plate_part1}-${result.plate_part2}-${result.plate_part3}-${result.plate_part4}`; const formData = new FormData(); @@ -52,7 +57,8 @@ const OperatorCreateForm = ({ open, setOpen, mutate }) => { accident_date: "", accident_time: "", accident_type: "", - province_id: null, + province_id: !hasCreateProvincePermission ? user.province_id : null, + is_province: !hasCreateProvincePermission, city_id: null, axis_name: "", driver_name: "", diff --git a/src/components/dashboard/damages/operator/Form/EditForm/EditController.jsx b/src/components/dashboard/damages/operator/Form/EditForm/EditController.jsx index f545cc6..d6e2b3d 100644 --- a/src/components/dashboard/damages/operator/Form/EditForm/EditController.jsx +++ b/src/components/dashboard/damages/operator/Form/EditForm/EditController.jsx @@ -5,11 +5,16 @@ import { GET_DAMAGE_ITEM_DETAILS, UPDATE_DAMAGE_ITEM } from "@/core/utils/routes import DialogLoading from "@/core/components/DialogLoading"; import { format } from "date-fns"; import moment from "jalali-moment"; +import { useAuth } from "@/lib/contexts/auth"; +import { usePermissions } from "@/lib/hooks/usePermissions"; const EditController = ({ rowId, mutate, setOpenEditDialog }) => { const requestServer = useRequest(); const [damageItemDetails, setDamageItemDetails] = useState(null); const [damageItemDetailsLoading, setDamageItemDetailsLoading] = useState(false); + const { user } = useAuth(); + const { data: userPermissions } = usePermissions(); + const hasCreateProvincePermission = userPermissions.some((item) => ["add-receipt"].includes(item)); useEffect(() => { setDamageItemDetailsLoading(true); @@ -46,6 +51,7 @@ const EditController = ({ rowId, mutate, setOpenEditDialog }) => { radio_button: damageItemDetails?.report_base === 1 ? "report_base" : "police_file_checkbox", report_base: damageItemDetails?.report_base, province_id: damageItemDetails?.province_id || null, + is_province: !hasCreateProvincePermission, city_id: damageItemDetails?.city_id || null, start_point: { lat: damageItemDetails?.lat || "", lng: damageItemDetails?.lng || "" }, }; diff --git a/src/components/dashboard/damages/operator/OperatorList.jsx b/src/components/dashboard/damages/operator/OperatorList.jsx index 15907c0..ec6b61e 100644 --- a/src/components/dashboard/damages/operator/OperatorList.jsx +++ b/src/components/dashboard/damages/operator/OperatorList.jsx @@ -256,7 +256,7 @@ const OperatorList = () => { } return ( - بدون تصویر + - ); }, @@ -451,8 +451,8 @@ const OperatorList = () => { need_filter={true} columns={columns} table_url={GET_TECHNICAL_DAMAGE_OPERATOR_LIST} - page_name={"operatorDamages"} - table_name={"operatorList"} + page_name={"damagesOperator"} + table_name={"damagesOperatorList"} sorting={[{ id: "id", desc: true }]} TableToolbar={Toolbar} enableRowActions diff --git a/src/components/dashboard/damages/operator/index.jsx b/src/components/dashboard/damages/operator/index.jsx index 4936664..8bbaeb6 100644 --- a/src/components/dashboard/damages/operator/index.jsx +++ b/src/components/dashboard/damages/operator/index.jsx @@ -6,7 +6,7 @@ import OperatorList from "./OperatorList"; const OperatorPage = () => { return ( - + ); diff --git a/src/components/dashboard/damages/report/ReportLists.jsx b/src/components/dashboard/damages/report/ReportLists.jsx index c43c9bb..c961bf2 100644 --- a/src/components/dashboard/damages/report/ReportLists.jsx +++ b/src/components/dashboard/damages/report/ReportLists.jsx @@ -230,8 +230,9 @@ const ReportLists = ({ data, specialFilter }) => { TableToolbar={Toolbar} columns={columns} data={data.data} - page_name={"receiptReport"} - table_name={"receiptReportList"} + page_name={"damagesReport"} + table_name={"damagesReportList"} + enablePagination={false} specialFilter={specialFilter} /> diff --git a/src/components/dashboard/damages/report/index.jsx b/src/components/dashboard/damages/report/index.jsx index 6e2092d..e2fa70e 100644 --- a/src/components/dashboard/damages/report/index.jsx +++ b/src/components/dashboard/damages/report/index.jsx @@ -123,7 +123,7 @@ const DamagesReportPage = () => { return ( - + { props.dependencyFieldValue?.value === "" ? "empty" : loadingEdaratList - ? "loading" - : props.filterParameters.value + ? "loading" + : props.filterParameters.value } columnSelectOption={getColumnSelectOptions} /> @@ -196,7 +196,7 @@ const ComplaintListTable = ({ open, setOpen, mutate }) => { ); } - return بدون توضیحات; + return -; }, }, { @@ -237,7 +237,10 @@ const ComplaintListTable = ({ open, setOpen, mutate }) => { size: 100, }, { - accessorFn: (row) => moment(row.StartTime_DateTime, "M/D/YYYY h:mm:ss A").locale("fa").format("HH:mm | yyyy/MM/DD"), + accessorFn: (row) => + moment(row.StartTime_DateTime, "M/D/YYYY h:mm:ss A") + .locale("fa") + .format("HH:mm | yyyy/MM/DD"), header: "تاریخ ثبت", id: "StartTime_DateTime", enableColumnFilter: false, @@ -246,8 +249,8 @@ const ComplaintListTable = ({ open, setOpen, mutate }) => { grow: false, size: 100, }, - ] - } + ], + }, ]; }, []); @@ -261,12 +264,12 @@ const ComplaintListTable = ({ open, setOpen, mutate }) => { columns={columns} sorting={[{ id: "fk_RegisteredEventMessage", desc: true }]} table_url={GET_FAST_REACT_COMPLAINTS} - page_name={"complaintFastReact"} - table_name={"complaintList"} + page_name={"fastReactComplaint"} + table_name={"fastReactComplaintList"} TableToolbar={Toolbar} enableRowActions positionActionsColumn={"last"} - RowActions={RowActions} + RowActions={(props) => } /> )} diff --git a/src/components/dashboard/fastReact/complaintList/Form/registerAction/index.jsx b/src/components/dashboard/fastReact/complaintList/Form/registerAction/index.jsx index 7362f4b..168acb3 100644 --- a/src/components/dashboard/fastReact/complaintList/Form/registerAction/index.jsx +++ b/src/components/dashboard/fastReact/complaintList/Form/registerAction/index.jsx @@ -4,7 +4,7 @@ import RegisterActionContent from "./RegisterActionContent"; import AppRegistrationIcon from "@mui/icons-material/AppRegistration"; import useRequest from "@/lib/hooks/useRequest"; import { REGISTER_COMPLAINTS_LIST } from "@/core/utils/routes"; -const RegisterAction = ({ rowId, mutate }) => { +const RegisterAction = ({ rowId, mutate, mutateParentTable }) => { const requestServer = useRequest({ notificationSuccess: true }); const [openRegisterActionDialog, setOpenRegisterActionDialog] = useState(false); const defaultValues = { @@ -15,7 +15,6 @@ const RegisterAction = ({ rowId, mutate }) => { image_after_1: null, }; const onBaseSubmit = async (result) => { - console.log(result); const formData = new FormData(); const rmsLatLng = `${result.start_point.lat},${result.start_point.lng}`; if (result.rms_status === "1") { @@ -33,6 +32,7 @@ const RegisterAction = ({ rowId, mutate }) => { }) .then((res) => { mutate(); + mutateParentTable(); setOpenRegisterActionDialog(false); }) .catch(() => {}); diff --git a/src/components/dashboard/fastReact/complaintList/RowActions/ReferList/ReferListContent.jsx b/src/components/dashboard/fastReact/complaintList/RowActions/ReferList/ReferListContent.jsx index 31a1e4c..aa8ba3d 100644 --- a/src/components/dashboard/fastReact/complaintList/RowActions/ReferList/ReferListContent.jsx +++ b/src/components/dashboard/fastReact/complaintList/RowActions/ReferList/ReferListContent.jsx @@ -46,21 +46,22 @@ const ReferListContent = ({ rowId }) => { کاربر از اداره - از اداره + به اداره تاریخ توضیحات {data.map((refer, index) => { + const formatLocation = (province, edareh) => + province ? `${province} | ${edareh}` : edareh; return ( - + {refer.user} - {`${refer.from_province} | ${refer.from_edareh}`} - {`${refer.to_province} | ${refer.to_edareh}`} + + {formatLocation(refer.from_province, refer.from_edareh)} + + {formatLocation(refer.to_province, refer.to_edareh)} {moment(refer.created_at).locale("fa").format("HH:mm | yyyy/MM/DD")} diff --git a/src/components/dashboard/fastReact/complaintList/RowActions/index.jsx b/src/components/dashboard/fastReact/complaintList/RowActions/index.jsx index e9972aa..081a536 100644 --- a/src/components/dashboard/fastReact/complaintList/RowActions/index.jsx +++ b/src/components/dashboard/fastReact/complaintList/RowActions/index.jsx @@ -4,13 +4,17 @@ import ReferList from "./ReferList"; import Refer from "./Refer"; import { usePermissions } from "@/lib/hooks/usePermissions"; -const RowActions = ({ row, mutate }) => { +const RowActions = ({ row, mutate, mutateParentTable }) => { const { data: userPermissions } = usePermissions(); - const hasActionPermission = userPermissions.includes("show-fast-react-edarate-shahri") + const hasActionPermission = userPermissions.includes("show-fast-react-edarate-shahri"); return ( {hasActionPermission && ( - + )} diff --git a/src/components/dashboard/fastReact/complaintList/index.jsx b/src/components/dashboard/fastReact/complaintList/index.jsx index 5c3edc6..cf2fb55 100644 --- a/src/components/dashboard/fastReact/complaintList/index.jsx +++ b/src/components/dashboard/fastReact/complaintList/index.jsx @@ -1,10 +1,13 @@ -import { Button, IconButton, useMediaQuery } from "@mui/material"; +import { Badge, Button, IconButton, useMediaQuery } from "@mui/material"; import ChecklistIcon from "@mui/icons-material/Checklist"; import { useTheme } from "@emotion/react"; import { useState } from "react"; import ComplaintListTable from "./ComplaintListTable"; +import { useSidebarBadge } from "@/lib/hooks/useSidebarBadge"; +import { getValueByPath } from "@/core/utils/getValueByPath"; const ComplaintList = ({ mutate }) => { + const { data } = useSidebarBadge(); const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down("sm")); const [open, setOpen] = useState(false); @@ -19,15 +22,21 @@ const ComplaintList = ({ mutate }) => { ) : ( - + + )} diff --git a/src/components/dashboard/fastReact/operator/Form/EditForm/EditController.jsx b/src/components/dashboard/fastReact/operator/Form/EditForm/EditController.jsx index 5025d54..6a46985 100644 --- a/src/components/dashboard/fastReact/operator/Form/EditForm/EditController.jsx +++ b/src/components/dashboard/fastReact/operator/Form/EditForm/EditController.jsx @@ -31,7 +31,6 @@ const EditController = ({ rowId, mutate, setOpenEditDialog }) => { image_after_1: fastReactItemDetails?.image_after || null, }; const HandleSubmit = async (result) => { - console.log("result", result); const formData = new FormData(); const rmsLatLng = `${result.start_point.lat},${result.start_point.lng}`; if (result.rms_status === "1") { diff --git a/src/components/dashboard/fastReact/operator/OperatorList.jsx b/src/components/dashboard/fastReact/operator/OperatorList.jsx index 3ff010b..925d89e 100644 --- a/src/components/dashboard/fastReact/operator/OperatorList.jsx +++ b/src/components/dashboard/fastReact/operator/OperatorList.jsx @@ -10,6 +10,7 @@ import DescriptionForm from "./RowActions/DescriptionDialog"; import ImageDialog from "./RowActions/ImageDialog"; import LocationForm from "./RowActions/LocationDialog"; import Toolbar from "./Toolbar"; +import BlinkingCell from "@/core/components/BlinkingCell"; const OperatorList = () => { const statusOptions = [ @@ -32,6 +33,7 @@ const OperatorList = () => { columnFilterModeOptions: ["equals", "contains"], grow: false, size: 100, + Cell: ({ row }) => , }, { header: "اطلاعات ثبت‌ شده در سامانه سوانح", @@ -105,7 +107,7 @@ const OperatorList = () => { ); } - return بدون توضیحات; + return -; }, }, { @@ -126,44 +128,10 @@ const OperatorList = () => { }, }, Cell: ({ row }) => { - if (!row.original.rms_start_latlng) return <>بدون موقعیت; + if (!row.original.lat) return <>-; return ( - - - ); - }, - }, - { - header: "تصاویر", - id: "images", - enableColumnFilter: false, - enableSorting: false, - datatype: "array", - grow: false, - size: 100, - muiTableBodyCellProps: { - sx: { - borderLeft: "1px solid #e1e1e1", - py: 0, - "&:first-of-type": { - borderLeft: "unset", - }, - }, - }, - Cell: ({ row }) => { - if (!row.original?.image_before && !row.original?.image_after) return <>بدون تصویر; - return ( - - {row.original?.image_before && row.original?.image_after && ( - - )} + ); }, @@ -181,7 +149,10 @@ const OperatorList = () => { size: 100, }, { - accessorFn: (row) => moment(row.StartTime_DateTime, "M/D/YYYY h:mm:ss A").locale("fa").format("HH:mm | yyyy/MM/DD"), + accessorFn: (row) => + moment(row.StartTime_DateTime, "M/D/YYYY h:mm:ss A") + .locale("fa") + .format("HH:mm | yyyy/MM/DD"), header: "تاریخ ثبت", id: "StartTime_DateTime", enableColumnFilter: false, @@ -190,60 +161,157 @@ const OperatorList = () => { grow: false, size: 100, }, - ] + ], }, { - accessorFn: (row) => { - return row.rms_last_activity - ? moment(row?.rms_last_activity).locale("fa").format("HH:mm | yyyy/MM/DD") - : "بدون تاریخ"; - }, - header: "تاریخ اقدام", - id: "rms_last_activity", - enableColumnFilter: true, - datatype: "date", - filterMode: "between", - grow: false, - size: 100, - }, - { - accessorKey: "rms_description", - header: "توضیح مامور", - id: "rms_description", + header: "اطلاعات اقدام", + id: "rms_register", enableColumnFilter: false, - datatype: "text", - filterMode: "equals", - sortDescFirst: false, - columnFilterModeOptions: ["equals", "contains"], + enableSorting: false, grow: false, - size: 100, - muiTableBodyCellProps: { - sx: { - borderLeft: "1px solid #e1e1e1", - py: 0, - "&:first-of-type": { - borderLeft: "unset", + size: 50, + columns: [ + { + accessorFn: (row) => (row.rms_status == 1 ? "اقدام انجام شد" : "اقدام انجام نشد"), + header: "وضعیت اقدام", + id: "rms_register_status", + enableColumnFilter: false, + enableSorting: false, + grow: false, + size: 50, + }, + { + accessorKey: "rms_description", + header: "توضیح مامور", + id: "rms_description", + enableColumnFilter: false, + datatype: "text", + filterMode: "equals", + sortDescFirst: 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 -; }, }, + { + header: "تصاویر", + id: "rms_images", + enableColumnFilter: false, + enableSorting: false, + datatype: "array", + grow: false, + size: 100, + muiTableBodyCellProps: { + sx: { + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ row }) => { + if (!row.original?.image_before && !row.original?.image_after) return <>-; + return ( + + {row.original?.image_before && row.original?.image_after && ( + + )} + + ); + }, + }, + { + header: "موقعیت", + id: "rms_location", + enableColumnFilter: false, + enableSorting: false, + datatype: "array", + grow: false, + size: 100, + muiTableBodyCellProps: { + sx: { + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ row }) => { + if (!row.original.rms_start_latlng) return <>-; + return ( + + + + ); + }, + }, + { + accessorFn: (row) => { + return row.rms_last_activity + ? moment(row?.rms_last_activity).locale("fa").format("HH:mm | yyyy/MM/DD") + : "-"; + }, + header: "تاریخ اقدام", + id: "rms_last_activity", + enableColumnFilter: true, + datatype: "date", + filterMode: "between", + grow: false, + size: 100, + }, + ], + }, + { + accessorKey: "status", + header: "وضعیت نظارت", + id: "status", + enableColumnFilter: true, + datatype: "numeric", + filterMode: "equals", + sortDescFirst: true, + grow: false, + size: 100, + columnSelectOption: () => { + return statusOptions.map((status) => ({ + value: status.value, + label: status.label, + })); }, - Cell: ({ renderedCellValue }) => { - if (renderedCellValue) { - return ( - - - - ); - } - return بدون توضیحات; - }, + Cell: ({ row }) => <>{row.original.status_fa}, }, { accessorKey: "supervisor_description", - header: "توضیح کارشناس", + header: "توضیح ناظر", id: "supervisor_description", enableColumnFilter: false, datatype: "text", @@ -267,33 +335,15 @@ const OperatorList = () => { ); } - return بدون توضیحات; + return -; }, }, - { - accessorKey: "status", - header: "وضعیت", - id: "status", - enableColumnFilter: true, - datatype: "numeric", - filterMode: "equals", - sortDescFirst: true, - grow: false, - size: 100, - columnSelectOption: () => { - return statusOptions.map((status) => ({ - value: status.value, - label: status.label, - })); - }, - Cell: ({ row }) => <>{row.original.status_fa}, - }, ], [] ); @@ -306,11 +356,11 @@ const OperatorList = () => { columns={columns} sorting={[ { id: "status", desc: true }, - { id: "id", desc: true }, + { id: "road_observeds__id", desc: true }, ]} table_url={GET_FAST_REACT_OPERATOR} - page_name={"operatorFastReact"} - table_name={"OperatorList"} + page_name={"fastReactOperator"} + table_name={"fastReactOperatorList"} TableToolbar={Toolbar} enableRowActions positionActionsColumn={"last"} diff --git a/src/components/dashboard/fastReact/operator/Toolbar.jsx b/src/components/dashboard/fastReact/operator/Toolbar.jsx index 479ae4e..7db297e 100644 --- a/src/components/dashboard/fastReact/operator/Toolbar.jsx +++ b/src/components/dashboard/fastReact/operator/Toolbar.jsx @@ -4,7 +4,7 @@ import { Stack } from "@mui/material"; const Toolbar = ({ table, filterData, mutate }) => { return ( - + diff --git a/src/components/dashboard/fastReact/operator/index.jsx b/src/components/dashboard/fastReact/operator/index.jsx index a2b328c..e95336c 100644 --- a/src/components/dashboard/fastReact/operator/index.jsx +++ b/src/components/dashboard/fastReact/operator/index.jsx @@ -6,7 +6,7 @@ import OperatorList from "./OperatorList"; const OperatorPage = () => { return ( - + ); diff --git a/src/components/dashboard/fastReact/supervisor/RowActions/index.jsx b/src/components/dashboard/fastReact/supervisor/RowActions/index.jsx index f9947ab..37d03f4 100644 --- a/src/components/dashboard/fastReact/supervisor/RowActions/index.jsx +++ b/src/components/dashboard/fastReact/supervisor/RowActions/index.jsx @@ -18,7 +18,9 @@ const RowActions = ({ row, mutate }) => { {hasSupervisePermission && row.original?.status === 0 && ( )} - {hasRestorePermission && row.original?.status !== 0 && } + {hasRestorePermission && row.original?.status !== 0 && ( + + )} ); }; diff --git a/src/components/dashboard/fastReact/supervisor/SupervisorList.jsx b/src/components/dashboard/fastReact/supervisor/SupervisorList.jsx index 89eb53c..b10eade 100644 --- a/src/components/dashboard/fastReact/supervisor/SupervisorList.jsx +++ b/src/components/dashboard/fastReact/supervisor/SupervisorList.jsx @@ -15,6 +15,7 @@ import LocationForm from "./RowActions/LocationDialog"; import EngineeringIcon from "@mui/icons-material/Engineering"; import ThreePIcon from "@mui/icons-material/ThreeP"; import ImageDialog from "./RowActions/ImageDialog"; +import BlinkingCell from "@/core/components/BlinkingCell"; const SupervisorList = () => { const { data: userPermissions } = usePermissions(); @@ -75,6 +76,7 @@ const SupervisorList = () => { columnFilterModeOptions: ["equals", "contains"], grow: false, size: 100, + Cell: ({ row }) => , }, ...(hasCountryPermission ? [dynamicColumns] : []), { @@ -125,8 +127,8 @@ const SupervisorList = () => { props.dependencyFieldValue?.value === "" ? "empty" : loadingEdaratList - ? "loading" - : props.filterParameters.value + ? "loading" + : props.filterParameters.value } columnSelectOption={getColumnSelectOptions} /> @@ -206,7 +208,7 @@ const SupervisorList = () => { ); } - return بدون توضیحات; + return -; }, }, { @@ -227,44 +229,10 @@ const SupervisorList = () => { }, }, Cell: ({ row }) => { - if (!row.original.rms_start_latlng) return <>بدون موقعیت; + if (!row.original.lat) return <>-; return ( - - - ); - }, - }, - { - header: "تصاویر", - id: "images", - enableColumnFilter: false, - enableSorting: false, - datatype: "array", - grow: false, - size: 100, - muiTableBodyCellProps: { - sx: { - borderLeft: "1px solid #e1e1e1", - py: 0, - "&:first-of-type": { - borderLeft: "unset", - }, - }, - }, - Cell: ({ row }) => { - if (!row.original?.image_before && !row.original?.image_after) return <>بدون تصویر; - return ( - - {row.original?.image_before && row.original?.image_after && ( - - )} + ); }, @@ -282,7 +250,10 @@ const SupervisorList = () => { size: 100, }, { - accessorFn: (row) => moment(row.StartTime_DateTime, "M/D/YYYY h:mm:ss A").locale("fa").format("HH:mm | yyyy/MM/DD"), + accessorFn: (row) => + moment(row.StartTime_DateTime, "M/D/YYYY h:mm:ss A") + .locale("fa") + .format("HH:mm | yyyy/MM/DD"), header: "تاریخ ثبت", id: "StartTime_DateTime", enableColumnFilter: false, @@ -291,60 +262,157 @@ const SupervisorList = () => { grow: false, size: 100, }, - ] + ], }, { - accessorFn: (row) => { - return row.rms_last_activity - ? moment(row?.rms_last_activity).locale("fa").format("HH:mm | yyyy/MM/DD") - : "بدون تاریخ"; - }, - header: "تاریخ اقدام", - id: "rms_last_activity", - enableColumnFilter: true, - datatype: "date", - filterMode: "between", - grow: false, - size: 100, - }, - { - accessorKey: "rms_description", - header: "توضیح مامور", - id: "rms_description", + header: "اطلاعات اقدام", + id: "rms_register", enableColumnFilter: false, - datatype: "text", - filterMode: "equals", - sortDescFirst: false, - columnFilterModeOptions: ["equals", "contains"], + enableSorting: false, grow: false, - size: 100, - muiTableBodyCellProps: { - sx: { - borderLeft: "1px solid #e1e1e1", - py: 0, - "&:first-of-type": { - borderLeft: "unset", + size: 50, + columns: [ + { + accessorFn: (row) => (row.rms_status == 1 ? "اقدام انجام شد" : "اقدام انجام نشد"), + header: "وضعیت اقدام", + id: "rms_register_status", + enableColumnFilter: false, + enableSorting: false, + grow: false, + size: 50, + }, + { + accessorKey: "rms_description", + header: "توضیح مامور", + id: "rms_description", + enableColumnFilter: false, + datatype: "text", + filterMode: "equals", + sortDescFirst: 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 -; }, }, + { + header: "تصاویر", + id: "rms_images", + enableColumnFilter: false, + enableSorting: false, + datatype: "array", + grow: false, + size: 100, + muiTableBodyCellProps: { + sx: { + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ row }) => { + if (!row.original?.image_before && !row.original?.image_after) return <>-; + return ( + + {row.original?.image_before && row.original?.image_after && ( + + )} + + ); + }, + }, + { + header: "موقعیت", + id: "rms_location", + enableColumnFilter: false, + enableSorting: false, + datatype: "array", + grow: false, + size: 100, + muiTableBodyCellProps: { + sx: { + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ row }) => { + if (!row.original.rms_start_latlng) return <>-; + return ( + + + + ); + }, + }, + { + accessorFn: (row) => { + return row.rms_last_activity + ? moment(row?.rms_last_activity).locale("fa").format("HH:mm | yyyy/MM/DD") + : "-"; + }, + header: "تاریخ اقدام", + id: "rms_last_activity", + enableColumnFilter: true, + datatype: "date", + filterMode: "between", + grow: false, + size: 100, + }, + ], + }, + { + accessorKey: "status", + header: "وضعیت نظارت", + id: "status", + enableColumnFilter: true, + datatype: "numeric", + filterMode: "equals", + sortDescFirst: true, + grow: false, + size: 100, + columnSelectOption: () => { + return statusOptions.map((status) => ({ + value: status.value, + label: status.label, + })); }, - Cell: ({ renderedCellValue }) => { - if (renderedCellValue) { - return ( - - - - ); - } - return بدون توضیحات; - }, + Cell: ({ row }) => <>{row.original.status_fa}, }, { accessorKey: "supervisor_description", - header: "توضیح کارشناس", + header: "توضیح ناظر", id: "supervisor_description", enableColumnFilter: false, datatype: "text", @@ -374,27 +442,9 @@ const SupervisorList = () => { ); } - return بدون توضیحات; + return -; }, }, - { - accessorKey: "status", - header: "وضعیت", - id: "status", - enableColumnFilter: true, - datatype: "numeric", - filterMode: "equals", - sortDescFirst: true, - grow: false, - size: 100, - columnSelectOption: () => { - return statusOptions.map((status) => ({ - value: status.value, - label: status.label, - })); - }, - Cell: ({ row }) => <>{row.original.status_fa}, - }, ]; }, []); @@ -406,11 +456,11 @@ const SupervisorList = () => { columns={columns} sorting={[ { id: "status", desc: false }, - { id: "id", desc: true }, + { id: "road_observeds__id", desc: true }, ]} table_url={GET_FAST_REACT_SUPERVISOR} - page_name={"supervisorFastReact"} - table_name={"supervisorList"} + page_name={"fastReactSupervisor"} + table_name={"fastReactSupervisorList"} TableToolbar={Toolbar} enableRowActions positionActionsColumn={"last"} diff --git a/src/components/dashboard/fastReact/supervisor/Toolbar.jsx b/src/components/dashboard/fastReact/supervisor/Toolbar.jsx index 479ae4e..7db297e 100644 --- a/src/components/dashboard/fastReact/supervisor/Toolbar.jsx +++ b/src/components/dashboard/fastReact/supervisor/Toolbar.jsx @@ -4,7 +4,7 @@ import { Stack } from "@mui/material"; const Toolbar = ({ table, filterData, mutate }) => { return ( - + diff --git a/src/components/dashboard/fastReact/supervisor/index.jsx b/src/components/dashboard/fastReact/supervisor/index.jsx index 3fa490b..03adf90 100644 --- a/src/components/dashboard/fastReact/supervisor/index.jsx +++ b/src/components/dashboard/fastReact/supervisor/index.jsx @@ -6,7 +6,7 @@ import SupervisorList from "./SupervisorList"; const SupervisorPage = () => { return ( - + ); diff --git a/src/components/dashboard/permissionTable/Actions/Create/Form/CreateFormContent.jsx b/src/components/dashboard/permissionTable/Actions/Create/Form/CreateFormContent.jsx new file mode 100644 index 0000000..6cb55e8 --- /dev/null +++ b/src/components/dashboard/permissionTable/Actions/Create/Form/CreateFormContent.jsx @@ -0,0 +1,218 @@ +import StyledForm from "@/core/components/StyledForm"; +import { yupResolver } from "@hookform/resolvers/yup"; +import { Beenhere, ExitToApp } from "@mui/icons-material"; +import { + Button, + DialogActions, + DialogContent, + Grid, + Stack, + TextField, + FormControlLabel, + Checkbox, +} from "@mui/material"; +import { Controller, useForm } from "react-hook-form"; +import { object, string } from "yup"; +import PersianTextField from "@/core/components/PersianTextField"; + +const validationSchema = object({ + name: string().required("وارد کردن نام انگلیسی الزامیست!"), + name_fa: string().required("وارد کردن نام فارسی الزامیست!"), + type: string().required("وارد کردن گروه (انگلیسی) الزامیست!"), + type_fa: string().required("وارد کردن گروه (فارسی) الزامیست!"), +}); + +const CreateFormContent = ({ setOpen, defaultValues, onSubmitBase }) => { + const { + control, + handleSubmit, + formState: { isSubmitting, errors }, + } = useForm({ + defaultValues, + resolver: yupResolver(validationSchema), + mode: "onBlur", + }); + const handleOnSubmit = async (data) => { + await onSubmitBase(data); + }; + + return ( + <> + + + + + + + ( + + )} + /> + + + ( + + )} + /> + + + + + + + ( + + )} + /> + + + ( + + )} + /> + + + + + + + ( + + )} + /> + + + + + + + ( + + } + label="دسترسی استانی" + /> + )} + /> + + + ( + + } + label="دسترسی اداره شهری" + /> + )} + /> + + + + + + + + + + + + ); +}; +export default CreateFormContent; diff --git a/src/components/dashboard/permissionTable/Actions/Create/Form/index.jsx b/src/components/dashboard/permissionTable/Actions/Create/Form/index.jsx new file mode 100644 index 0000000..2c01835 --- /dev/null +++ b/src/components/dashboard/permissionTable/Actions/Create/Form/index.jsx @@ -0,0 +1,66 @@ +import { Dialog, DialogTitle, IconButton } from "@mui/material"; +import CreateFormContent from "./CreateFormContent"; +import CloseIcon from "@mui/icons-material/Close"; +import useRequest from "@/lib/hooks/useRequest"; +import { CREATE_PERMISSION } from "@/core/utils/routes"; +import { DialogHeader } from "next/dist/client/components/react-dev-overlay/internal/components/Dialog"; + +const CreateForm = ({ open, setOpen, mutate }) => { + const requestServer = useRequest({ notificationSuccess: true }); + const defaultValues = { + name: "", + name_fa: "", + description: "", + type: "", + type_fa: "", + need_province: false, + need_edare_shahri: false, + }; + const onSubmit = async (result) => { + const formData = new FormData(); + formData.append("name", result.name); + formData.append("name_fa", result.name_fa); + formData.append("description", result.description); + formData.append("type", result.type); + formData.append("type_fa", result.type_fa); + formData.append("need_province", result.need_province ? 1 : 0); + formData.append("need_edare_shahri", result.need_edare_shahri ? 1 : 0); + await requestServer(CREATE_PERMISSION, "post", { + data: formData, + }) + .then(() => { + mutate(); + setOpen(false); + }) + .catch(() => {}); + }; + return ( + + setOpen(false)} + sx={(theme) => ({ + position: "absolute", + right: 8, + top: 8, + zIndex: 50, + color: theme.palette.grey[500], + })} + > + + + + ثبت سطح دسترسی جدید + + {open && ( + + )} + + ); +}; +export default CreateForm; diff --git a/src/components/dashboard/permissionTable/Actions/Create/index.jsx b/src/components/dashboard/permissionTable/Actions/Create/index.jsx new file mode 100644 index 0000000..c558a8b --- /dev/null +++ b/src/components/dashboard/permissionTable/Actions/Create/index.jsx @@ -0,0 +1,36 @@ +import { AddCircle } from "@mui/icons-material"; +import { Button, IconButton, useMediaQuery, useTheme } from "@mui/material"; +import CreateForm from "./Form"; +import { useState } from "react"; + +const CreatePermission = ({ mutate }) => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down("sm")); + const [open, setOpen] = useState(false); + + const handleOpen = () => { + setOpen(true); + }; + + return ( + <> + {isMobile ? ( + + + + ) : ( + + )} + + + ); +}; +export default CreatePermission; diff --git a/src/components/dashboard/permissionTable/Actions/Edit/EditController.jsx b/src/components/dashboard/permissionTable/Actions/Edit/EditController.jsx new file mode 100644 index 0000000..d2baab2 --- /dev/null +++ b/src/components/dashboard/permissionTable/Actions/Edit/EditController.jsx @@ -0,0 +1,46 @@ +import useRequest from "@/lib/hooks/useRequest"; +import CreateFormContent from "../Create/Form/CreateFormContent"; +import { UPDATE_PERMISSION } from "@/core/utils/routes"; +import { DialogTitle } from "@mui/material"; +import { DialogHeader } from "next/dist/client/components/react-dev-overlay/internal/components/Dialog"; + +const EditController = ({ rowId, mutate, setOpen, row }) => { + const requestServer = useRequest({ notificationSuccess: true }); + + const defaultData = { + name: row.original?.name || "", + name_fa: row.original?.name_fa || "", + description: row.original?.description || "", + type: row.original?.type || "", + type_fa: row.original?.type_fa || "", + need_province: row.original?.need_province || false, + need_edare_shahri: row.original?.need_edare_shahri || false, + }; + const handleSubmit = async (result) => { + const formData = new FormData(); + formData.append("name", result.name); + formData.append("name_fa", result.name_fa); + formData.append("description", result.description); + formData.append("type", result.type); + formData.append("type_fa", result.type_fa); + formData.append("need_province", result.need_province ? 1 : 0); + formData.append("need_edare_shahri", result.need_edare_shahri ? 1 : 0); + await requestServer(`${UPDATE_PERMISSION}/${rowId}`, "post", { + data: formData, + }) + .then(() => { + mutate(); + setOpen(false); + }) + .catch(() => {}); + }; + return ( + <> + + ویرایش سطح دسترسی + + + + ); +}; +export default EditController; diff --git a/src/components/dashboard/permissionTable/Actions/Edit/index.jsx b/src/components/dashboard/permissionTable/Actions/Edit/index.jsx new file mode 100644 index 0000000..b7d98a9 --- /dev/null +++ b/src/components/dashboard/permissionTable/Actions/Edit/index.jsx @@ -0,0 +1,51 @@ +import { useState } from "react"; +import { Dialog, IconButton, Tooltip } from "@mui/material"; +import BorderColorIcon from "@mui/icons-material/BorderColor"; +import CloseIcon from "@mui/icons-material/Close"; +import EditController from "./EditController"; + +const EditPermission = ({ mutate, row, rowId }) => { + const [open, setOpen] = useState(false); + + return ( + <> + + { + setOpen(true); + }} + > + + + + + setOpen(false)} + sx={(theme) => ({ + position: "absolute", + right: 8, + top: 8, + zIndex: 50, + color: theme.palette.grey[500], + })} + > + + + {open && } + + + ); +}; +export default EditPermission; diff --git a/src/components/dashboard/permissionTable/PermissionList.jsx b/src/components/dashboard/permissionTable/PermissionList.jsx new file mode 100644 index 0000000..05f53af --- /dev/null +++ b/src/components/dashboard/permissionTable/PermissionList.jsx @@ -0,0 +1,157 @@ +"use client"; +import DataTableWithAuth from "@/core/components/DataTableWithAuth"; +import { GET_PERMISSION_TABLE_LIST } from "@/core/utils/routes"; +import { Box, Stack, Typography } from "@mui/material"; +import { useMemo } from "react"; +import Toolbar from "./Toolbar"; +import RowActions from "./RowActions"; +import moment from "jalali-moment"; +import DoneIcon from "@mui/icons-material/Done"; +import ClearIcon from "@mui/icons-material/Clear"; + +const PermissionList = () => { + const columns = useMemo( + () => [ + { + accessorKey: "id", + header: "کد یکتا", + id: "id", + enableColumnFilter: true, + datatype: "text", + filterMode: "equals", + sortDescFirst: false, + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + }, + { + accessorKey: "type", + header: "گروه (انگلیسی)", + id: "type", + enableColumnFilter: true, + datatype: "text", + filterMode: "equals", + sortDescFirst: false, + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + }, + { + accessorKey: "type_fa", + header: "گروه (فارسی)", + id: "type_fa", + enableColumnFilter: true, + datatype: "text", + filterMode: "equals", + sortDescFirst: false, + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + }, + { + accessorKey: "name", + header: "نام انگلیسی", + id: "name", + enableColumnFilter: true, + datatype: "text", + filterMode: "equals", + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + }, + { + accessorKey: "name_fa", + header: "نام فارسی", + id: "name_fa", + enableColumnFilter: true, + datatype: "text", + filterMode: "equals", + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + }, + { + accessorKey: "need_province", + header: "دسترسی استانی", + id: "need_province", + enableColumnFilter: true, + datatype: "text", + filterMode: "equals", + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + Cell: ({ renderedCellValue }) => ( + <> + {renderedCellValue === 1 ? ( + + + + ) : ( + + + + )} + + ), + }, + { + accessorKey: "need_edare_shahri", + header: "دسترسی اداره شهری", + id: "need_edare_shahri", + enableColumnFilter: true, + datatype: "text", + filterMode: "equals", + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + Cell: ({ renderedCellValue }) => ( + <> + {renderedCellValue === 1 ? ( + + + + ) : ( + + + + )} + + ), + }, + { + accessorFn: (row) => { + const date = row.created_at ? new Date(row.created_at) : null; + return date ? moment(date).locale("fa").format("HH:mm | jYYYY/jMM/jDD") : "-"; + }, + header: "تاریخ ثبت", + id: "created_at", + enableColumnFilter: true, + datatype: "date", + filterMode: "between", + grow: false, + size: 100, + }, + ], + [] + ); + + return ( + <> + + + + + ); +}; +export default PermissionList; diff --git a/src/components/dashboard/permissionTable/RowActions/DeleteDialog/DeleteContent.jsx b/src/components/dashboard/permissionTable/RowActions/DeleteDialog/DeleteContent.jsx new file mode 100644 index 0000000..2bf7bc1 --- /dev/null +++ b/src/components/dashboard/permissionTable/RowActions/DeleteDialog/DeleteContent.jsx @@ -0,0 +1,39 @@ +import { Button, DialogActions, DialogContent, Stack, Typography } from "@mui/material"; +import React, { useState } from "react"; +import useRequest from "@/lib/hooks/useRequest"; +import { DELETE_PERMISSION } from "@/core/utils/routes"; + +const DeleteContent = ({ rowId, mutate, setOpenDeleteDialog }) => { + const [submitting, setSubmitting] = useState(false); + const requestServer = useRequest({ notificationSuccess: true }); + const handleClick = () => { + setSubmitting(true); + requestServer(`${DELETE_PERMISSION}/${rowId}`, "delete") + .then(() => { + mutate(); + setSubmitting(false); + setOpenDeleteDialog(false); + }) + .catch(() => { + setSubmitting(false); + }); + }; + return ( + <> + + + آیا از حذف سطح دسترسی اطمینان دارید؟ + + + + + + + + ); +}; +export default DeleteContent; diff --git a/src/components/dashboard/permissionTable/RowActions/DeleteDialog/index.jsx b/src/components/dashboard/permissionTable/RowActions/DeleteDialog/index.jsx new file mode 100644 index 0000000..2578e2a --- /dev/null +++ b/src/components/dashboard/permissionTable/RowActions/DeleteDialog/index.jsx @@ -0,0 +1,34 @@ +import DeleteIcon from "@mui/icons-material/Delete"; +import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material"; +import { useState } from "react"; +import DeleteContent from "./DeleteContent"; +const DeleteDialog = ({ rowId, mutate }) => { + const [openDeleteDialog, setOpenDeleteDialog] = useState(false); + + return ( + <> + + setOpenDeleteDialog(true)}> + + + + setOpenDeleteDialog(false)} + PaperProps={{ + sx: { + boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px", + }, + }} + dir="rtl" + maxWidth={"md"} + > + حذف سطح دسترسی + {openDeleteDialog && ( + + )} + + + ); +}; +export default DeleteDialog; diff --git a/src/components/dashboard/permissionTable/RowActions/index.jsx b/src/components/dashboard/permissionTable/RowActions/index.jsx new file mode 100644 index 0000000..cb78144 --- /dev/null +++ b/src/components/dashboard/permissionTable/RowActions/index.jsx @@ -0,0 +1,12 @@ +import { Box } from "@mui/material"; +import EditPermission from "../Actions/Edit"; +import DeleteDialog from "./DeleteDialog"; +const RowActions = ({ row, mutate }) => { + return ( + + + + + ); +}; +export default RowActions; diff --git a/src/components/dashboard/permissionTable/Toolbar.jsx b/src/components/dashboard/permissionTable/Toolbar.jsx new file mode 100644 index 0000000..1f6422e --- /dev/null +++ b/src/components/dashboard/permissionTable/Toolbar.jsx @@ -0,0 +1,9 @@ +import CreatePermission from "./Actions/Create"; +const Toolbar = ({ mutate }) => { + return ( + <> + + + ); +}; +export default Toolbar; diff --git a/src/components/dashboard/permissionTable/index.jsx b/src/components/dashboard/permissionTable/index.jsx new file mode 100644 index 0000000..bbbce86 --- /dev/null +++ b/src/components/dashboard/permissionTable/index.jsx @@ -0,0 +1,13 @@ +import PageTitle from "@/core/components/PageTitle"; +import { Stack } from "@mui/material"; +import PermissionList from "./PermissionList"; + +const PermissionTablePage = () => { + return ( + + + + + ); +}; +export default PermissionTablePage; diff --git a/src/components/dashboard/roadItems/operator/Actions/Create/Forms/GetItemsForm.jsx b/src/components/dashboard/roadItems/operator/Actions/Create/Forms/GetItemsForm.jsx index e7daaa8..de689e1 100644 --- a/src/components/dashboard/roadItems/operator/Actions/Create/Forms/GetItemsForm.jsx +++ b/src/components/dashboard/roadItems/operator/Actions/Create/Forms/GetItemsForm.jsx @@ -1,7 +1,7 @@ -import React from "react"; -import { Card, CardActionArea, Grid, LinearProgress, Typography } from "@mui/material"; -import Image from "next/image"; +import DialogLoading from "@/core/components/DialogLoading"; import useRoadItemGetItems from "@/lib/hooks/useRoadItemGetItems"; +import { Card, CardActionArea, Grid, Typography } from "@mui/material"; +import Image from "next/image"; const GetItemsForm = ({ setValue, setItemsList, tabState, setTabState }) => { const { itemsList, loadingItemsList, errorItemsList } = useRoadItemGetItems(); @@ -13,7 +13,7 @@ const GetItemsForm = ({ setValue, setItemsList, tabState, setTabState }) => { خطا در دریافت لیست آیتم ها ) : loadingItemsList ? ( - + ) : ( {itemsList.map((item) => ( diff --git a/src/components/dashboard/roadItems/operator/Actions/Create/Forms/GetSubItemsForm.jsx b/src/components/dashboard/roadItems/operator/Actions/Create/Forms/GetSubItemsForm.jsx index 9b6bc8e..dc84c40 100644 --- a/src/components/dashboard/roadItems/operator/Actions/Create/Forms/GetSubItemsForm.jsx +++ b/src/components/dashboard/roadItems/operator/Actions/Create/Forms/GetSubItemsForm.jsx @@ -1,6 +1,6 @@ -import React from "react"; -import { Card, CardActionArea, Grid, LinearProgress, Typography } from "@mui/material"; +import DialogLoading from "@/core/components/DialogLoading"; import useRoadItemGetSubItems from "@/lib/hooks/useRoadItemGetISubtems"; +import { Card, CardActionArea, Grid, Typography } from "@mui/material"; const GetSubItemsForm = ({ setValue, watch, setSubItemsList, tabState, setTabState }) => { const { subItemsList, loadingSubItemsList, errorSubItemsList } = useRoadItemGetSubItems(watch("item_id")); @@ -12,7 +12,7 @@ const GetSubItemsForm = ({ setValue, watch, setSubItemsList, tabState, setTabSta خطا در دریافت اقدام انجام شده ) : loadingSubItemsList ? ( - + ) : ( {subItemsList.map((item) => ( diff --git a/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/SearchItemInfo.jsx b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/SearchItemInfo.jsx index 611e7d8..6c270c9 100644 --- a/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/SearchItemInfo.jsx +++ b/src/components/dashboard/roadItems/operator/Actions/ObservedGashtCreate/SearchItemInfo.jsx @@ -1,6 +1,6 @@ -import { LinearProgress, Typography } from "@mui/material"; +import DialogLoading from "@/core/components/DialogLoading"; import useRoadItemGetItems from "@/lib/hooks/useRoadItemGetItems"; -import React from "react"; +import { Typography } from "@mui/material"; import SearchItems from "./SearchItems"; import TableInfo from "./TableInfo"; @@ -18,7 +18,7 @@ const SearchItemInfo = ({ return ( <> {loadingItemsList ? ( - + ) : errorItemsList ? ( خطا در دریافت اطلاعات!!! diff --git a/src/components/dashboard/roadItems/operator/OperatorList.jsx b/src/components/dashboard/roadItems/operator/OperatorList.jsx index 793b1e6..352fe65 100644 --- a/src/components/dashboard/roadItems/operator/OperatorList.jsx +++ b/src/components/dashboard/roadItems/operator/OperatorList.jsx @@ -1,4 +1,5 @@ "use client"; +import BlinkingCell from "@/core/components/BlinkingCell"; import CustomSelectByDependency from "@/core/components/DataTable/filter/fieldsType/CustomSelectByDependency"; import DataTableWithAuth from "@/core/components/DataTableWithAuth"; import { GET_ROAD_ITEMS_OPERATOR_LIST } from "@/core/utils/routes"; @@ -8,12 +9,12 @@ import { Box, Stack, Typography } from "@mui/material"; import moment from "jalali-moment"; import { useEffect, useMemo, useState } from "react"; import RowActions from "./RowActions"; +import DescriptionForm from "./RowActions/DescriptionForm"; import ImageDialog from "./RowActions/ImageForm"; import LocationForm from "./RowActions/LocationForm"; +import MachinesCodeDialog from "./RowActions/MachinesCodeForm"; import RahdaranDialog from "./RowActions/RahdaranForm"; import Toolbar from "./Toolbar"; -import DescriptionForm from "./RowActions/DescriptionForm"; -import MachinesCodeDialog from "./RowActions/MachinesCodeForm"; const OperatorList = () => { const statusOptions = [ @@ -25,7 +26,6 @@ const OperatorList = () => { const columns = useMemo( () => [ { - accessorKey: "id", header: "کد یکتا", id: "id", enableColumnFilter: true, @@ -34,245 +34,256 @@ const OperatorList = () => { columnFilterModeOptions: ["equals", "contains"], grow: false, size: 100, + Cell: ({ row }) => , }, { - accessorKey: "item", - header: "آیتم فعالیت", - id: "item", - enableColumnFilter: true, - datatype: "numeric", - filterMode: "equals", - grow: false, - size: 100, - ColumnSelectComponent: (props) => { - const { itemsList, loadingItemsList, errorItemsList } = useRoadItemGetItems(); - - const getColumnSelectOptions = useMemo(() => { - if (loadingItemsList) { - return [{ value: "loading", label: "در حال بارگذاری..." }]; - } - if (errorItemsList) { - return [{ value: "error", label: "خطا در بارگذاری" }]; - } - return [ - { value: "", label: "همه آیتم ها" }, - ...itemsList.map((item) => ({ - value: item.id, - label: item.name, - })), - ]; - }, [itemsList, loadingItemsList, errorItemsList]); - - return ( - - ); - }, - Cell: ({ row }) => { - return row.original.item_fa; - }, - }, - { - accessorKey: "sub_item", - header: "اقدام انجام شده", - id: "sub_item", - enableColumnFilter: true, - datatype: "numeric", - filterMode: "equals", - dependencyId: "item", - ColumnSelectComponent: (props) => { - const { subItemsList, loadingSubItemsList, errorSubItemsList } = useRoadItemGetSubItems( - props.dependencyFieldValue.value - ); - const [prevDependency, setPrevDependency] = useState(props.dependencyFieldValue.value); - - const getColumnSelectOptions = useMemo(() => { - if (props.dependencyFieldValue.value === "") { - return [{ value: "empty", label: "ابتدا آیتم فعالیت را انتخاب کنید" }]; - } - if (loadingSubItemsList) { - return [{ value: "loading", label: "در حال بارگذاری..." }]; - } - if (errorSubItemsList) { - return [{ value: "error", label: "خطا در بارگذاری" }]; - } - return [ - { value: "", label: "همه اقدام ها" }, - ...subItemsList.map((item) => ({ - value: item.sub_item, - label: item.name, - })), - ]; - }, [subItemsList, loadingSubItemsList, errorSubItemsList]); - - useEffect(() => { - if (prevDependency === props.dependencyFieldValue.value) return; - props.handleChange({ ...props.filterParameters, value: "" }); - setPrevDependency(props.dependencyFieldValue.value); - }, [props.dependencyFieldValue.value]); - return ( - - ); - }, - Cell: ({ row }) => { - return row.original.sub_item_fa; - }, - }, - { - accessorKey: "value", - header: "مقدار", // Value - id: "value", + header: "اطلاعات فعالیت", + id: "info", enableColumnFilter: false, enableSorting: false, - datatype: "text", - filterMode: "equals", - columnFilterModeOptions: ["equals", "contains"], grow: false, - size: 120, - Cell: ({ renderedCellValue, row }) => { - return ( - - - {(row.original.sub_item_data / 1).toLocaleString()} - - - {`(${row.original.unit_fa})`} - - - ); - }, - }, - { - header: "تصاویر", - id: "images", - enableColumnFilter: false, - enableSorting: false, - datatype: "array", - grow: false, - size: 100, - muiTableBodyCellProps: { - sx: { - borderLeft: "1px solid #e1e1e1", - py: 0, - "&:first-of-type": { - borderLeft: "unset", + size: 50, + columns: [ + { + accessorKey: "item", + header: "آیتم فعالیت", + id: "item", + enableColumnFilter: true, + datatype: "numeric", + filterMode: "equals", + grow: false, + size: 100, + ColumnSelectComponent: (props) => { + const { itemsList, loadingItemsList, errorItemsList } = useRoadItemGetItems(); + + const getColumnSelectOptions = useMemo(() => { + if (loadingItemsList) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorItemsList) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: "همه آیتم ها" }, + ...itemsList.map((item) => ({ + value: item.id, + label: item.name, + })), + ]; + }, [itemsList, loadingItemsList, errorItemsList]); + + return ( + + ); + }, + Cell: ({ row }) => { + return row.original.item_fa; }, }, - }, - Cell: ({ renderedCellValue, row }) => { - return ( - - - - ); - }, - }, - { - header: "موقعیت", // Location - id: "location", - enableColumnFilter: false, - enableSorting: false, - datatype: "array", - grow: false, - size: 100, - muiTableBodyCellProps: { - sx: { - borderLeft: "1px solid #e1e1e1", - py: 0, - "&:first-of-type": { - borderLeft: "unset", + { + accessorKey: "sub_item", + header: "اقدام انجام شده", + id: "sub_item", + enableColumnFilter: true, + datatype: "numeric", + filterMode: "equals", + dependencyId: "item", + ColumnSelectComponent: (props) => { + const { subItemsList, loadingSubItemsList, errorSubItemsList } = useRoadItemGetSubItems( + props.dependencyFieldValue.value + ); + const [prevDependency, setPrevDependency] = useState(props.dependencyFieldValue.value); + + const getColumnSelectOptions = useMemo(() => { + if (props.dependencyFieldValue.value === "") { + return [{ value: "empty", label: "ابتدا آیتم فعالیت را انتخاب کنید" }]; + } + if (loadingSubItemsList) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorSubItemsList) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: "همه اقدام ها" }, + ...subItemsList.map((item) => ({ + value: item.sub_item, + label: item.name, + })), + ]; + }, [subItemsList, loadingSubItemsList, errorSubItemsList]); + + useEffect(() => { + if (prevDependency === props.dependencyFieldValue.value) return; + props.handleChange({ ...props.filterParameters, value: "" }); + setPrevDependency(props.dependencyFieldValue.value); + }, [props.dependencyFieldValue.value]); + return ( + + ); + }, + Cell: ({ row }) => { + return row.original.sub_item_fa; }, }, - }, - Cell: ({ renderedCellValue, row }) => { - return ( - - - - ); - }, - }, - { - header: "خودرو ها", - id: "cmmsMachines__machine_code", - enableColumnFilter: true, - datatype: "text", - filterMode: "contains", - enableSorting: false, - columnFilterModeOptions: ["equals", "contains"], - grow: false, - size: 100, - muiTableBodyCellProps: { - sx: { - borderLeft: "1px solid #e1e1e1", - py: 0, - "&:first-of-type": { - borderLeft: "unset", + { + accessorKey: "value", + header: "مقدار", // Value + id: "value", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + filterMode: "equals", + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 120, + Cell: ({ renderedCellValue, row }) => { + return ( + + + {(row.original.sub_item_data / 1).toLocaleString()} + + + {`(${row.original.unit_fa})`} + + + ); }, }, - }, - Cell: ({ renderedCellValue, row }) => { - return ( - - - - ); - }, - }, - { - header: "راهداران", - id: "rahdaran__code", - enableColumnFilter: true, - enableSorting: false, - datatype: "text", - filterMode: "contains", - columnFilterModeOptions: ["equals", "contains"], - grow: false, - size: 100, - muiTableBodyCellProps: { - sx: { - borderLeft: "1px solid #e1e1e1", - py: 0, - "&:first-of-type": { - borderLeft: "unset", + { + header: "تصاویر", + id: "images", + 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, row }) => { + return ( + + + + ); }, }, - }, - Cell: ({ renderedCellValue, row }) => { - return ( - - - - ); - }, - }, - { - 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: "between", - grow: false, - size: 100, + { + header: "موقعیت", // Location + id: "location", + 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, row }) => { + return ( + + + + ); + }, + }, + { + header: "خودرو ها", + id: "cmmsMachines__machine_code", + enableColumnFilter: true, + datatype: "text", + 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, row }) => { + return ( + + + + ); + }, + }, + { + header: "راهداران", + id: "rahdaran__code", + enableColumnFilter: true, + enableSorting: false, + datatype: "text", + filterMode: "contains", + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + muiTableBodyCellProps: { + sx: { + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ renderedCellValue, row }) => { + return ( + + + + ); + }, + }, + { + 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: "between", + grow: false, + size: 100, + }, + ], }, { accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"), @@ -330,7 +341,7 @@ const OperatorList = () => { ); } - return بدون توضیحات; + return -; }, }, ], @@ -348,8 +359,8 @@ const OperatorList = () => { { id: "id", desc: true }, ]} table_url={GET_ROAD_ITEMS_OPERATOR_LIST} - page_name={"operator"} - table_name={"operatorList"} + page_name={"roadItemsOperator"} + table_name={"roadItemsOperatorList"} TableToolbar={Toolbar} enableRowActions positionActionsColumn={"last"} diff --git a/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormContent.jsx b/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormContent.jsx index c49d50d..43c8823 100644 --- a/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormContent.jsx +++ b/src/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormContent.jsx @@ -1,4 +1,5 @@ import EditFormCreate from "@/components/dashboard/roadItems/operator/RowActions/EditForm/EditFormCreate"; +import DialogLoading from "@/core/components/DialogLoading"; import useRoadItemGetISubtems from "@/lib/hooks/useRoadItemGetISubtems"; import { LinearProgress, Typography } from "@mui/material"; @@ -79,7 +80,7 @@ const EditFormContent = ({ setOpenEditDialog, onSubmit, defaultData, is_gasht }) خطا در دریافت اطلاعات!!! ) : loadingSubItemsList ? ( - + ) : ( - + {subItem.needs_image === 1 ? ( diff --git a/src/components/dashboard/roadItems/operator/Toolbar.jsx b/src/components/dashboard/roadItems/operator/Toolbar.jsx index d8c6fad..37c8646 100644 --- a/src/components/dashboard/roadItems/operator/Toolbar.jsx +++ b/src/components/dashboard/roadItems/operator/Toolbar.jsx @@ -5,7 +5,7 @@ import ObservedGashtCreate from "./Actions/ObservedGashtCreate"; const Toolbar = ({ table, filterData, mutate }) => { return ( - + diff --git a/src/components/dashboard/roadItems/operator/index.jsx b/src/components/dashboard/roadItems/operator/index.jsx index a2b328c..e1ec59d 100644 --- a/src/components/dashboard/roadItems/operator/index.jsx +++ b/src/components/dashboard/roadItems/operator/index.jsx @@ -6,7 +6,7 @@ import OperatorList from "./OperatorList"; const OperatorPage = () => { return ( - + ); diff --git a/src/components/dashboard/roadItems/reports/ItemsReports/index.jsx b/src/components/dashboard/roadItems/reports/ItemsReports/index.jsx index b9eb0da..dfe6585 100644 --- a/src/components/dashboard/roadItems/reports/ItemsReports/index.jsx +++ b/src/components/dashboard/roadItems/reports/ItemsReports/index.jsx @@ -157,7 +157,7 @@ const ReportPage = () => { }); return ( - + { }); return ( - + { const statusOptions = [ @@ -65,8 +66,8 @@ const SupervisorList = () => { }; return [ { - accessorKey: "id", - header: "کد یکتا", // Unique Code + // accessorKey: "id", + header: "کد یکتا", id: "id", enableColumnFilter: true, datatype: "text", @@ -75,6 +76,7 @@ const SupervisorList = () => { columnFilterModeOptions: ["equals", "contains"], grow: false, size: 100, + Cell: ({ row }) => , }, ...(hasCountryPermission ? [dynamicColumns] : []), { @@ -135,240 +137,250 @@ const SupervisorList = () => { Cell: ({ renderedCellValue, row }) => <>{row.original.edarat_name}, }, { - header: "آیتم فعالیت", - id: "item", - enableColumnFilter: true, - datatype: "numeric", - filterMode: "equals", - grow: false, - size: 100, - ColumnSelectComponent: (props) => { - const { itemsList, loadingItemsList, errorItemsList } = useRoadItemGetItems(); - - const getColumnSelectOptions = useMemo(() => { - if (loadingItemsList) { - return [{ value: "loading", label: "در حال بارگذاری..." }]; - } - if (errorItemsList) { - return [{ value: "error", label: "خطا در بارگذاری" }]; - } - return [ - { value: "", label: "همه آیتم ها" }, - ...itemsList.map((item) => ({ - value: item.id, - label: item.name, - })), - ]; - }, [itemsList, loadingItemsList, errorItemsList]); - - return ( - - ); - }, - Cell: ({ row }) => { - return row.original.item_fa; - }, - }, - { - header: "اقدام انجام شده", - id: "sub_item", - enableColumnFilter: true, - datatype: "numeric", - filterMode: "equals", - dependencyId: "item", - ColumnSelectComponent: (props) => { - const { subItemsList, loadingSubItemsList, errorSubItemsList } = useRoadItemGetSubItems( - props.dependencyFieldValue.value - ); - const [prevDependency, setPrevDependency] = useState(props.dependencyFieldValue.value); - - const getColumnSelectOptions = useMemo(() => { - if (props.dependencyFieldValue.value === "") { - return [{ value: "empty", label: "ابتدا آیتم فعالیت را انتخاب کنید" }]; - } - if (loadingSubItemsList) { - return [{ value: "loading", label: "در حال بارگذاری..." }]; - } - if (errorSubItemsList) { - return [{ value: "error", label: "خطا در بارگذاری" }]; - } - return [ - { value: "", label: "همه اقدام ها" }, - ...subItemsList.map((item) => ({ - value: item.sub_item, - label: item.name, - })), - ]; - }, [subItemsList, loadingSubItemsList, errorSubItemsList]); - - useEffect(() => { - if (prevDependency === props.dependencyFieldValue.value) return; - props.handleChange({ ...props.filterParameters, value: "" }); - setPrevDependency(props.dependencyFieldValue.value); - }, [props.dependencyFieldValue.value]); - return ( - - ); - }, - Cell: ({ row }) => { - return row.original.sub_item_fa; - }, - }, - { - header: "مقدار", // Value - id: "value", + header: "اطلاعات فعالیت", + id: "info", enableColumnFilter: false, enableSorting: false, - datatype: "text", - filterMode: "equals", grow: false, - size: 120, - columnFilterModeOptions: ["equals", "contains"], - Cell: ({ renderedCellValue, row }) => { - return ( - - - {(row.original.sub_item_data / 1).toLocaleString()} - - - {`(${row.original.unit_fa})`} - - - ); - }, - }, - { - header: "تصاویر", - id: "images", - enableColumnFilter: false, - enableSorting: false, - datatype: "array", - grow: false, - size: 100, - muiTableBodyCellProps: { - sx: { - borderLeft: "1px solid #e1e1e1", - py: 0, - "&:first-of-type": { - borderLeft: "unset", + size: 50, + columns: [ + { + header: "آیتم فعالیت", + id: "item", + enableColumnFilter: true, + datatype: "numeric", + filterMode: "equals", + grow: false, + size: 100, + ColumnSelectComponent: (props) => { + const { itemsList, loadingItemsList, errorItemsList } = useRoadItemGetItems(); + + const getColumnSelectOptions = useMemo(() => { + if (loadingItemsList) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorItemsList) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: "همه آیتم ها" }, + ...itemsList.map((item) => ({ + value: item.id, + label: item.name, + })), + ]; + }, [itemsList, loadingItemsList, errorItemsList]); + + return ( + + ); + }, + Cell: ({ row }) => { + return row.original.item_fa; }, }, - }, - Cell: ({ renderedCellValue, row }) => { - return ( - - - - ); - }, - }, - { - header: "موقعیت", // Location - id: "location", - enableColumnFilter: false, - enableSorting: false, - datatype: "array", - grow: false, - size: 100, - muiTableBodyCellProps: { - sx: { - borderLeft: "1px solid #e1e1e1", - py: 0, - "&:first-of-type": { - borderLeft: "unset", + { + header: "اقدام انجام شده", + id: "sub_item", + enableColumnFilter: true, + datatype: "numeric", + filterMode: "equals", + dependencyId: "item", + ColumnSelectComponent: (props) => { + const { subItemsList, loadingSubItemsList, errorSubItemsList } = useRoadItemGetSubItems( + props.dependencyFieldValue.value + ); + const [prevDependency, setPrevDependency] = useState(props.dependencyFieldValue.value); + + const getColumnSelectOptions = useMemo(() => { + if (props.dependencyFieldValue.value === "") { + return [{ value: "empty", label: "ابتدا آیتم فعالیت را انتخاب کنید" }]; + } + if (loadingSubItemsList) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorSubItemsList) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: "همه اقدام ها" }, + ...subItemsList.map((item) => ({ + value: item.sub_item, + label: item.name, + })), + ]; + }, [subItemsList, loadingSubItemsList, errorSubItemsList]); + + useEffect(() => { + if (prevDependency === props.dependencyFieldValue.value) return; + props.handleChange({ ...props.filterParameters, value: "" }); + setPrevDependency(props.dependencyFieldValue.value); + }, [props.dependencyFieldValue.value]); + return ( + + ); + }, + Cell: ({ row }) => { + return row.original.sub_item_fa; }, }, - }, - Cell: ({ renderedCellValue, row }) => { - return ( - - - - ); - }, - }, - { - header: "خودرو ها", - id: "cmmsMachines__machine_code", - enableColumnFilter: true, - datatype: "text", - filterMode: "contains", - enableSorting: false, - columnFilterModeOptions: ["equals", "contains"], - grow: false, - size: 100, - muiTableBodyCellProps: { - sx: { - borderLeft: "1px solid #e1e1e1", - py: 0, - "&:first-of-type": { - borderLeft: "unset", + { + header: "مقدار", // Value + id: "value", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + filterMode: "equals", + grow: false, + size: 120, + columnFilterModeOptions: ["equals", "contains"], + Cell: ({ renderedCellValue, row }) => { + return ( + + + {(row.original.sub_item_data / 1).toLocaleString()} + + + {`(${row.original.unit_fa})`} + + + ); }, }, - }, - Cell: ({ renderedCellValue, row }) => { - return ( - - - - ); - }, - }, - { - header: "راهداران", - id: "rahdaran__code", - enableColumnFilter: true, - enableSorting: false, - datatype: "text", - filterMode: "contains", - columnFilterModeOptions: ["equals", "contains"], - grow: false, - size: 100, - muiTableBodyCellProps: { - sx: { - borderLeft: "1px solid #e1e1e1", - py: 0, - "&:first-of-type": { - borderLeft: "unset", + { + header: "تصاویر", + id: "images", + 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, row }) => { + return ( + + + + ); }, }, - }, - Cell: ({ renderedCellValue, row }) => { - return ( - - - - ); - }, - }, - { - 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: "between", - grow: false, - size: 100, + { + header: "موقعیت", // Location + id: "location", + 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, row }) => { + return ( + + + + ); + }, + }, + { + header: "خودرو ها", + id: "cmmsMachines__machine_code", + enableColumnFilter: true, + datatype: "text", + 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, row }) => { + return ( + + + + ); + }, + }, + { + header: "راهداران", + id: "rahdaran__code", + enableColumnFilter: true, + enableSorting: false, + datatype: "text", + filterMode: "contains", + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + muiTableBodyCellProps: { + sx: { + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ renderedCellValue, row }) => { + return ( + + + + ); + }, + }, + { + 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: "between", + grow: false, + size: 100, + }, + ], }, { accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"), @@ -411,8 +423,8 @@ const SupervisorList = () => { { id: "id", desc: true }, ]} table_url={GET_ROAD_ITEMS_SUPERVISOR_LIST} - page_name={"supervisor"} - table_name={"supervisorList"} + page_name={"roadItemsSupervisor"} + table_name={"roadItemsSupervisorList"} TableToolbar={Toolbar} enableRowActions positionActionsColumn={"last"} diff --git a/src/components/dashboard/roadItems/supervisor/index.jsx b/src/components/dashboard/roadItems/supervisor/index.jsx index 3fa490b..784a066 100644 --- a/src/components/dashboard/roadItems/supervisor/index.jsx +++ b/src/components/dashboard/roadItems/supervisor/index.jsx @@ -6,7 +6,7 @@ import SupervisorList from "./SupervisorList"; const SupervisorPage = () => { return ( - + ); diff --git a/src/components/dashboard/roadPatrols/operator/Forms/CreatePatrol/CompeleteRequest.jsx b/src/components/dashboard/roadPatrols/operator/Forms/CreatePatrol/CompeleteRequest.jsx index 0fa5919..ca4f198 100644 --- a/src/components/dashboard/roadPatrols/operator/Forms/CreatePatrol/CompeleteRequest.jsx +++ b/src/components/dashboard/roadPatrols/operator/Forms/CreatePatrol/CompeleteRequest.jsx @@ -88,7 +88,11 @@ const CompeleteRequest = ({ allData, handlePrev, mutate, setOpen }) => { const sendOtp = async (data) => { try { - const response = await requestServer(`${GET_OTP_TOKEN}?phone_number=${data.phoneNumber}`, "get"); + await requestServer(GET_OTP_TOKEN, "post", { + data: { + phone_number: data.phoneNumber, + }, + }); setOtpSended(true); setDelayPerRequest(true); setValueSend("phoneNumber", data.phoneNumber); diff --git a/src/components/dashboard/roadPatrols/operator/Forms/CreatePatrol/PhoneValidation.jsx b/src/components/dashboard/roadPatrols/operator/Forms/CreatePatrol/PhoneValidation.jsx deleted file mode 100644 index 0c9cb30..0000000 --- a/src/components/dashboard/roadPatrols/operator/Forms/CreatePatrol/PhoneValidation.jsx +++ /dev/null @@ -1,118 +0,0 @@ -"use client"; - -import { Box, Button, FormControl, InputLabel, OutlinedInput } from "@mui/material"; -import React, { useEffect, useState } from "react"; -import ForwardToInboxIcon from "@mui/icons-material/ForwardToInbox"; -import useRequest from "@/lib/hooks/useRequest"; -import { GET_OTP_TOKEN, VERIFY_OTP } from "@/core/utils/routes"; -import { formatCounter } from "@/core/utils/formatCounter"; - -const PhoneValidation = ({ tabState, setTabState }) => { - const requestServer = useRequest({ auth: true }); - const [phoneNumber, setPhoneNumber] = useState(""); - const [verificationCode, setVerificationCode] = useState(""); - const [validPhone, setValidPhone] = useState(false); - const [delayPerRequest, setDelayPerRequest] = useState(false); - const [counter, setCounter] = useState(120); - const [otpSended, setOtpSended] = useState(false); - const [readyToVerify, setReadyToVerify] = useState(false); - - const handleNumericInput = (e) => { - e.target.value = e.target.value.replace(/[^0-9]/g, ""); - }; - - useEffect(() => { - if (phoneNumber.length === 11) { - setValidPhone(true); - } else { - setValidPhone(false); - } - if (verificationCode.length === 6 && phoneNumber.length === 11) { - setReadyToVerify(true); - } else { - setReadyToVerify(false); - } - }, [phoneNumber, verificationCode]); - - useEffect(() => { - if (counter === 0) { - setDelayPerRequest(false); - return; - } - if (delayPerRequest && counter > 0) { - const timer = setInterval(() => { - setCounter((prevCounter) => prevCounter - 1); - }, 1000); - - return () => clearInterval(timer); - } - }, [counter, delayPerRequest]); - - const sendOtp = () => { - if (!validPhone) return false; - requestServer(`${GET_OTP_TOKEN}?phone_number=${phoneNumber}`, "get") - .then((response) => {}) - .catch(() => {}); - //////////**** (mohammad) this part should keep in success but for now we go next level ****//////////// - setOtpSended(true); - setDelayPerRequest(true); - }; - - const phoneRegister = () => { - const formData = new FormData(); - formData.append("phone_number", phoneNumber); - formData.append("verification_code", verificationCode); - - setTabState(tabState + 1); - requestServer(VERIFY_OTP, "post", { - data: formData, - }) - .then(() => {}) - .catch(() => {}); - }; - - return ( - - - - شماره تلفن مامور گشت - setPhoneNumber(e.target.value)} - onInput={handleNumericInput} - type="text" - inputProps={{ - maxLength: 11, - }} - /> - - - - - ); -}; - -export default PhoneValidation; diff --git a/src/components/dashboard/roadPatrols/operator/OperatorList.jsx b/src/components/dashboard/roadPatrols/operator/OperatorList.jsx index 52bb4b4..4548072 100644 --- a/src/components/dashboard/roadPatrols/operator/OperatorList.jsx +++ b/src/components/dashboard/roadPatrols/operator/OperatorList.jsx @@ -7,10 +7,9 @@ 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 RahdaranDialog from "./RowActions/RahdaranForm" +import RahdaranDialog from "./RowActions/RahdaranForm"; import MachinePerformanceForm from "./RowActions/MachinePerformanceForm"; - const OperatorList = () => { const columns = useMemo( () => [ @@ -80,7 +79,7 @@ const OperatorList = () => { ); } - return بدون شخص; + return -; }, }, { @@ -148,8 +147,8 @@ const OperatorList = () => { columns={columns} sorting={[{ id: "id", desc: true }]} table_url={GET_ROAD_PATROL_OPERATOR_LIST} - page_name={"operator"} - table_name={"operatorList"} + page_name={"roadPatrolOperator"} + table_name={"roadPatrolOperatorList"} TableToolbar={Toolbar} enableRowActions positionActionsColumn={"last"} diff --git a/src/components/dashboard/roadPatrols/operator/RowActions/MachinePerformanceForm/MachinesCodeFetch.jsx b/src/components/dashboard/roadPatrols/operator/RowActions/MachinePerformanceForm/MachinesCodeFetch.jsx index 0eb47d2..0da7b28 100644 --- a/src/components/dashboard/roadPatrols/operator/RowActions/MachinePerformanceForm/MachinesCodeFetch.jsx +++ b/src/components/dashboard/roadPatrols/operator/RowActions/MachinePerformanceForm/MachinesCodeFetch.jsx @@ -14,7 +14,7 @@ const MachinePerformanceFetch = ({ row }) => { const fetchData = async () => { try { setLoading(true); - const response = await request(`${GET_CMMS_MACHINE_ROAD_PATROL}/${row.getValue('id')}`); + const response = await request(`${GET_CMMS_MACHINE_ROAD_PATROL}/${row.getValue("id")}`); setData(response.data.data); } catch (error) { } finally { @@ -31,19 +31,20 @@ const MachinePerformanceFetch = ({ row }) => { {loading ? ( ) : data && row.original?.stop_points?.length > 0 ? ( - + ) : ( عملکرد خودرویی در سامانه یافت نشد )} - ) -} -export default MachinePerformanceFetch \ No newline at end of file + ); +}; +export default MachinePerformanceFetch; diff --git a/src/components/dashboard/roadPatrols/operator/RowActions/MachinePerformanceForm/index.jsx b/src/components/dashboard/roadPatrols/operator/RowActions/MachinePerformanceForm/index.jsx index c8dcb9e..168936e 100644 --- a/src/components/dashboard/roadPatrols/operator/RowActions/MachinePerformanceForm/index.jsx +++ b/src/components/dashboard/roadPatrols/operator/RowActions/MachinePerformanceForm/index.jsx @@ -25,9 +25,7 @@ const MachinePerformanceForm = ({ row }) => { maxWidth={"md"} > عملکرد خودرو - {openMachinesCodeDialog && ( - - )} + {openMachinesCodeDialog && } + )} + + ); +}; +export default PrintExcel; diff --git a/src/components/dashboard/roadSafety/operator/Form/EditAxisType/EditFormContent.jsx b/src/components/dashboard/roadSafety/operator/Form/EditAxisType/EditFormContent.jsx new file mode 100644 index 0000000..a76342b --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/Form/EditAxisType/EditFormContent.jsx @@ -0,0 +1,102 @@ +import SelectBox from "@/core/components/SelectBox"; +import StyledForm from "@/core/components/StyledForm"; +import { UPDATE_SAFETY_AND_PRIVACY } from "@/core/utils/routes"; +import useRequest from "@/lib/hooks/useRequest"; +import { yupResolver } from "@hookform/resolvers/yup"; +import BeenhereIcon from "@mui/icons-material/Beenhere"; +import ExitToAppIcon from "@mui/icons-material/ExitToApp"; +import { Button, DialogActions, DialogContent, Grid, Stack } from "@mui/material"; +import { Controller, useForm } from "react-hook-form"; +import { object, string } from "yup"; + +const validationSchema = object({ + axis_type_id: string().required("نوع محور را مشخص کنید!"), +}); + +const EditFormContent = ({ setOpen, mutate, row }) => { + const requestServer = useRequest({ notificationSuccess: true }); + const defaultValues = { + axis_type_id: row.original.axis_type_id || "", + }; + + const handleClose = () => { + setOpen(false); + }; + + const { + control, + handleSubmit, + formState: { isSubmitting }, + } = useForm({ + defaultValues, + resolver: yupResolver(validationSchema), + mode: "onBlur", + }); + const onSubmitBase = async (data) => { + const formData = new FormData(); + formData.append("axis_type_id", data.axis_type_id); + await requestServer(`${UPDATE_SAFETY_AND_PRIVACY}/${row.original.id}`, "post", { + data: formData, + }) + .then((response) => { + mutate(); + setOpen(false); + }) + .catch((error) => {}); + }; + + return ( + + + + + + ( + + )} + /> + + + + + + + + + + ); +}; +export default EditFormContent; diff --git a/src/components/dashboard/roadSafety/operator/Form/EditAxisType/OperatorEditForm.jsx b/src/components/dashboard/roadSafety/operator/Form/EditAxisType/OperatorEditForm.jsx new file mode 100644 index 0000000..34e66e3 --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/Form/EditAxisType/OperatorEditForm.jsx @@ -0,0 +1,26 @@ +import { Dialog, DialogTitle, IconButton } from "@mui/material"; +import CloseIcon from "@mui/icons-material/Close"; +import EditFormContent from "./EditFormContent"; + +const OperatorEditForm = ({ open, setOpen, mutate, row }) => { + return ( + + setOpen(false)} + sx={(theme) => ({ + position: "absolute", + right: 8, + top: 8, + zIndex: 50, + color: theme.palette.grey[500], + })} + > + + + ویرایش محور + {open && } + + ); +}; +export default OperatorEditForm; diff --git a/src/components/dashboard/roadSafety/operator/Form/EditAxisType/index.jsx b/src/components/dashboard/roadSafety/operator/Form/EditAxisType/index.jsx new file mode 100644 index 0000000..7e99d16 --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/Form/EditAxisType/index.jsx @@ -0,0 +1,19 @@ +import { Dialog, IconButton, Tooltip } from "@mui/material"; +import { useState } from "react"; +import EditIcon from "@mui/icons-material/Edit"; +import OperatorEditForm from "./OperatorEditForm"; + +const EditAxisType = ({ row, mutate }) => { + const [openEditDialog, setOpenEditDialog] = useState(false); + return ( + <> + + setOpenEditDialog(true)}> + + + + + + ); +}; +export default EditAxisType; diff --git a/src/components/dashboard/roadSafety/operator/Form/StepOne/CreateFormContent.jsx b/src/components/dashboard/roadSafety/operator/Form/StepOne/CreateFormContent.jsx new file mode 100644 index 0000000..6c49683 --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/Form/StepOne/CreateFormContent.jsx @@ -0,0 +1,154 @@ +import React, { useState } from "react"; +import { useForm } from "react-hook-form"; +import { yupResolver } from "@hookform/resolvers/yup"; +import { mixed, number, object, string } from "yup"; +import { Box, Button, DialogActions, DialogContent, Tab, Tabs } from "@mui/material"; +import StyledForm from "@/core/components/StyledForm"; +import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile"; +import FileCopyIcon from "@mui/icons-material/FileCopy"; +import ExitToAppIcon from "@mui/icons-material/ExitToApp"; +import KeyboardDoubleArrowRightIcon from "@mui/icons-material/KeyboardDoubleArrowRight"; +import BeenhereIcon from "@mui/icons-material/Beenhere"; +import useRequest from "@/lib/hooks/useRequest"; +import GetItemInfo from "./GetItemInfo"; +import GetSubItemInfo from "./GetSubItemInfo"; +import { format } from "date-fns"; +import { FIRST_STEP_STORE } from "@/core/utils/routes"; + +function TabPanel(props) { + const { children, value, index } = props; + return ( + + ); +} + +const validationSchema = object({ + recognize_picture: mixed().nullable().required("لطفا عکس فعالیت را بارگذاری کنید!"), + info_id: number().required("نوع آیتم را مشخص کنید!"), + axis_type_id: string().required("نوع محور را مشخص کنید!"), + start_point: mixed() + .test("start-point-required", "لطفاً نقطه شروع را مشخص کنید!", function (value) { + return !!value; // چک می‌کند که مقدار موجود است + }) + .required("لطفاً نقطه فعالیت را مشخص کنید!"), + activity_time: string().required("لطفا زمان فعالیت را انتخاب کنید!"), + activity_date: string().required("لطفا تاریخ فعالیت را انتخاب کنید!"), +}); + +const CreateFormContent = ({ setOpen, mutate }) => { + const requestServer = useRequest({ notificationSuccess: true }); + const [itemsList, setItemsList] = useState(); + const defaultValues = { + info_id: null, + axis_type_id: "", + recognize_picture: null, + activity_date: "", + activity_time: "", + start_point: "", + }; + + const [tabState, setTabState] = useState(0); + const handleClose = () => { + setOpen(false); + }; + const handleChangeTab = (event, newValue) => { + setTabState(newValue); + }; + + const handlePrev = () => { + if (tabState === 2) { + const fieldsToReset = ["recognize_picture", "activity_time", "activity_date", "start_point"]; + fieldsToReset.forEach((field) => resetField(field)); + } + if (tabState === 0) { + handleClose(); + } else { + setTabState(tabState - 1); + } + }; + const { + control, + handleSubmit, + resetField, + setValue, + formState: { errors, isSubmitting }, + } = useForm({ + defaultValues, + resolver: yupResolver(validationSchema), + mode: "onBlur", + }); + const onSubmitBase = async (data) => { + const startPoint = `${data.start_point.lat},${data.start_point.lng}`; + const formData = new FormData(); + formData.append("activity_date", data.activity_date); + formData.append("activity_time", format(new Date(data.activity_time), "HH:mm")); + formData.append("info_id", data.info_id); + formData.append("axis_type_id", data.axis_type_id); + formData.append("recognize_picture", data.recognize_picture); + formData.append("point", startPoint); + await requestServer(FIRST_STEP_STORE, "post", { + data: formData, + }) + .then((response) => { + mutate(); + setOpen(false); + }) + .catch((error) => {}); + }; + + return ( + + + } label="انتخاب مورد" /> + } label="اطلاعات مورد مشاهده شده" /> + + + + + + + + + + + + + + {tabState === 1 && ( + + )} + + + ); +}; +export default CreateFormContent; diff --git a/src/components/dashboard/roadSafety/operator/Form/StepOne/GetItemInfo.jsx b/src/components/dashboard/roadSafety/operator/Form/StepOne/GetItemInfo.jsx new file mode 100644 index 0000000..ad9ef36 --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/Form/StepOne/GetItemInfo.jsx @@ -0,0 +1,62 @@ +import DialogLoading from "@/core/components/DialogLoading"; +import useSafetyAndPrivacyGetItems from "@/lib/hooks/useSafetyAndPrivacyGetItems"; +import { Card, CardActionArea, Grid, Typography } from "@mui/material"; +import { Controller } from "react-hook-form"; + +const GetItemInfo = ({ setItemsList, setTabState, control }) => { + const { itemsList, loadingItemsList, errorItemsList } = useSafetyAndPrivacyGetItems(); + + return ( + <> + {errorItemsList ? ( + + خطا در دریافت لیست آیتم ها + + ) : loadingItemsList ? ( + + ) : ( + + ( + <> + {itemsList.map((item) => ( + + { + field.onChange(item.id); + setItemsList(item); + setTabState(1); + }} + > + + {item.name} + + + + ))} + + )} + /> + + )} + + ); +}; +export default GetItemInfo; diff --git a/src/components/dashboard/roadSafety/operator/Form/StepOne/GetSubItemInfo.jsx b/src/components/dashboard/roadSafety/operator/Form/StepOne/GetSubItemInfo.jsx new file mode 100644 index 0000000..a6e3f5e --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/Form/StepOne/GetSubItemInfo.jsx @@ -0,0 +1,129 @@ +import { Box, Chip, Divider, Grid, Stack, Typography } from "@mui/material"; +import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile"; +import ImageUpload from "./ImageUpload"; +import { Controller, useWatch } from "react-hook-form"; +import MapInfoOneMarker from "@/core/components/MapInfoOneMarker"; +import MuiDatePicker from "@/core/components/MuiDatePicker"; +import MuiTimePicker from "@/core/components/MuiTimePicker"; +import SelectBox from "@/core/components/SelectBox"; + +const GetSubItemInfo = ({ itemsList, control, setValue, errors }) => { + const StartPoint = useWatch({ control, name: "start_point" }); + return ( + + + + + + } + label={ + + مورد انتخاب ‌شده + + } + /> + + + + {itemsList?.name || "هیچ آیتمی انتخاب نشده است"} + + + + + + + + ( + + )} + /> + + + + + + + { + return ( + field.onChange(value || [])} + helperText={error ? error.message : null} + /> + ); + }} + name={"activity_date"} + /> + + + { + return ( + field.onChange(value || null)} + helperText={error ? error.message : null} + /> + ); + }} + name={"activity_time"} + /> + + + ( + + )} + /> + + + + + + + + ); +}; +export default GetSubItemInfo; diff --git a/src/components/dashboard/roadSafety/operator/Form/StepOne/ImageUpload.jsx b/src/components/dashboard/roadSafety/operator/Form/StepOne/ImageUpload.jsx new file mode 100644 index 0000000..5186a4b --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/Form/StepOne/ImageUpload.jsx @@ -0,0 +1,77 @@ +import { FormControl, FormHelperText } from "@mui/material"; +import UploadSystem from "@/core/components/UploadSystem"; +import React, { useEffect, useState } from "react"; + +const ImageUpload = ({ name, value, onChange, error, title }) => { + const [beforeImg, setBeforeImg] = useState(value ? value : null); + const [beforeFileType, setBeforeFileType] = useState(value ? "image/" : null); + const [beforeFileName, setBeforeFileName] = useState(null); + const [showBeforeImage, setShowBeforeImage] = useState(!value); + + useEffect(() => { + if (value) { + setShowBeforeImage(false); + if (typeof value === "string") { + setBeforeImg(value); + setBeforeFileType("image/"); + } else if (value instanceof File) { + setBeforeImg(URL.createObjectURL(value)); + setBeforeFileType(value.type); + } + } + }, [value]); + + const handleFileChange = (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); + onChange(uploadedFile); + setShowBeforeImage(false); + } + }; + + return ( + + + {title} + + + {error ? error.message : null} + + ); +}; +export default ImageUpload; diff --git a/src/components/dashboard/roadSafety/operator/Form/StepOne/OperatorCreateForm.jsx b/src/components/dashboard/roadSafety/operator/Form/StepOne/OperatorCreateForm.jsx new file mode 100644 index 0000000..44b2828 --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/Form/StepOne/OperatorCreateForm.jsx @@ -0,0 +1,26 @@ +"use client"; +import { Dialog, IconButton } from "@mui/material"; +import CreateFormContent from "./CreateFormContent"; +import CloseIcon from "@mui/icons-material/Close"; + +const OperatorCreateForm = ({ open, setOpen, mutate }) => { + return ( + + setOpen(false)} + sx={(theme) => ({ + position: "absolute", + right: 8, + top: 8, + zIndex: 50, + color: theme.palette.grey[500], + })} + > + + + {open && } + + ); +}; +export default OperatorCreateForm; diff --git a/src/components/dashboard/roadSafety/operator/Form/StepOne/index.jsx b/src/components/dashboard/roadSafety/operator/Form/StepOne/index.jsx new file mode 100644 index 0000000..e390936 --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/Form/StepOne/index.jsx @@ -0,0 +1,36 @@ +import { Button, IconButton, useMediaQuery } from "@mui/material"; +import { AddCircle } from "@mui/icons-material"; +import { useTheme } from "@emotion/react"; +import { useState } from "react"; +import OperatorCreateForm from "./OperatorCreateForm"; + +const StepOne = ({ mutate }) => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down("sm")); + const [open, setOpen] = useState(false); + + const handleOpen = () => { + setOpen(true); + }; + return ( + <> + {isMobile ? ( + + + + ) : ( + + )} + + + ); +}; +export default StepOne; diff --git a/src/components/dashboard/roadSafety/operator/Form/StepThree/ImageUpload.jsx b/src/components/dashboard/roadSafety/operator/Form/StepThree/ImageUpload.jsx new file mode 100644 index 0000000..5186a4b --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/Form/StepThree/ImageUpload.jsx @@ -0,0 +1,77 @@ +import { FormControl, FormHelperText } from "@mui/material"; +import UploadSystem from "@/core/components/UploadSystem"; +import React, { useEffect, useState } from "react"; + +const ImageUpload = ({ name, value, onChange, error, title }) => { + const [beforeImg, setBeforeImg] = useState(value ? value : null); + const [beforeFileType, setBeforeFileType] = useState(value ? "image/" : null); + const [beforeFileName, setBeforeFileName] = useState(null); + const [showBeforeImage, setShowBeforeImage] = useState(!value); + + useEffect(() => { + if (value) { + setShowBeforeImage(false); + if (typeof value === "string") { + setBeforeImg(value); + setBeforeFileType("image/"); + } else if (value instanceof File) { + setBeforeImg(URL.createObjectURL(value)); + setBeforeFileType(value.type); + } + } + }, [value]); + + const handleFileChange = (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); + onChange(uploadedFile); + setShowBeforeImage(false); + } + }; + + return ( + + + {title} + + + {error ? error.message : null} + + ); +}; +export default ImageUpload; diff --git a/src/components/dashboard/roadSafety/operator/Form/StepThree/StepThreeContent.jsx b/src/components/dashboard/roadSafety/operator/Form/StepThree/StepThreeContent.jsx new file mode 100644 index 0000000..e3916d1 --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/Form/StepThree/StepThreeContent.jsx @@ -0,0 +1,69 @@ +import { Button, DialogActions, DialogContent, Stack } from "@mui/material"; +import { Controller, useForm } from "react-hook-form"; +import { yupResolver } from "@hookform/resolvers/yup"; +import StyledForm from "@/core/components/StyledForm"; +import { mixed, object } from "yup"; +import ImageUpload from "./ImageUpload"; +import useRequest from "@/lib/hooks/useRequest"; +import { THIRD_STEP_STORE } from "@/core/utils/routes"; + +const StepThreeContent = ({ setOpen, mutate, rowId }) => { + const requestServer = useRequest({ notificationSuccess: true }); + const defaultValues = { + action_picture: null, + }; + const validationSchema = object({ + action_picture: mixed().nullable().required("لطفا عکس اقدام را بارگذاری کنید!"), + }); + const { + control, + handleSubmit, + formState: { isSubmitting, errors }, + } = useForm({ + defaultValues, + resolver: yupResolver(validationSchema), + mode: "onBlur", + }); + const onSubmit = async (data) => { + const formData = new FormData(); + formData.append("action_picture", data.action_picture); + await requestServer(`${THIRD_STEP_STORE}/${rowId}`, "post", { + data: formData, + }) + .then((response) => { + mutate(); + setOpen(false); + }) + .catch((error) => {}); + }; + return ( + + + + ( + + )} + /> + + + + + + + + ); +}; +export default StepThreeContent; diff --git a/src/components/dashboard/roadSafety/operator/Form/StepThree/index.jsx b/src/components/dashboard/roadSafety/operator/Form/StepThree/index.jsx new file mode 100644 index 0000000..8602d6e --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/Form/StepThree/index.jsx @@ -0,0 +1,32 @@ +import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material"; +import { useState } from "react"; +import StepThreeContent from "./StepThreeContent"; +import AddPhotoAlternateIcon from "@mui/icons-material/AddPhotoAlternate"; +const StepThree = ({ mutate, rowId }) => { + const [open, setOpen] = useState(false); + return ( + <> + + setOpen(true)}> + + + + setOpen(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={"sm"} + fullWidth + > + بارگذاری تصویر اقدام + + + + ); +}; +export default StepThree; diff --git a/src/components/dashboard/roadSafety/operator/Form/StepTwo/ShowDocuments.jsx b/src/components/dashboard/roadSafety/operator/Form/StepTwo/ShowDocuments.jsx new file mode 100644 index 0000000..93958c8 --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/Form/StepTwo/ShowDocuments.jsx @@ -0,0 +1,37 @@ +import { Box, Card, IconButton, Stack, Typography } from "@mui/material"; +import DeleteIcon from "@mui/icons-material/Delete"; +import React from "react"; +import MinorCrashIcon from "@mui/icons-material/MinorCrash"; + +const ShowDocuments = ({ deleteDamageItem, selectedDamageItem }) => { + return ( + + + + + + {selectedDamageItem.name} + + + + + + deleteDamageItem(selectedDamageItem.name)}> + + + + + ); +}; +export default ShowDocuments; diff --git a/src/components/dashboard/roadSafety/operator/Form/StepTwo/StepTwoContent.jsx b/src/components/dashboard/roadSafety/operator/Form/StepTwo/StepTwoContent.jsx new file mode 100644 index 0000000..1b9099d --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/Form/StepTwo/StepTwoContent.jsx @@ -0,0 +1,135 @@ +import { Box, Button, Chip, DialogActions, DialogContent, Divider, Fade, Grid, Stack, Typography } from "@mui/material"; +import { useEffect, useState } from "react"; +import { Controller, useForm } from "react-hook-form"; +import { yupResolver } from "@hookform/resolvers/yup"; +import { mixed, object } from "yup"; +import ShowDocuments from "./ShowDocuments"; +import StyledForm from "@/core/components/StyledForm"; +import { SECOND_STEP_STORE } from "@/core/utils/routes"; +import useRequest from "@/lib/hooks/useRequest"; + +const StepTwoContent = ({ setOpenStepTwoDialog, mutate, rowId }) => { + const requestServer = useRequest({ notificationSuccess: true }); + const [selectedDamageItemList, setSelectedDamageItemList] = useState([]); + const defaultValues = { + judiciary_document: null, + }; + const validationSchema = object({ + judiciary_document: mixed().test("is-array", "لطفا حداقل یک فایل بارگذاری کنید!", (value) => { + return Array.isArray(value) && value.length > 0; + }), + }); + const { + control, + handleSubmit, + setValue, + formState: { isSubmitting, errors }, + } = useForm({ + defaultValues, + resolver: yupResolver(validationSchema), + mode: "onBlur", + }); + + const handleCreateDamage = (files) => { + setSelectedDamageItemList((prev) => { + const newFiles = files.filter((file) => !prev.some((item) => item.name === file.name)); + return [...prev, ...newFiles]; + }); + }; + useEffect(() => { + setValue("judiciary_document", selectedDamageItemList); + }, [selectedDamageItemList]); + + const deleteDamageItem = (name) => { + setSelectedDamageItemList((prev) => prev.filter((documentItem) => documentItem.name !== name)); + }; + const onSubmit = async (data) => { + const formData = new FormData(); + data.judiciary_document.map((item, index) => formData.append(`judiciary_document[${index}]`, item)); + await requestServer(`${SECOND_STEP_STORE}/${rowId}`, "post", { + data: formData, + }) + .then((response) => { + mutate(); + setOpenStepTwoDialog(false); + }) + .catch((error) => {}); + }; + return ( + + + + ( + <> + + {error && {error.message}} + + )} + /> + + + + + {selectedDamageItemList.length === 0 && ( + + + فایل موردنظر را بارگذاری کنید. + + + )} + + + {selectedDamageItemList.length !== 0 && + selectedDamageItemList.map((selectedDamageItem, index) => ( + + + + ))} + + + + + + + + + ); +}; +export default StepTwoContent; diff --git a/src/components/dashboard/roadSafety/operator/Form/StepTwo/index.jsx b/src/components/dashboard/roadSafety/operator/Form/StepTwo/index.jsx new file mode 100644 index 0000000..5bdfe20 --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/Form/StepTwo/index.jsx @@ -0,0 +1,33 @@ +import UploadFileIcon from "@mui/icons-material/UploadFile"; +import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material"; +import { useState } from "react"; +import StepTwoContent from "./StepTwoContent"; + +const StepTwo = ({ mutate, rowId }) => { + const [openStepTwoDialog, setOpenStepTwoDialog] = useState(false); + return ( + <> + + setOpenStepTwoDialog(true)}> + + + + setOpenStepTwoDialog(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={"sm"} + fullWidth + > + بارگذاری مستندات قضایی + + + + ); +}; +export default StepTwo; diff --git a/src/components/dashboard/roadSafety/operator/OperatorList.jsx b/src/components/dashboard/roadSafety/operator/OperatorList.jsx new file mode 100644 index 0000000..c59e81b --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/OperatorList.jsx @@ -0,0 +1,455 @@ +"use client"; +import CustomSelectByDependency from "@/core/components/DataTable/filter/fieldsType/CustomSelectByDependency"; +import DataTableWithAuth from "@/core/components/DataTableWithAuth"; +import { Box, Stack } from "@mui/material"; +import moment from "jalali-moment"; +import { useEffect, useMemo, useState } from "react"; +import RowActions from "./RowActions"; +import Toolbar from "./Toolbar"; +import { usePermissions } from "@/lib/hooks/usePermissions"; +import { useAuth } from "@/lib/contexts/auth"; +import useProvinces from "@/lib/hooks/useProvince"; +import useEdaratLists from "@/lib/hooks/useEdaratLists"; +import { GET_SAFETY_AND_PRIVACY } from "@/core/utils/routes"; +import RecognizePictureDialog from "./RowActions/RecognizePictureDialog"; +import ActionPictureDialog from "./RowActions/ActionPictureDialog"; +import JudiciaryDocumentDialog from "./RowActions/JudiciaryDocumentDialog"; +import LocationForm from "./RowActions/LocationForm"; +import useSafetyAndPrivacyGetItems from "@/lib/hooks/useSafetyAndPrivacyGetItems"; + +const OperatorList = () => { + const { data: userPermissions } = usePermissions(); + const hasCountryPermission = userPermissions?.includes("show-fast-react"); + const { user } = useAuth(); + const statusOptions = [ + { value: "", label: "همه وضعیت ها" }, + { value: 1, label: "گام اول (شناسایی)" }, + { value: 2, label: "گام دوم (مستندات قضایی)" }, + { value: 3, label: "گام سوم (برخورد)" }, + ]; + const axisOptions = [ + { value: "", label: "همه محور ها" }, + { value: 1, label: "آزادراه" }, + { value: 2, label: "بزرگراه" }, + { value: 3, label: "اصلی" }, + { value: 4, label: "فرعی" }, + { value: 5, label: "روستایی" }, + ]; + + const columns = useMemo(() => { + const dynamicColumns = { + header: "استان", + id: "province_id", + enableColumnFilter: true, + datatype: "numeric", + filterMode: "equals", + grow: false, + size: 130, + ColumnSelectComponent: (props) => { + const { provinces, errorProvinces, loadingProvinces } = useProvinces(); + const getColumnSelectOptions = useMemo(() => { + if (loadingProvinces) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorProvinces) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: "کل کشور" }, + ...provinces.map((province) => ({ + value: province.id, + label: province.name_fa, + })), + ]; + }, [provinces, errorProvinces, loadingProvinces]); + return ( + + ); + }, + Cell: ({ row }) => <>{row.original.province_fa}, + }; + return [ + { + accessorKey: "id", + header: "کد یکتا", + id: "id", + enableColumnFilter: true, + datatype: "text", + filterMode: "equals", + sortDescFirst: false, + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + }, + ...(hasCountryPermission ? [dynamicColumns] : []), + { + header: "اداره", + id: "edare_shahri_id", + enableColumnFilter: true, + datatype: "numeric", + filterMode: "equals", + dependencyId: hasCountryPermission ? "province_id" : null, + grow: false, + size: 120, + ColumnSelectComponent: (props) => { + const { edaratList, loadingEdaratList, errorEdaratList } = useEdaratLists( + hasCountryPermission ? props.dependencyFieldValue.value : user.province_id + ); + const [prevDependency, setPrevDependency] = useState( + hasCountryPermission ? props.dependencyFieldValue.value : user.province_id + ); + + const getColumnSelectOptions = useMemo(() => { + if (hasCountryPermission && props.dependencyFieldValue.value === "") { + return [{ value: "empty", label: "ابتدا استان را انتخاب کنید" }]; + } + if (loadingEdaratList) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorEdaratList) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: "کل ادارات" }, + ...edaratList.map((edare) => ({ + value: edare.id, + label: edare.name_fa, + })), + ]; + }, [edaratList, loadingEdaratList, errorEdaratList]); + useEffect(() => { + if (hasCountryPermission) return; + if (prevDependency === props.dependencyFieldValue?.value) return; + props.handleChange({ ...props.filterParameters, value: "" }); + setPrevDependency(props.dependencyFieldValue?.value); + }, [props.dependencyFieldValue?.value, hasCountryPermission]); + return ( + + ); + }, + Cell: ({ row }) => <>{row.original.edare_shahri_name}, + }, + { + header: "اطلاعات فعالیت", + id: "info", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + grow: false, + size: 50, + columns: [ + { + accessorKey: "info_id", + header: "مورد مشاهده شده", + id: "info_id", + enableColumnFilter: true, + datatype: "numeric", + filterMode: "equals", + grow: false, + size: 100, + ColumnSelectComponent: (props) => { + const { itemsList, loadingItemsList, errorItemsList } = useSafetyAndPrivacyGetItems(); + + const getColumnSelectOptions = useMemo(() => { + if (loadingItemsList) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorItemsList) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: "همه موارد" }, + ...itemsList.map((item) => ({ + value: item.id, + label: item.name, + })), + ]; + }, [itemsList, loadingItemsList, errorItemsList]); + + return ( + + ); + }, + Cell: ({ row }) => <>{row.original.info_fa}, + }, + { + accessorKey: "axis_type_id", + header: "نوع محور", + id: "axis_type_id", + enableColumnFilter: true, + datatype: "numeric", + filterMode: "equals", + sortDescFirst: true, + grow: false, + size: 100, + columnSelectOption: () => { + return axisOptions.map((status) => ({ + value: status.value, + label: status.label, + })); + }, + Cell: ({ row }) => (row.original?.axis_type_name ? <>{row.original.axis_type_name} : <>-), + }, + { + accessorKey: "location", + header: "موقعیت", + id: "location", + enableColumnFilter: false, + enableSorting: false, + datatype: "array", + grow: false, + size: 100, + muiTableBodyCellProps: { + sx: { + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ row }) => { + return ( + + + + ); + }, + }, + { + accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"), + header: "تاریخ ثبت", + id: "created_at", + enableColumnFilter: true, + datatype: "date", + filterMode: "between", + grow: false, + size: 100, + }, + ], + }, + { + header: "گام اول (شناسایی)", + id: "stepOne", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + grow: false, + size: 50, + columns: [ + { + accessorKey: "recognize_picture", + header: "تصویر بازدید", + id: "recognize_picture", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + grow: false, + size: 100, + muiTableBodyCellProps: { + sx: { + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ renderedCellValue }) => { + return renderedCellValue ? ( + + + + ) : ( + <>- + ); + }, + }, + { + accessorFn: (row) => + row.activity_date_time ? ( + moment(row.activity_date_time).locale("fa").format("HH:mm | yyyy/MM/DD") + ) : ( + <>- + ), + header: "تاریخ بازدید", + id: "activity_date_time", + enableColumnFilter: true, + datatype: "date", + filterMode: "between", + grow: false, + size: 100, + }, + ], + }, + { + header: "گام دوم (مستندات قضایی)", + id: "stepTwo", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + grow: false, + size: 50, + columns: [ + { + header: "مستندات قضایی", + id: "judiciary_document", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + grow: false, + size: 100, + muiTableBodyCellProps: { + sx: { + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ row }) => { + return ( + + {row.original.judiciary_document_upload_date !== "0000-00-00 00:00:00" ? ( + + ) : ( + <>- + )} + + ); + }, + }, + { + accessorFn: (row) => { + const date = row.judiciary_document_upload_date; + if (!date || date === "0000-00-00 00:00:00") { + return <>-; + } + return moment(date, "YYYY-MM-DD HH:mm:ss").locale("fa").format("HH:mm | yyyy/MM/DD"); + }, + + header: "تاریخ بارگذاری مستندات", + id: "judiciary_document_upload_date", + enableColumnFilter: true, + datatype: "date", + filterMode: "between", + grow: false, + size: 100, + }, + ], + }, + { + header: "گام سوم (برخورد)", + id: "stepThree", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + grow: false, + size: 50, + columns: [ + { + accessorKey: "action_picture", + header: "تصویر اقدام", + id: "action_picture", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + grow: false, + size: 100, + muiTableBodyCellProps: { + sx: { + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ renderedCellValue }) => { + return renderedCellValue ? ( + + + + ) : ( + <>- + ); + }, + }, + { + accessorFn: (row) => + row.action_picture_document_upload_date ? ( + moment(row.action_picture_document_upload_date) + .locale("fa") + .format("HH:mm | yyyy/MM/DD") + ) : ( + <>- + ), + header: "تاریخ ثبت اقدام", + id: "action_picture_document_upload_date", + enableColumnFilter: true, + datatype: "date", + filterMode: "between", + grow: false, + size: 100, + }, + ], + }, + { + header: "وضعیت", + id: "step", + enableColumnFilter: true, + datatype: "numeric", + filterMode: "equals", + sortDescFirst: true, + grow: false, + size: 100, + columnSelectOption: () => { + return statusOptions.map((status) => ({ + value: status.value, + label: status.label, + })); + }, + Cell: ({ row }) => <>{row.original.step_fa}, + }, + ]; + }, []); + + return ( + <> + + + + + ); +}; +export default OperatorList; diff --git a/src/components/dashboard/roadSafety/operator/RowActions/ActionPictureDialog/ActionPictureContent.jsx b/src/components/dashboard/roadSafety/operator/RowActions/ActionPictureDialog/ActionPictureContent.jsx new file mode 100644 index 0000000..f27255b --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/RowActions/ActionPictureDialog/ActionPictureContent.jsx @@ -0,0 +1,44 @@ +import { Box, Stack, Typography, useTheme } from "@mui/material"; +import Image from "next/image"; + +const ActionPictureContent = ({ image, title }) => { + const theme = useTheme(); + return ( + + + {title} + + + Image + + + ); +}; +export default ActionPictureContent; diff --git a/src/components/dashboard/roadSafety/operator/RowActions/ActionPictureDialog/index.jsx b/src/components/dashboard/roadSafety/operator/RowActions/ActionPictureDialog/index.jsx new file mode 100644 index 0000000..4c2911c --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/RowActions/ActionPictureDialog/index.jsx @@ -0,0 +1,40 @@ +import PhotoLibraryIcon from "@mui/icons-material/PhotoLibrary"; +import { Button, Dialog, DialogActions, DialogContent, IconButton, Tooltip } from "@mui/material"; +import { useState } from "react"; +import ActionPictureContent from "./ActionPictureContent"; + +const ActionPictureDialog = ({ image }) => { + const [openImageDialog, setOpenImageDialog] = useState(false); + + return ( + <> + + setOpenImageDialog(true)}> + + + + setOpenImageDialog(false)} + PaperProps={{ + sx: { + boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px", + }, + }} + maxWidth={"sm"} + scroll="paper" + > + + + + + + + + + ); +}; +export default ActionPictureDialog; diff --git a/src/components/dashboard/roadSafety/operator/RowActions/DeleteDialog/DeleteContent.jsx b/src/components/dashboard/roadSafety/operator/RowActions/DeleteDialog/DeleteContent.jsx new file mode 100644 index 0000000..7a83c08 --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/RowActions/DeleteDialog/DeleteContent.jsx @@ -0,0 +1,40 @@ +import { Button, DialogActions, DialogContent, Stack, Typography } from "@mui/material"; +import React, { useState } from "react"; +import useRequest from "@/lib/hooks/useRequest"; +import { DELETE_SAFETY_AND_PRIVACY } from "@/core/utils/routes"; + +const DeleteContent = ({ rowId, mutate, setOpenDeleteDialog }) => { + const [submitting, setSubmitting] = useState(false); + const requestServer = useRequest({ notificationSuccess: true }); + const handleClick = () => { + setSubmitting(true); + requestServer(`${DELETE_SAFETY_AND_PRIVACY}/${rowId}`, "delete") + .then(() => { + mutate(); + setOpenDeleteDialog(false); + setSubmitting(false); + }) + .catch(() => { + setSubmitting(false); + }); + }; + return ( + <> + + + آیا از حذف فعالیت اطمینان دارید؟ + + + + + + + + ); +}; + +export default DeleteContent; diff --git a/src/components/dashboard/roadSafety/operator/RowActions/DeleteDialog/index.jsx b/src/components/dashboard/roadSafety/operator/RowActions/DeleteDialog/index.jsx new file mode 100644 index 0000000..596cf9a --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/RowActions/DeleteDialog/index.jsx @@ -0,0 +1,32 @@ +import DeleteIcon from "@mui/icons-material/Delete"; +import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material"; +import { useState } from "react"; +import DeleteContent from "./DeleteContent"; +const DeleteForm = ({ rowId, mutate }) => { + const [openDeleteDialog, setOpenDeleteDialog] = useState(false); + + return ( + <> + + setOpenDeleteDialog(true)}> + + + + setOpenDeleteDialog(false)} + PaperProps={{ + sx: { + boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px", + }, + }} + dir="rtl" + maxWidth={"md"} + > + حذف فعالیت + + + + ); +}; +export default DeleteForm; diff --git a/src/components/dashboard/roadSafety/operator/RowActions/JudiciaryDocumentDialog/JudiciaryDocumentContent.jsx b/src/components/dashboard/roadSafety/operator/RowActions/JudiciaryDocumentDialog/JudiciaryDocumentContent.jsx new file mode 100644 index 0000000..95a3f1e --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/RowActions/JudiciaryDocumentDialog/JudiciaryDocumentContent.jsx @@ -0,0 +1,43 @@ +import { Box, Button, Chip, Divider, Grid, Typography } from "@mui/material"; +import DownloadIcon from "@mui/icons-material/Download"; +import ArticleIcon from "@mui/icons-material/Article"; + +const JudiciaryDocumentContent = ({ judiciaryDocumentDetails }) => { + return ( + + {judiciaryDocumentDetails.map((judiciaryDocument, index) => { + return ( + + + } + label={ + + مستندات قضایی {index + 1} + + } + /> + + + + + ); + })} + + ); +}; +export default JudiciaryDocumentContent; diff --git a/src/components/dashboard/roadSafety/operator/RowActions/JudiciaryDocumentDialog/JudiciaryDocumentController.jsx b/src/components/dashboard/roadSafety/operator/RowActions/JudiciaryDocumentDialog/JudiciaryDocumentController.jsx new file mode 100644 index 0000000..0773130 --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/RowActions/JudiciaryDocumentDialog/JudiciaryDocumentController.jsx @@ -0,0 +1,35 @@ +import { useEffect, useState } from "react"; +import useRequest from "@/lib/hooks/useRequest"; +import DialogLoading from "@/core/components/DialogLoading"; +import JudiciaryDocumentContent from "./JudiciaryDocumentContent"; +import { DESERIALIZE_JUDICIARY_DOCUMENT } from "@/core/utils/routes"; +import { Typography } from "@mui/material"; + +const JudiciaryDocumentController = ({ rowId }) => { + const requestServer = useRequest(); + const [judiciaryDocumentDetails, setJudiciaryDocumentDetails] = useState([]); + const [judiciaryDocumentDetailsLoading, setJudiciaryDocumentDetailsLoading] = useState(false); + useEffect(() => { + setJudiciaryDocumentDetailsLoading(true); + requestServer(`${DESERIALIZE_JUDICIARY_DOCUMENT}/${rowId}`, "get") + .then((response) => { + setJudiciaryDocumentDetails(response.data.data); + setJudiciaryDocumentDetailsLoading(false); + }) + .catch((e) => { + setJudiciaryDocumentDetailsLoading(false); + }); + }, [rowId]); + return ( + <> + {judiciaryDocumentDetailsLoading ? ( + + ) : judiciaryDocumentDetails.length > 0 ? ( + + ) : ( + بدون مستندات + )} + + ); +}; +export default JudiciaryDocumentController; diff --git a/src/components/dashboard/roadSafety/operator/RowActions/JudiciaryDocumentDialog/index.jsx b/src/components/dashboard/roadSafety/operator/RowActions/JudiciaryDocumentDialog/index.jsx new file mode 100644 index 0000000..575d4c5 --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/RowActions/JudiciaryDocumentDialog/index.jsx @@ -0,0 +1,40 @@ +import { Button, Dialog, DialogActions, DialogContent, DialogTitle, IconButton, Tooltip } from "@mui/material"; +import ArticleIcon from "@mui/icons-material/Article"; +import React, { useState } from "react"; +import JudiciaryDocumentController from "./JudiciaryDocumentController"; + +const JudiciaryDocumentDialog = ({ rowId }) => { + const [openJudiciaryDocumentDialog, setOpenJudiciaryDocumentDialog] = useState(false); + return ( + <> + + setOpenJudiciaryDocumentDialog(true)}> + + + + setOpenJudiciaryDocumentDialog(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={"sm"} + fullWidth + > + مشاهده مستندات قضایی + + + + + + + + + ); +}; +export default JudiciaryDocumentDialog; diff --git a/src/components/dashboard/roadSafety/operator/RowActions/LocationForm/LocationFormContent.jsx b/src/components/dashboard/roadSafety/operator/RowActions/LocationForm/LocationFormContent.jsx new file mode 100644 index 0000000..14b3db3 --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/RowActions/LocationForm/LocationFormContent.jsx @@ -0,0 +1,35 @@ +"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, end_lat, end_lng }) => { + return ( + <> + + + + + + + + + + + + ); +}; +export default LocationFormContent; diff --git a/src/components/dashboard/roadSafety/operator/RowActions/LocationForm/index.jsx b/src/components/dashboard/roadSafety/operator/RowActions/LocationForm/index.jsx new file mode 100644 index 0000000..d614215 --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/RowActions/LocationForm/index.jsx @@ -0,0 +1,40 @@ +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, end_lat, end_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"} + > + موقعیت + {openLocationDialog && ( + + )} + + + ); +}; +export default LocationForm; diff --git a/src/components/dashboard/roadSafety/operator/RowActions/RecognizePictureDialog/RecognizePictureContent.jsx b/src/components/dashboard/roadSafety/operator/RowActions/RecognizePictureDialog/RecognizePictureContent.jsx new file mode 100644 index 0000000..39dbdcf --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/RowActions/RecognizePictureDialog/RecognizePictureContent.jsx @@ -0,0 +1,44 @@ +import { Box, Stack, Typography, useTheme } from "@mui/material"; +import Image from "next/image"; + +const RecognizePictureContent = ({ image, title }) => { + const theme = useTheme(); + return ( + + + {title} + + + Image + + + ); +}; +export default RecognizePictureContent; diff --git a/src/components/dashboard/roadSafety/operator/RowActions/RecognizePictureDialog/index.jsx b/src/components/dashboard/roadSafety/operator/RowActions/RecognizePictureDialog/index.jsx new file mode 100644 index 0000000..72ef4ea --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/RowActions/RecognizePictureDialog/index.jsx @@ -0,0 +1,40 @@ +import PhotoLibraryIcon from "@mui/icons-material/PhotoLibrary"; +import { Button, Dialog, DialogActions, DialogContent, IconButton, Tooltip } from "@mui/material"; +import { useState } from "react"; +import RecognizePictureContent from "./RecognizePictureContent"; + +const RecognizePictureDialog = ({ image }) => { + const [openImageDialog, setOpenImageDialog] = useState(false); + + return ( + <> + + setOpenImageDialog(true)}> + + + + setOpenImageDialog(false)} + PaperProps={{ + sx: { + boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px", + }, + }} + maxWidth={"sm"} + scroll="paper" + > + + + + + + + + + ); +}; +export default RecognizePictureDialog; diff --git a/src/components/dashboard/roadSafety/operator/RowActions/index.jsx b/src/components/dashboard/roadSafety/operator/RowActions/index.jsx new file mode 100644 index 0000000..85a7f23 --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/RowActions/index.jsx @@ -0,0 +1,28 @@ +import { usePermissions } from "@/lib/hooks/usePermissions"; +import { Box } from "@mui/material"; +import EditAxisType from "../Form/EditAxisType"; +import StepThree from "../Form/StepThree"; +import StepTwo from "../Form/StepTwo"; +import DeleteForm from "./DeleteDialog"; + +const RowActions = ({ row, mutate }) => { + const { data: userPermissions } = usePermissions(); + const hasDeletePermission = userPermissions?.includes("delete-safety-and-privacy"); + const hasUpdatePermission = userPermissions?.includes("update-safety-and-privacy"); + const hasEdarateShahriPermission = userPermissions?.includes( + "show-safety-and-privacy-operator-cartable-edarate-shahri" + ); + return ( + + {hasUpdatePermission && row.original?.axis_type_id == null && } + {hasEdarateShahriPermission && ( + <> + {row.original?.step === 1 && } + {row.original?.step === 2 && } + + )} + {hasDeletePermission && } + + ); +}; +export default RowActions; diff --git a/src/components/dashboard/roadSafety/operator/Toolbar.jsx b/src/components/dashboard/roadSafety/operator/Toolbar.jsx new file mode 100644 index 0000000..fe8ff36 --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/Toolbar.jsx @@ -0,0 +1,16 @@ +import { Stack } from "@mui/material"; +import StepOne from "./Form/StepOne"; +import PrintExcel from "./ExcelPrint"; +import { usePermissions } from "@/lib/hooks/usePermissions"; + +const Toolbar = ({ table, filterData, mutate }) => { + const { data: userPermissions } = usePermissions(); + const hasCreatePermission = userPermissions?.includes("add-safety-and-privacy"); + return ( + + + {hasCreatePermission && } + + ); +}; +export default Toolbar; diff --git a/src/components/dashboard/roadSafety/operator/index.jsx b/src/components/dashboard/roadSafety/operator/index.jsx new file mode 100644 index 0000000..74badaf --- /dev/null +++ b/src/components/dashboard/roadSafety/operator/index.jsx @@ -0,0 +1,14 @@ +"use client"; +import PageTitle from "@/core/components/PageTitle"; +import { Stack } from "@mui/material"; +import OperatorList from "./OperatorList"; + +const OperatorPage = () => { + return ( + + + + + ); +}; +export default OperatorPage; diff --git a/src/components/dashboard/roadSafety/report/ExcelPrint/index.jsx b/src/components/dashboard/roadSafety/report/ExcelPrint/index.jsx new file mode 100644 index 0000000..192d4fb --- /dev/null +++ b/src/components/dashboard/roadSafety/report/ExcelPrint/index.jsx @@ -0,0 +1,72 @@ +"use client"; +import { Button, CircularProgress, IconButton, useMediaQuery } from "@mui/material"; +import { useMemo, useState } from "react"; +import moment from "jalali-moment"; +import FileSaver from "file-saver"; +import DescriptionIcon from "@mui/icons-material/Description"; +import useRequest from "@/lib/hooks/useRequest"; +import { useTheme } from "@emotion/react"; +import { EXPORT_COUNTRY_ROAD_PATROL_REPORTS, EXPORT_PROVINCE_ROAD_PATROL_REPORTS } from "@/core/utils/routes"; + +const PrintExcel = ({ table, filterData }) => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down("sm")); + const [loading, setLoading] = useState(false); + const requestServer = useRequest({ notificationSuccess: true }); + const activeFilters = Object.entries(filterData).reduce((acc, [key, filter]) => { + if (filter.value) { + acc.push({ id: filter.id, value: filter.value }); + } + return acc; + }, []); + + const filterParams = useMemo(() => { + const params = new URLSearchParams(); + activeFilters.length > 0 && + activeFilters.map((filter, index) => { + params.set(`${filter.id}`, filter.value); + }); + return params; + }, [activeFilters]); + + const clickHandler = () => { + setLoading(true); + const CountryOrProvince = activeFilters.find((item) => item.id === "province_id"); + const requestUrl = + CountryOrProvince.value === "-1" ? EXPORT_COUNTRY_ROAD_PATROL_REPORTS : EXPORT_PROVINCE_ROAD_PATROL_REPORTS; + requestServer(`${requestUrl}?${filterParams}`, "get", { + requestOptions: { responseType: "blob" }, + }) + .then((response) => { + const filename = `خروجی کارتابل گزارشات گشت راهداری تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`; + FileSaver.saveAs(response.data, filename); + }) + .catch(() => {}) + .finally(() => { + setLoading(false); + }); + }; + + return ( + <> + {isMobile ? ( + + + + ) : ( + + )} + + ); +}; +export default PrintExcel; diff --git a/src/components/dashboard/roadSafety/report/ReportLists.jsx b/src/components/dashboard/roadSafety/report/ReportLists.jsx new file mode 100644 index 0000000..9d64db2 --- /dev/null +++ b/src/components/dashboard/roadSafety/report/ReportLists.jsx @@ -0,0 +1,302 @@ +"use client"; +import DataTableWithAuth from "@/core/components/DataTableWithAuth"; +import { Box } from "@mui/material"; +import { useMemo } from "react"; +import Toolbar from "./Toolbar"; + +const ReportLists = ({ data, specialFilter }) => { + const columns = useMemo(() => { + return [ + { + accessorKey: "edare_name", + header: "اداره کل", + id: "edare_name", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + grow: false, + size: 50, + }, + + { + accessorKey: "sum", + header: "تعداد کل", + id: "sum", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + grow: false, + size: 50, + muiTableBodyCellProps: { + sx: { + textAlign: "center", + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ renderedCellValue }) => { + return (renderedCellValue / 1).toLocaleString(); + }, + }, + { + header: "ساخت و ساز غیر مجاز", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + id: "id_89", + grow: false, + size: 50, + columns: [ + { + accessorFn: (row) => (row["89"] ? row["89"]["1"] : 0), + header: "گام اول (شناسایی)", + id: "id_89.1", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + grow: false, + size: 50, + muiTableBodyCellProps: { + sx: { + textAlign: "center", + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ renderedCellValue }) => { + return (renderedCellValue / 1).toLocaleString(); + }, + }, + { + accessorFn: (row) => (row["89"] ? row["89"]["2"] : 0), + header: "گام دوم (مستندات قضایی)", + id: "id_89.2", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + grow: false, + size: 50, + muiTableBodyCellProps: { + sx: { + textAlign: "center", + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ renderedCellValue }) => { + return (renderedCellValue / 1).toLocaleString(); + }, + }, + { + accessorFn: (row) => (row["89"] ? row["89"]["3"] : 0), + header: "گام سوم (برخورد)", + id: "id_89.3", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + grow: false, + size: 50, + muiTableBodyCellProps: { + sx: { + textAlign: "center", + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ renderedCellValue }) => { + return (renderedCellValue / 1).toLocaleString(); + }, + }, + ], + }, + { + header: "راه دسترسی غیر مجاز", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + id: "id_90", + grow: false, + size: 50, + columns: [ + { + accessorFn: (row) => (row["90"] ? row["90"]["1"] : 0), + header: "گام اول (شناسایی)", + id: "id_90.1", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + grow: false, + size: 50, + muiTableBodyCellProps: { + sx: { + textAlign: "center", + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ renderedCellValue }) => { + return (renderedCellValue / 1).toLocaleString(); + }, + }, + { + accessorFn: (row) => (row["90"] ? row["90"]["2"] : 0), + header: "گام دوم (مستندات قضایی)", + id: "id_90.2", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + grow: false, + size: 50, + muiTableBodyCellProps: { + sx: { + textAlign: "center", + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ renderedCellValue }) => { + return (renderedCellValue / 1).toLocaleString(); + }, + }, + { + accessorFn: (row) => (row["90"] ? row["90"]["3"] : 0), + header: "گام سوم (برخورد)", + id: "id_90.3", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + grow: false, + size: 50, + muiTableBodyCellProps: { + sx: { + textAlign: "center", + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ renderedCellValue }) => { + return (renderedCellValue / 1).toLocaleString(); + }, + }, + ], + }, + { + header: "عبور تاسیسات زیربنایی غیر مجاز", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + id: "id_91", + grow: false, + size: 50, + columns: [ + { + accessorFn: (row) => (row["91"] ? row["91"]["1"] : 0), + header: "گام اول (شناسایی)", + id: "id_91.1", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + grow: false, + size: 50, + muiTableBodyCellProps: { + sx: { + textAlign: "center", + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ renderedCellValue }) => { + return (renderedCellValue / 1).toLocaleString(); + }, + }, + { + accessorFn: (row) => (row["91"] ? row["91"]["2"] : 0), + header: "گام دوم (مستندات قضایی)", + id: "id_91.2", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + grow: false, + size: 50, + muiTableBodyCellProps: { + sx: { + textAlign: "center", + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ renderedCellValue }) => { + return (renderedCellValue / 1).toLocaleString(); + }, + }, + { + accessorFn: (row) => (row["91"] ? row["91"]["3"] : 0), + header: "گام سوم (برخورد)", + id: "id_91.3", + enableColumnFilter: false, + enableSorting: false, + datatype: "text", + grow: false, + size: 50, + muiTableBodyCellProps: { + sx: { + textAlign: "center", + borderLeft: "1px solid #e1e1e1", + py: 0, + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + Cell: ({ renderedCellValue }) => { + return (renderedCellValue / 1).toLocaleString(); + }, + }, + ], + }, + ]; + }, []); + + return ( + + + + ); +}; + +export default ReportLists; diff --git a/src/components/dashboard/roadSafety/report/Search/FromDateController.jsx b/src/components/dashboard/roadSafety/report/Search/FromDateController.jsx new file mode 100644 index 0000000..cc6226a --- /dev/null +++ b/src/components/dashboard/roadSafety/report/Search/FromDateController.jsx @@ -0,0 +1,28 @@ +import { Controller } from "react-hook-form"; +import MuiDatePicker from "@/core/components/MuiDatePicker"; +import React from "react"; +import moment from "jalali-moment"; + +const FromDateController = ({ control }) => { + return ( + ( + { + const formattedDate = moment(new Date(newValue)).locale("en").format("YYYY-MM-DD"); + onChange(formattedDate); // Update the field value in react-hook-form + }} + helperText={error ? error.message : null} + /> + )} + /> + ); +}; +export default FromDateController; diff --git a/src/components/dashboard/roadSafety/report/Search/SearchReportField.jsx b/src/components/dashboard/roadSafety/report/Search/SearchReportField.jsx new file mode 100644 index 0000000..606e08c --- /dev/null +++ b/src/components/dashboard/roadSafety/report/Search/SearchReportField.jsx @@ -0,0 +1,49 @@ +import { Button, Grid, LinearProgress, Typography } from "@mui/material"; +import SearchIcon from "@mui/icons-material/Search"; +import React from "react"; +import FromDateController from "./FromDateController"; +import ToDateController from "./ToDateController"; +import SelectProvince from "./SelectProvince"; +import { Controller } from "react-hook-form"; +import SelectAxisType from "./SelectAxisType"; + +const SearchReportField = ({ control, hasProvincesPermission }) => { + return ( + + + + + + + + {hasProvincesPermission && ( + + + + )} + + + + + ( + + )} + /> + + + ); +}; + +export default SearchReportField; diff --git a/src/components/dashboard/roadSafety/report/Search/SelectAxisType.jsx b/src/components/dashboard/roadSafety/report/Search/SelectAxisType.jsx new file mode 100644 index 0000000..217143e --- /dev/null +++ b/src/components/dashboard/roadSafety/report/Search/SelectAxisType.jsx @@ -0,0 +1,45 @@ +import { FormControl, FormHelperText, InputLabel, MenuItem, Select } from "@mui/material"; +import { Controller } from "react-hook-form"; + +const axisOptions = [ + { value: 1, label: "آزادراه" }, + { value: 2, label: "بزرگراه" }, + { value: 3, label: "اصلی" }, + { value: 4, label: "فرعی" }, + { value: 5, label: "روستایی" }, +]; + +const SelectAxisType = ({ control }) => { + return ( + ( + + نوع محور + + {error && {error.message}} + + )} + /> + ); +}; +export default SelectAxisType; diff --git a/src/components/dashboard/roadSafety/report/Search/SelectProvince.jsx b/src/components/dashboard/roadSafety/report/Search/SelectProvince.jsx new file mode 100644 index 0000000..2b24d67 --- /dev/null +++ b/src/components/dashboard/roadSafety/report/Search/SelectProvince.jsx @@ -0,0 +1,45 @@ +import useProvinces from "@/lib/hooks/useProvince"; +import { FormControl, FormHelperText, InputLabel, MenuItem, Select } from "@mui/material"; +import { Controller } from "react-hook-form"; + +const SelectProvince = ({ control }) => { + const { provinces, loadingProvinces, errorProvinces } = useProvinces(); + return ( + ( + + استان + + {error && {error.message}} + + )} + /> + ); +}; +export default SelectProvince; diff --git a/src/components/dashboard/roadSafety/report/Search/ToDateController.jsx b/src/components/dashboard/roadSafety/report/Search/ToDateController.jsx new file mode 100644 index 0000000..ad7690a --- /dev/null +++ b/src/components/dashboard/roadSafety/report/Search/ToDateController.jsx @@ -0,0 +1,30 @@ +import { Controller, useWatch } from "react-hook-form"; +import MuiDatePicker from "@/core/components/MuiDatePicker"; +import React from "react"; +import moment from "jalali-moment"; + +const ToDateController = ({ control }) => { + const minDate = useWatch({ control, name: "from_date" }); + return ( + ( + { + const formattedDate = moment(new Date(newValue)).locale("en").format("YYYY-MM-DD"); + onChange(formattedDate); // Update the field value in react-hook-form + }} + helperText={error ? error.message : null} + /> + )} + /> + ); +}; +export default ToDateController; diff --git a/src/components/dashboard/roadSafety/report/Search/index.jsx b/src/components/dashboard/roadSafety/report/Search/index.jsx new file mode 100644 index 0000000..f29d302 --- /dev/null +++ b/src/components/dashboard/roadSafety/report/Search/index.jsx @@ -0,0 +1,13 @@ +import StyledForm from "@/core/components/StyledForm"; +import SearchReportField from "./SearchReportField"; + +const SearchReportList = ({ handleSubmit, onSearchSubmit, control, hasProvincesPermission }) => { + return ( + <> + + + + + ); +}; +export default SearchReportList; diff --git a/src/components/dashboard/roadSafety/report/Toolbar.jsx b/src/components/dashboard/roadSafety/report/Toolbar.jsx new file mode 100644 index 0000000..7dd930f --- /dev/null +++ b/src/components/dashboard/roadSafety/report/Toolbar.jsx @@ -0,0 +1,11 @@ +import PrintExcel from "./ExcelPrint"; +import { Box } from "@mui/material"; + +const Toolbar = ({ table, filterData, mutate }) => { + return ( + + + + ); +}; +export default Toolbar; diff --git a/src/components/dashboard/roadSafety/report/index.jsx b/src/components/dashboard/roadSafety/report/index.jsx new file mode 100644 index 0000000..cafa140 --- /dev/null +++ b/src/components/dashboard/roadSafety/report/index.jsx @@ -0,0 +1,142 @@ +"use client"; +import PageTitle from "@/core/components/PageTitle"; +import { LinearProgress, Stack } from "@mui/material"; +import SearchReportList from "./Search"; +import { useEffect, useState } from "react"; +import ReportLists from "./ReportLists"; +import useRequest from "@/lib/hooks/useRequest"; +import { GET_ROAD_SAFETY_CITY_ACTIVITY_REPORT, GET_ROAD_SAFETY_PROVINCE_ACTIVITY_REPORT } from "@/core/utils/routes"; +import moment from "jalali-moment"; +import * as yup from "yup"; +import { useForm } from "react-hook-form"; +import { yupResolver } from "@hookform/resolvers/yup"; +import { usePermissions } from "@/lib/hooks/usePermissions"; +import { useAuth } from "@/lib/contexts/auth"; + +const ReportPage = () => { + const [data, setData] = useState(null); + const { data: userPermissions } = usePermissions(); + const { user } = useAuth(); + const requestServer = useRequest(); + const hasProvincesPermission = userPermissions.includes("show-safety-and-privacy-operator-cartable"); + + const defaultValues = { + from_date: moment(new Date()).format("YYYY-MM-DD"), + date_to: moment(new Date()).format("YYYY-MM-DD"), + province_id: hasProvincesPermission ? "-1" : user.province_id, + axis_type_id: "-1", + }; + const defaultFilter = [ + { value: `${defaultValues.province_id}`, datatype: "numeric", id: "province_id", fn: "equals" }, + { value: `${defaultValues.axis_type_id}`, datatype: "numeric", id: "axis_type_id", fn: "equals" }, + { value: `${defaultValues.from_date}`, datatype: "date", id: "from_date", fn: "between" }, + { value: `${defaultValues.date_to}`, datatype: "date", id: "date_to", fn: "between" }, + ]; + const [specialFilter, setSpecialFilter] = useState(defaultFilter); + + const onSearchSubmit = async (data) => { + const params = new URLSearchParams(); + params.set("from_date", `${data.from_date}`); + params.set("date_to", `${data.date_to}`); + if (data.axis_type_id != "-1") params.set("axis_type_id", `${data.axis_type_id}`); + + setSpecialFilter([ + { value: `${data.province_id}`, datatype: "numeric", id: "province_id", fn: "equals" }, + { value: `${data.axis_type_id}`, datatype: "numeric", id: "axis_type_id", fn: "equals" }, + { value: `${data.from_date}`, datatype: "date", id: "from_date", fn: "between" }, + { value: `${data.date_to}`, datatype: "date", id: "date_to", fn: "between" }, + ]); + if (data.province_id === "-1") { + try { + const response = await requestServer(`${GET_ROAD_SAFETY_PROVINCE_ACTIVITY_REPORT}?${params}`); + const result = response.data.data; + const nationalReportForItem = result.activities.find((report) => report.province_id === -1); + const nationalReport = { + edare_name: "کل کشور", + ...nationalReportForItem, + }; + + setData({ + data: [ + nationalReport, + ...result.provinces.map((province) => { + const filteredReports = result.activities.find( + (report) => report.province_id === province.id + ); + return { + ...filteredReports, + edare_name: province.name_fa, + }; + }), + ], + filters: data, + }); + } catch (e) {} + } else { + try { + params.set("province_id", `${data.province_id}`); + const response = await requestServer(`${GET_ROAD_SAFETY_CITY_ACTIVITY_REPORT}?${params}`); + const result = response.data.data; + const nationalReportForItem = result.activities.find((report) => report.edare_shahri_id == "-1"); + const nationalReport = { + ...nationalReportForItem, + edare_name: "کل استان", + }; + setData({ + data: [ + nationalReport, + ...result.edarateShahri.map((edare) => { + const filteredReports = result.activities.find( + (report) => report.edare_shahri_id == edare.id + ); + return { + edare_name: edare.name_fa, + ...filteredReports, + }; + }), + ], + filters: data, + }); + } catch (e) {} + } + }; + + useEffect(() => { + if (!userPermissions) return; + onSearchSubmit(defaultValues); + }, [userPermissions]); + + const validationSchema = yup.object().shape({ + from_date: yup + .string() + .required("تاریخ ثبت الزامی است!") + .matches(/^\d{4}-\d{2}-\d{2}$/, "تاریخ ثبت الزامی است!") + .test("is-valid-date", "تاریخ ثبت معتبر نیست!", (value) => moment(value, "YYYY-MM-DD", true).isValid()), + date_to: yup + .string() + .required("تاریخ ثبت الزامی است!") + .matches(/^\d{4}-\d{2}-\d{2}$/, "تاریخ ثبت الزامی است!") + .test("is-valid-date", "تاریخ ثبت معتبر نیست!", (value) => moment(value, "YYYY-MM-DD", true).isValid()), + province_id: yup.string().nullable(), + axis_type_id: yup.string().nullable(), + }); + + const { control, handleSubmit } = useForm({ + defaultValues, + resolver: yupResolver(validationSchema), + mode: "onBlur", + }); + return ( + + + + {!data ? : } + + ); +}; +export default ReportPage; diff --git a/src/components/dashboard/userActivities/Actions/Create/Form/ActionTypeList.jsx b/src/components/dashboard/userActivities/Actions/Create/Form/ActionTypeList.jsx new file mode 100644 index 0000000..0732896 --- /dev/null +++ b/src/components/dashboard/userActivities/Actions/Create/Form/ActionTypeList.jsx @@ -0,0 +1,38 @@ +import { FormControl, FormHelperText, InputLabel, MenuItem, OutlinedInput, Select } from "@mui/material"; + +const ActionTypeList = ({ value, onChange, error }) => { + const statusOptions = [ + { value: "show", label: "show" }, + { value: "add", label: "add" }, + { value: "edit", label: "edit" }, + { value: "delete", label: "delete" }, + { value: "report", label: "report" }, + { value: "action", label: "action" }, + ]; + + return ( + + + نوع فعالیت + + + {error && {error.message}} + + ); +}; +export default ActionTypeList; diff --git a/src/components/dashboard/userActivities/Actions/Create/Form/CreateFormContent.jsx b/src/components/dashboard/userActivities/Actions/Create/Form/CreateFormContent.jsx new file mode 100644 index 0000000..2898404 --- /dev/null +++ b/src/components/dashboard/userActivities/Actions/Create/Form/CreateFormContent.jsx @@ -0,0 +1,98 @@ +import PersianTextField from "@/core/components/PersianTextField"; +import StyledForm from "@/core/components/StyledForm"; +import { yupResolver } from "@hookform/resolvers/yup"; +import { Beenhere, ExitToApp } from "@mui/icons-material"; +import { Button, DialogActions, DialogContent, Stack, TextField } from "@mui/material"; +import { Controller, useForm } from "react-hook-form"; +import { object, string } from "yup"; +import ActionTypeList from "./ActionTypeList"; + +const validationSchema = object({ + title: string().required("وارد کردن عنوان الزامیست!"), + log_unique_code: string().required("وارد کردن کد الزامیست!"), + action_type: string().required("وارد کردن نوع فعالیت الزامیست!"), +}); + +const CreateFormContent = ({ setOpen, defaultValues, onSubmitBase }) => { + const { + control, + handleSubmit, + formState: { isSubmitting }, + } = useForm({ + defaultValues, + resolver: yupResolver(validationSchema), + mode: "onBlur", + }); + const handleOnSubmit = async (data) => { + await onSubmitBase(data); + }; + + return ( + <> + + + + ( + + )} + /> + ( + + )} + /> + ( + + )} + /> + + + + + + + + + ); +}; +export default CreateFormContent; diff --git a/src/components/dashboard/userActivities/Actions/Create/Form/index.jsx b/src/components/dashboard/userActivities/Actions/Create/Form/index.jsx new file mode 100644 index 0000000..5275391 --- /dev/null +++ b/src/components/dashboard/userActivities/Actions/Create/Form/index.jsx @@ -0,0 +1,58 @@ +import { Dialog, DialogTitle, IconButton } from "@mui/material"; +import CreateFormContent from "./CreateFormContent"; +import CloseIcon from "@mui/icons-material/Close"; +import useRequest from "@/lib/hooks/useRequest"; +import { CREATE_USER_ACTIVITY } from "@/core/utils/routes"; +import { DialogHeader } from "next/dist/client/components/react-dev-overlay/internal/components/Dialog"; + +const CreateForm = ({ open, setOpen, mutate }) => { + const requestServer = useRequest({ notificationSuccess: true }); + const defaultValues = { + title: "", + log_unique_code: "", + action_type: "", + }; + const onSubmit = async (result) => { + const formData = new FormData(); + formData.append("description", result.title); + formData.append("log_unique_code", result.log_unique_code); + formData.append("action_type", result.action_type); + await requestServer(CREATE_USER_ACTIVITY, "post", { + data: formData, + }) + .then(() => { + mutate(); + setOpen(false); + }) + .catch(() => {}); + }; + return ( + + setOpen(false)} + sx={(theme) => ({ + position: "absolute", + right: 8, + top: 8, + zIndex: 50, + color: theme.palette.grey[500], + })} + > + + + + ثبت فعالیت کاربران + + {open && ( + + )} + + ); +}; +export default CreateForm; diff --git a/src/components/dashboard/userActivities/Actions/Create/index.jsx b/src/components/dashboard/userActivities/Actions/Create/index.jsx new file mode 100644 index 0000000..b26543a --- /dev/null +++ b/src/components/dashboard/userActivities/Actions/Create/index.jsx @@ -0,0 +1,36 @@ +import { AddCircle } from "@mui/icons-material"; +import { Button, IconButton, useMediaQuery, useTheme } from "@mui/material"; +import CreateForm from "./Form"; +import { useState } from "react"; + +const CreateUserActivity = ({ mutate }) => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down("sm")); + const [open, setOpen] = useState(false); + + const handleOpen = () => { + setOpen(true); + }; + + return ( + <> + {isMobile ? ( + + + + ) : ( + + )} + + + ); +}; +export default CreateUserActivity; diff --git a/src/components/dashboard/userActivities/Actions/Edit/EditController.jsx b/src/components/dashboard/userActivities/Actions/Edit/EditController.jsx new file mode 100644 index 0000000..0486691 --- /dev/null +++ b/src/components/dashboard/userActivities/Actions/Edit/EditController.jsx @@ -0,0 +1,38 @@ +import useRequest from "@/lib/hooks/useRequest"; +import CreateFormContent from "../Create/Form/CreateFormContent"; +import { UPDATE_USER_ACTIVITY } from "@/core/utils/routes"; +import { DialogTitle } from "@mui/material"; +import { DialogHeader } from "next/dist/client/components/react-dev-overlay/internal/components/Dialog"; + +const EditController = ({ rowId, mutate, setOpen, row }) => { + const requestServer = useRequest({ notificationSuccess: true }); + + const defaultData = { + title: row.original?.description || "", + log_unique_code: row.original?.log_unique_code || "", + action_type: row.original?.action_type || "", + }; + const handleSubmit = async (result) => { + const formData = new FormData(); + formData.append("description", result.title); + formData.append("log_unique_code", result.log_unique_code); + formData.append("action_type", result.action_type); + await requestServer(`${UPDATE_USER_ACTIVITY}/${rowId}`, "post", { + data: formData, + }) + .then(() => { + mutate(); + setOpen(false); + }) + .catch(() => {}); + }; + return ( + <> + + ویرایش فعالیت کاربران + + + + ); +}; +export default EditController; diff --git a/src/components/dashboard/userActivities/Actions/Edit/index.jsx b/src/components/dashboard/userActivities/Actions/Edit/index.jsx new file mode 100644 index 0000000..ca5f622 --- /dev/null +++ b/src/components/dashboard/userActivities/Actions/Edit/index.jsx @@ -0,0 +1,51 @@ +import { useState } from "react"; +import { Dialog, IconButton, Tooltip } from "@mui/material"; +import BorderColorIcon from "@mui/icons-material/BorderColor"; +import CloseIcon from "@mui/icons-material/Close"; +import EditController from "./EditController"; + +const EditUserActivity = ({ mutate, row, rowId }) => { + const [open, setOpen] = useState(false); + + return ( + <> + + { + setOpen(true); + }} + > + + + + + setOpen(false)} + sx={(theme) => ({ + position: "absolute", + right: 8, + top: 8, + zIndex: 50, + color: theme.palette.grey[500], + })} + > + + + {open && } + + + ); +}; +export default EditUserActivity; diff --git a/src/components/dashboard/userActivities/RowActions/DeleteDialog/DeleteContent.jsx b/src/components/dashboard/userActivities/RowActions/DeleteDialog/DeleteContent.jsx new file mode 100644 index 0000000..159746a --- /dev/null +++ b/src/components/dashboard/userActivities/RowActions/DeleteDialog/DeleteContent.jsx @@ -0,0 +1,39 @@ +import { Button, DialogActions, DialogContent, Stack, Typography } from "@mui/material"; +import React, { useState } from "react"; +import useRequest from "@/lib/hooks/useRequest"; +import { DELETE_USER_ACTIVITIES } from "@/core/utils/routes"; + +const DeleteContent = ({ rowId, mutate, setOpenDeleteDialog }) => { + const [submitting, setSubmitting] = useState(false); + const requestServer = useRequest({ notificationSuccess: true }); + const handleClick = () => { + setSubmitting(true); + requestServer(`${DELETE_USER_ACTIVITIES}/${rowId}`, "delete") + .then(() => { + mutate(); + setSubmitting(false); + setOpenDeleteDialog(false); + }) + .catch(() => { + setSubmitting(false); + }); + }; + return ( + <> + + + آیا از حذف این فعالیت کاربران اطمینان دارید؟ + + + + + + + + ); +}; +export default DeleteContent; diff --git a/src/components/dashboard/userActivities/RowActions/DeleteDialog/index.jsx b/src/components/dashboard/userActivities/RowActions/DeleteDialog/index.jsx new file mode 100644 index 0000000..7cbd3a1 --- /dev/null +++ b/src/components/dashboard/userActivities/RowActions/DeleteDialog/index.jsx @@ -0,0 +1,34 @@ +import DeleteIcon from "@mui/icons-material/Delete"; +import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material"; +import { useState } from "react"; +import DeleteContent from "./DeleteContent"; +const DeleteDialog = ({ rowId, mutate }) => { + const [openDeleteDialog, setOpenDeleteDialog] = useState(false); + + return ( + <> + + setOpenDeleteDialog(true)}> + + + + setOpenDeleteDialog(false)} + PaperProps={{ + sx: { + boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px", + }, + }} + dir="rtl" + maxWidth={"md"} + > + حذف فعالیت کاربران + {openDeleteDialog && ( + + )} + + + ); +}; +export default DeleteDialog; diff --git a/src/components/dashboard/userActivities/RowActions/index.jsx b/src/components/dashboard/userActivities/RowActions/index.jsx new file mode 100644 index 0000000..2f7f578 --- /dev/null +++ b/src/components/dashboard/userActivities/RowActions/index.jsx @@ -0,0 +1,12 @@ +import { Box } from "@mui/material"; +import EditUserActivity from "../Actions/Edit"; +import DeleteDialog from "./DeleteDialog"; +const RowActions = ({ row, mutate }) => { + return ( + + + + + ); +}; +export default RowActions; diff --git a/src/components/dashboard/userActivities/Toolbar.jsx b/src/components/dashboard/userActivities/Toolbar.jsx new file mode 100644 index 0000000..7d3ce90 --- /dev/null +++ b/src/components/dashboard/userActivities/Toolbar.jsx @@ -0,0 +1,9 @@ +import CreateUserActivity from "./Actions/Create"; +const Toolbar = ({ mutate }) => { + return ( + <> + + + ); +}; +export default Toolbar; diff --git a/src/components/dashboard/userActivities/UserActivitiesList.jsx b/src/components/dashboard/userActivities/UserActivitiesList.jsx new file mode 100644 index 0000000..cbdad72 --- /dev/null +++ b/src/components/dashboard/userActivities/UserActivitiesList.jsx @@ -0,0 +1,83 @@ +"use client"; +import DataTableWithAuth from "@/core/components/DataTableWithAuth"; +import { GET_USER_ACTIVITIES_LIST } from "@/core/utils/routes"; +import { Box } from "@mui/material"; +import { useMemo } from "react"; +import RowActions from "./RowActions"; +import Toolbar from "./Toolbar"; + +const UserActivitiesList = () => { + const columns = useMemo( + () => [ + { + accessorKey: "id", + header: "کد یکتا", + id: "id", + enableColumnFilter: true, + datatype: "text", + filterMode: "equals", + sortDescFirst: false, + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + }, + { + accessorKey: "description", + header: "عنوان", + id: "description", + enableColumnFilter: true, + datatype: "text", + filterMode: "equals", + sortDescFirst: false, + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + }, + { + accessorKey: "log_unique_code", + header: "کد", + id: "log_unique_code", + enableColumnFilter: true, + datatype: "text", + filterMode: "equals", + sortDescFirst: false, + columnFilterModeOptions: ["equals"], + grow: false, + size: 100, + }, + { + accessorKey: "action_type", + header: "نوع فعالیت", + id: "action_type", + enableColumnFilter: false, + datatype: "text", + filterMode: "equals", + sortDescFirst: false, + columnFilterModeOptions: ["equals"], + grow: false, + size: 100, + }, + ], + [] + ); + + return ( + <> + + + + + ); +}; +export default UserActivitiesList; diff --git a/src/components/dashboard/userActivities/index.jsx b/src/components/dashboard/userActivities/index.jsx new file mode 100644 index 0000000..321001d --- /dev/null +++ b/src/components/dashboard/userActivities/index.jsx @@ -0,0 +1,13 @@ +import PageTitle from "@/core/components/PageTitle"; +import { Stack } from "@mui/material"; +import UserActivitiesList from "./UserActivitiesList"; + +const UserActivitiesPage = () => { + return ( + + + + + ); +}; +export default UserActivitiesPage; diff --git a/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarBadge.jsx b/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarBadge.jsx index 4ee1a83..5f0fa7a 100644 --- a/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarBadge.jsx +++ b/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarBadge.jsx @@ -14,6 +14,6 @@ const SidebarBadge = ({ badge, chipProps = {} }) => { if (!data) return null; if (!value) return null; - return ; + return ; }; export default SidebarBadge; diff --git a/src/core/components/BlinkingCell.jsx b/src/core/components/BlinkingCell.jsx new file mode 100644 index 0000000..3b1eed2 --- /dev/null +++ b/src/core/components/BlinkingCell.jsx @@ -0,0 +1,12 @@ +import { Box, Stack } from "@mui/material"; +import BlinkingCircle from "./BlinkingCircle"; + +const BlinkingCell = ({ visible = false, value }) => { + return ( + + {value} + {visible && } + + ); +}; +export default BlinkingCell; diff --git a/src/core/components/BlinkingCircle.jsx b/src/core/components/BlinkingCircle.jsx new file mode 100644 index 0000000..0d377e1 --- /dev/null +++ b/src/core/components/BlinkingCircle.jsx @@ -0,0 +1,24 @@ +import { keyframes } from "@emotion/react"; +import { Box } from "@mui/material"; + +const blink = keyframes` + 0% { opacity: 1; } + 50% { opacity: 0.3; } + 100% { opacity: 1; } +`; + +const BlinkingCircle = () => { + return ( + theme.palette.warning.main, + animation: `${blink} 1.3s infinite ease-in-out`, + }} + /> + ); +}; + +export default BlinkingCircle; diff --git a/src/core/components/DataTable/Main.js b/src/core/components/DataTable/Main.js index e9a3a37..efad5a0 100644 --- a/src/core/components/DataTable/Main.js +++ b/src/core/components/DataTable/Main.js @@ -1,17 +1,29 @@ -import DataTable_Paper from "./table/Paper"; -import { useMaterialReactTable } from "material-react-table"; -import { FA_DATATABLE_LOCALIZATION } from "./localization/fa/datatable"; -import { flattenArrayOfObjects } from "@/core/utils/flattenArrayOfObjects"; -import useDataTable from "@/lib/hooks/useDataTable"; -import { useCallback, useMemo, useState } from "react"; -import useRequest from "@/lib/hooks/useRequest"; -import useSWR from "swr"; -import { flattenObjectOfObjects } from "@/core/utils/flattenObjectOfObjects"; import DataTableFilterDataStructure from "@/core/utils/DataTableFilterDataStructure"; +import { flattenArrayOfObjects } from "@/core/utils/flattenArrayOfObjects"; +import { flattenObjectOfObjects } from "@/core/utils/flattenObjectOfObjects"; import isArrayEmpty from "@/core/utils/isArrayEmpty"; +import useDataTable from "@/lib/hooks/useDataTable"; +import useRequest from "@/lib/hooks/useRequest"; +import { useMaterialReactTable } from "material-react-table"; +import { useCallback, useEffect, useReducer, useState } from "react"; +import useSWR from "swr"; +import { FA_DATATABLE_LOCALIZATION } from "./localization/fa/datatable"; +import DataTable_Paper from "./table/Paper"; + +const rowSelectionReducer = (state, action) => { + switch (action.type) { + case "TOGGLE_ROW": + return { [action.payload]: true }; + case "RESET": + return {}; + default: + return state; + } +}; const DataTable_Main = (props) => { const request = useRequest(); + const [rowSelection, dispatchRowSelection] = useReducer(rowSelectionReducer, {}); const { filterData, sortData, setSortData, hideData } = useDataTable(); const { need_filter, @@ -48,7 +60,15 @@ const DataTable_Main = (props) => { const filteredFilterData = DataTableFilterDataStructure(filterData, isArrayEmpty); params.set("filters", JSON.stringify(filteredFilterData.length === 0 ? [] : filteredFilterData)); } - params.set("sorting", JSON.stringify(sortData)); + params.set( + "sorting", + JSON.stringify( + Object.values(sortData).map(({ id, ...rest }) => ({ + ...rest, + id: id.replace(/__/g, "."), + })) + ) + ); return `${table_url}?${params}`; }, [table_url, filterData, pagination, sortData, specialFilter]); @@ -73,10 +93,19 @@ const DataTable_Main = (props) => { keepPreviousData: true, }); + useEffect(() => { + if (!isValidating) return; + dispatchRowSelection({ type: "RESET" }); + }, [isValidating]); + const table = useMaterialReactTable({ localization: FA_DATATABLE_LOCALIZATION, columns, data: data ?? [], + muiTableBodyRowProps: ({ row }) => ({ + onClick: () => dispatchRowSelection({ type: "TOGGLE_ROW", payload: row.id }), + selected: !!rowSelection[row.id], + }), initialState: { density: "compact", columnVisibility: flattenHideData, @@ -88,6 +117,7 @@ const DataTable_Main = (props) => { columnVisibility: flattenHideData, sorting: sortData, pagination, + rowSelection, }, muiTableHeadProps: { sx: { diff --git a/src/core/components/PersianTextField.jsx b/src/core/components/PersianTextField.jsx index 286564f..1b2b490 100644 --- a/src/core/components/PersianTextField.jsx +++ b/src/core/components/PersianTextField.jsx @@ -3,11 +3,11 @@ import { TextField } from "@mui/material"; import { useRef } from "react"; const PersianTextField = (props) => { - const { fieldOnChange, ...rest } = props; + const { onChange, ...rest } = props; const inputRef = useRef(null); const handleChange = (value) => { - fieldOnChange(value); + onChange(value); }; usePersianInput(inputRef, handleChange); diff --git a/src/core/utils/errorResponse.js b/src/core/utils/errorResponse.js index 5de1e77..2a147ed 100644 --- a/src/core/utils/errorResponse.js +++ b/src/core/utils/errorResponse.js @@ -56,7 +56,7 @@ const errorClient = (response, notification, toastContainer, logout) => { }; export const errorResponse = (response, notification, toastContainer, logout) => { - if (notification) toast.dismiss({ container: toastContainer }); + if (notification) toast.dismiss({ containerId: toastContainer }); if (isServerError(response.status)) { errorServer(response, notification, toastContainer); } else if (isClientError(response.status)) { diff --git a/src/core/utils/pageMenu.js b/src/core/utils/pageMenu.js index 1811e60..3465345 100644 --- a/src/core/utils/pageMenu.js +++ b/src/core/utils/pageMenu.js @@ -17,6 +17,7 @@ import SpeedIcon from "@mui/icons-material/Speed"; import EngineeringIcon from "@mui/icons-material/Engineering"; import AssessmentIcon from "@mui/icons-material/Assessment"; import AssignmentLateIcon from "@mui/icons-material/AssignmentLate"; +import LockPersonIcon from "@mui/icons-material/LockPerson"; import LineAxisIcon from "@mui/icons-material/LineAxis"; import ScienceIcon from "@mui/icons-material/Science"; import DriveEtaIcon from "@mui/icons-material/DriveEta"; @@ -94,7 +95,7 @@ export const pageMenu = [ type: "menu", icon: , hasSubitems: true, - badges: ["road_items.total"], + badges: ["roadItem.total"], Subitems: [ { id: "roadItemManagmentSupervisor", @@ -102,7 +103,7 @@ export const pageMenu = [ type: "menu", icon: , hasSubitems: true, - badges: ["road_items.supervise_cnt"], + badges: ["roadItem.supervise_cnt"], Subitems: [ { id: "roadItemManagmentSupervisorCartable", @@ -122,7 +123,7 @@ export const pageMenu = [ type: "menu", icon: , hasSubitems: true, - badges: ["road_items.operation_cnt"], + badges: ["roadItem.operation_cnt"], Subitems: [ { id: "roadItemManagmentOparationCartable", @@ -184,7 +185,6 @@ export const pageMenu = [ type: "menu", icon: , hasSubitems: true, - badges: ["road_patrols.total"], Subitems: [ { id: "roadPatrolManagmentSupervisor", @@ -192,7 +192,6 @@ export const pageMenu = [ type: "menu", icon: , hasSubitems: true, - badges: ["road_patrols.supervise_cnt"], Subitems: [ { id: "roadPatrolManagmentSupervisorCartable", @@ -212,7 +211,6 @@ export const pageMenu = [ type: "menu", icon: , hasSubitems: true, - badges: ["road_patrols.operation_cnt"], Subitems: [ { id: "roadPatrolManagmentOparationCartable", @@ -292,7 +290,7 @@ export const pageMenu = [ type: "menu", icon: , hasSubitems: true, - badges: ["safety_and_privacy.step_one", "safety_and_privacy.step_two"], + badges: ["safetyAndPrivacy.step_one", "safetyAndPrivacy.step_two"], Subitems: [ { id: "safetyAndPrivacyManagmentOparation", @@ -301,18 +299,11 @@ export const pageMenu = [ icon: , hasSubitems: true, Subitems: [ - { - id: "safetyAndPrivacyManagmentOparationCreate", - label: "ثبت فعالیت", - type: "page", - route: process.env.NEXT_PUBLIC_API_URL + "/v2/safety_and_privacy/operator/first_step", - permissions: ["add-safety-and-privacy"], - }, { id: "safetyAndPrivacyManagmentOparationCartable", label: "کارتابل", type: "page", - route: process.env.NEXT_PUBLIC_API_URL + "/v2/safety_and_privacy/operator/cartable", + route: "/dashboard/road-safety/operator", permissions: [ "show-safety-and-privacy-operator-cartable", "show-safety-and-privacy-operator-cartable-province", @@ -331,20 +322,18 @@ export const pageMenu = [ "show-safety-and-privacy-operator-cartable", "show-safety-and-privacy-operator-cartable-province", "show-safety-and-privacy-operator-cartable-edarate-shahri", - "add-safety-and-privacy", ], }, { id: "safetyAndPrivacyManagmentReport", label: "گزارش ها", type: "page", - route: process.env.NEXT_PUBLIC_API_URL + "/v2/safety_and_privacy/report", + route: "/dashboard/road-safety/report", icon: , permissions: [ "show-safety-and-privacy-operator-cartable", "show-safety-and-privacy-operator-cartable-province", "show-safety-and-privacy-operator-cartable-edarate-shahri", - "add-safety-and-privacy", ], }, ], @@ -355,7 +344,7 @@ export const pageMenu = [ type: "menu", icon: , hasSubitems: true, - badges: ["road_observations.total"], + badges: ["roadObserved.total"], Subitems: [ { id: "roadObservationsManagmentSupervisor", @@ -363,7 +352,7 @@ export const pageMenu = [ type: "menu", icon: , hasSubitems: true, - badges: ["road_observations.supervise_cnt"], + badges: ["roadObserved.supervise_cnt", "roadObserved.complaint_cnt"], Subitems: [ { id: "roadObservationsManagmentSupervisorCartable", @@ -380,7 +369,7 @@ export const pageMenu = [ type: "menu", icon: , hasSubitems: true, - badges: ["road_observations.operation_cnt"], + badges: ["roadObserved.operation_cnt", "roadObserved.complaint_cnt"], Subitems: [ { id: "roadObservationsManagmentOparationCartable", @@ -499,6 +488,22 @@ export const pageMenu = [ icon: , permissions: ["azmayesh-type-management"], }, + { + id: "permissionItem", + label: "سطح دسترسی ها", + type: "page", + route: "/dashboard/permissions", + icon: , + permissions: ["manage-permissions"], + }, + { + id: "userActivities", + label: "انواع فعالیت کاربران", + type: "page", + route: "/dashboard/user-activities", + icon: , + permissions: ["manage-log-list"], + }, { id: "CarDetails", label: "اطلاعات خودرو", diff --git a/src/core/utils/routes.js b/src/core/utils/routes.js index 6014c93..4953100 100644 --- a/src/core/utils/routes.js +++ b/src/core/utils/routes.js @@ -6,7 +6,7 @@ export const UPDATE_USER_ROUTE = api + "/api/v3/profile/edit"; export const CHANGE_USER_PASSWORD = api + "/api/v3/profile/change_password"; export const GET_LOGIN_ROUTE = api + "/login_dev"; export const GET_PERMISSIONS_ROUTE = api + "/webapi/user/get-permission"; -export const GET_SIDEBAR_BADGE_ROUTE = api + "/v2/activity_statistics"; +export const GET_SIDEBAR_BADGE_ROUTE = api + "/api/v3/notifications"; export const REFER_ADMIN_PROVINCE = "/v3/api/fake-submit"; export const REFER_ADMIN_CITY = "/v3/api/fake-submit"; export const GET_CITY_LISTS = "/v3/api/fake-cities"; @@ -41,7 +41,7 @@ export const GET_ROAD_PATROL_OPERATOR_REPORT = api + "/v2/road_patrols/operator/ export const GET_ROAD_PATROL_SUPERVISOR_REPORT = api + "/v2/road_patrols/operator/report"; export const CREATE_PATROL = api + "/api/v3/road_patrols/store"; export const GET_FMS_DATA = api + "/api/v3/fms_vehicle/get_activity"; -export const GET_OTP_TOKEN = api + "/v2/get_otp_token"; +export const GET_OTP_TOKEN = api + "/api/v3/otp/get_token"; export const GET_PROVINCE_ACTIVITY_REPORT = api + "/api/v3/road_patrol_reports/country_activity"; export const GET_CITY_ACTIVITY_REPORT = api + "/api/v3/road_patrol_reports/province_activity"; @@ -58,8 +58,8 @@ export const EXPORT_PROVINCE_ROAD_ITEM_REPORTS_PER_SUB_ITEM = api + "/api/v3/road_item_reports/province_activity_excel_per_sub_item"; export const EXPORT_COUNTRY_ROAD_ITEM_REPORTS_PER_SUB_ITEM = api + "/api/v3/road_item_reports/country_activity_excel_per_sub_item"; -export const GET_ROAD_ITEMS_ITEM = api + "/v2/items"; -export const GET_ROAD_ITEMS_SUB_ITEM = api + "/v2/sub_items"; +export const GET_ROAD_ITEMS_ITEM = api + "/api/v3/items"; +export const GET_ROAD_ITEMS_SUB_ITEM = api + "/api/v3/sub_items"; export const GET_EDARAT_LISTS = api + "/public/contents/edarate_shahri_by_province"; export const CREATE_ROAD_ITEMS = api + "/api/v3/road_items/store"; export const UPDATE_ROAD_ITEMS = api + "/api/v3/road_items/update"; @@ -127,3 +127,28 @@ export const UPDATE_FAST_REACT = api + "/api/v3/road_observations/modify_registr export const EXPORT_FAST_REACT_SUPERVISOR_LIST = api + "/api/v3/road_observations/supervisor_report"; export const EXPORT_FAST_REACT_OPERATOR_LIST = api + "/api/v3/road_observations/operator_report"; export const EXPORT_FAST_REACT_COMPLAINT_LIST = api + "/api/v3/road_observations/complaints_report"; + +// road safety +export const GET_SAFETY_AND_PRIVACY = api + "/api/v3/safety_and_privacy"; +export const DELETE_SAFETY_AND_PRIVACY = api + "/api/v3/safety_and_privacy"; +export const DESERIALIZE_JUDICIARY_DOCUMENT = api + "/api/v3/safety_and_privacy/deserialize"; +export const GET_SAFETY_AND_PRIVACY_ITEM = api + "/api/v3/safety_and_privacy/sub_items"; +export const FIRST_STEP_STORE = api + "/api/v3/safety_and_privacy/first_step_store"; +export const SECOND_STEP_STORE = api + "/api/v3/safety_and_privacy/second_step_store"; +export const THIRD_STEP_STORE = api + "/api/v3/safety_and_privacy/third_step_store"; +export const UPDATE_SAFETY_AND_PRIVACY = api + "/api/v3/safety_and_privacy"; +export const EXPORT_OPERATOR_ROAD_SAFETY = api + "/api/v3/safety_and_privacy/excel_report"; +export const GET_ROAD_SAFETY_PROVINCE_ACTIVITY_REPORT = api + "/api/v3/safety_and_privacy_report/country_activity"; +export const GET_ROAD_SAFETY_CITY_ACTIVITY_REPORT = api + "/api/v3/safety_and_privacy_report/province_activity"; + +// permission table +export const GET_PERMISSION_TABLE_LIST = api + "/api/v3/permissions"; +export const DELETE_PERMISSION = api + "/api/v3/permissions"; +export const UPDATE_PERMISSION = api + "/api/v3/permissions"; +export const CREATE_PERMISSION = api + "/api/v3/permissions"; + +// user activities +export const GET_USER_ACTIVITIES_LIST = api + "/api/v3/log_list"; +export const CREATE_USER_ACTIVITY = api + "/api/v3/log_list"; +export const UPDATE_USER_ACTIVITY = api + "/api/v3/log_list"; +export const DELETE_USER_ACTIVITIES = api + "/api/v3/log_list"; diff --git a/src/core/utils/successRequest.js b/src/core/utils/successRequest.js index b06d83d..7fbde71 100644 --- a/src/core/utils/successRequest.js +++ b/src/core/utils/successRequest.js @@ -4,7 +4,7 @@ import { successToast } from "@/core/components/Toasts/success"; export const successRequest = (notification, toastContainer) => { if (notification) { - toast.dismiss({ container: toastContainer }); + toast.dismiss({ containerId: toastContainer }); successToast(toastContainer); } }; diff --git a/src/lib/hooks/useSafetyAndPrivacyGetItems.js b/src/lib/hooks/useSafetyAndPrivacyGetItems.js new file mode 100644 index 0000000..d97dbbf --- /dev/null +++ b/src/lib/hooks/useSafetyAndPrivacyGetItems.js @@ -0,0 +1,30 @@ +import { useEffect, useState } from "react"; +import useRequest from "@/lib/hooks/useRequest"; +import { GET_SAFETY_AND_PRIVACY_ITEM } from "@/core/utils/routes"; + +const useSafetyAndPrivacyGetItems = () => { + const requestServer = useRequest(); + const [itemsList, setItemsList] = useState([]); + const [loadingItemsList, setLoadingItemsList] = useState(true); + const [errorItemsList, setErrorItemsList] = useState(null); + + useEffect(() => { + const fetchItems = async () => { + try { + const response = await requestServer(`${GET_SAFETY_AND_PRIVACY_ITEM}`); + setItemsList(response.data.data); + setLoadingItemsList(false); + setErrorItemsList(false); + } catch (e) { + setErrorItemsList(e); + setLoadingItemsList(false); + } + }; + + fetchItems(); + }, []); + + return { itemsList, loadingItemsList, errorItemsList }; +}; + +export default useSafetyAndPrivacyGetItems; diff --git a/src/lib/hooks/useSidebarBadge.js b/src/lib/hooks/useSidebarBadge.js index 29e5fed..994cf21 100644 --- a/src/lib/hooks/useSidebarBadge.js +++ b/src/lib/hooks/useSidebarBadge.js @@ -8,7 +8,7 @@ export const useSidebarBadge = () => { const fetcher = async (url) => { try { const response = await request(url); - return response.data; + return response.data.data; } catch (error) { throw new Error(); }