diff --git a/src/components/dashboard/azmayesh/Actions/Create/index.jsx b/src/components/dashboard/azmayesh/Actions/Create/index.jsx index 88de5f6..54e65db 100644 --- a/src/components/dashboard/azmayesh/Actions/Create/index.jsx +++ b/src/components/dashboard/azmayesh/Actions/Create/index.jsx @@ -4,7 +4,7 @@ import { Button, IconButton, useMediaQuery } from "@mui/material"; import { useTheme } from "@emotion/react"; import { useState } from "react"; import { AddCircle } from "@mui/icons-material"; -import CreateDialog from "./CreateDialog"; +import CandUAzmayesh from "@/components/dashboard/azmayesh/Forms/CandUAzmayesh"; const AzmayeshCreate = ({ mutate }) => { const theme = useTheme(); @@ -26,7 +26,7 @@ const AzmayeshCreate = ({ mutate }) => { ثبت آزمایش )} - {open && } + {open && } ); }; diff --git a/src/components/dashboard/azmayesh/AzmayeshList.jsx b/src/components/dashboard/azmayesh/AzmayeshList.jsx index f9b30c5..d411e4e 100644 --- a/src/components/dashboard/azmayesh/AzmayeshList.jsx +++ b/src/components/dashboard/azmayesh/AzmayeshList.jsx @@ -5,8 +5,9 @@ import { Box, Typography } from "@mui/material"; import DataTableWithAuth from "@/core/components/DataTableWithAuth"; import Toolbar from "./Toolbar"; import { GET_AZMAYESH_LIST } from "@/core/utils/routes"; -import moment from "jalali-moment"; import ShowLocation from "./ShowLocation"; +import moment from "jalali-moment"; +import RowActions from "./RowActions"; const AzmayeshList = () => { const columns = useMemo( @@ -101,7 +102,7 @@ const AzmayeshList = () => { filterFn: "equals", Cell: ({ renderedCellValue }) => ( - {moment(renderedCellValue).locale("fa").format("YYYY/MM/DD")} + {renderedCellValue ? moment(renderedCellValue).locale("fa").format("YYYY/MM/DD") : "-"} ), }, @@ -114,7 +115,7 @@ const AzmayeshList = () => { filterFn: "equals", Cell: ({ renderedCellValue }) => ( - {moment(renderedCellValue).locale("fa").format("YYYY/MM/DD")} + {renderedCellValue ? moment(renderedCellValue).locale("fa").format("YYYY/MM/DD") : "-"} ), }, @@ -133,6 +134,9 @@ const AzmayeshList = () => { page_name={"azmayesh"} table_name={"azmayeshList"} TableToolbar={Toolbar} + enableRowActions + positionActionsColumn={"last"} + RowActions={RowActions} /> diff --git a/src/components/dashboard/azmayesh/Actions/Create/CreateDialog/ChooseLocation.jsx b/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUChooseLocation.jsx similarity index 98% rename from src/components/dashboard/azmayesh/Actions/Create/CreateDialog/ChooseLocation.jsx rename to src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUChooseLocation.jsx index 4986e19..469b1f5 100644 --- a/src/components/dashboard/azmayesh/Actions/Create/CreateDialog/ChooseLocation.jsx +++ b/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUChooseLocation.jsx @@ -21,7 +21,7 @@ import VerifiedIcon from "@mui/icons-material/Verified"; import EditIcon from "@mui/icons-material/Edit"; import { useTheme } from "@emotion/react"; -const ChooseLocation = ({ mapBoxData, setMapBoxData }) => { +const CandUChooseLocation = ({ mapBoxData, setMapBoxData }) => { const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down("sm")); @@ -177,4 +177,4 @@ const ChooseLocation = ({ mapBoxData, setMapBoxData }) => { ); }; -export default ChooseLocation; +export default CandUChooseLocation; diff --git a/src/components/dashboard/azmayesh/Actions/Create/CreateDialog/AzmayeshGeneralInfo.jsx b/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUGeneralInfo.jsx similarity index 98% rename from src/components/dashboard/azmayesh/Actions/Create/CreateDialog/AzmayeshGeneralInfo.jsx rename to src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUGeneralInfo.jsx index e5b160a..24f4493 100644 --- a/src/components/dashboard/azmayesh/Actions/Create/CreateDialog/AzmayeshGeneralInfo.jsx +++ b/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUGeneralInfo.jsx @@ -22,7 +22,7 @@ import { faIR } from "@mui/x-date-pickers/locales"; import ClearIcon from "@mui/icons-material/Clear"; import React from "react"; -const AzmayeshGeneralInfo = ({ control, register, setValue, errors }) => { +const CandUGeneralInfo = ({ control, register, setValue, errors }) => { const { azmayeshes, errorAzmayeshes, loadingAzmayeshes } = useAzmayesh(); const { provinces, errorProvinces, loadingProvinces } = useProvinces(); @@ -98,11 +98,11 @@ const AzmayeshGeneralInfo = ({ control, register, setValue, errors }) => { value={provinces.find((province) => province.id === value) || null} disablePortal options={provinces} - getOptionLabel={(province) => province.name} + getOptionLabel={(province) => province.name_fa} isOptionEqualToValue={(option, value) => option.id === value?.id} onChange={(event, newValue) => { onChange(newValue ? newValue.id : ""); - setValue("province_name", newValue ? newValue.name : ""); + setValue("province_name", newValue ? newValue.name_fa : ""); }} renderInput={(params) => ( { ( { ( { ); }; -export default AzmayeshGeneralInfo; +export default CandUGeneralInfo; diff --git a/src/components/dashboard/azmayesh/Actions/Create/CreateDialog/MapBox.jsx b/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUMapBox.jsx similarity index 80% rename from src/components/dashboard/azmayesh/Actions/Create/CreateDialog/MapBox.jsx rename to src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUMapBox.jsx index a09e986..1907436 100644 --- a/src/components/dashboard/azmayesh/Actions/Create/CreateDialog/MapBox.jsx +++ b/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUMapBox.jsx @@ -3,14 +3,14 @@ import { Box, Stack } from "@mui/material"; import dynamic from "next/dynamic"; import MapLoading from "@/core/components/MapLayer/Loading"; -import ChooseLocation from "./ChooseLocation"; +import CandUChooseLocation from "./CandUChooseLocation"; const MapLayer = dynamic(() => import("@/core/components/MapLayer"), { loading: () => , ssr: false, }); -const MapBox = ({ mapBoxData, setMapBoxData }) => { +const CandUMapBox = ({ mapBoxData, setMapBoxData }) => { return ( { }} > - + ); }; -export default MapBox; +export default CandUMapBox; diff --git a/src/components/dashboard/azmayesh/Actions/Create/CreateDialog/CreateTimeLine.jsx b/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUTimeLine.jsx similarity index 96% rename from src/components/dashboard/azmayesh/Actions/Create/CreateDialog/CreateTimeLine.jsx rename to src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUTimeLine.jsx index 61ab92c..bcf43b3 100644 --- a/src/components/dashboard/azmayesh/Actions/Create/CreateDialog/CreateTimeLine.jsx +++ b/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/CandUTimeLine.jsx @@ -13,7 +13,7 @@ import { TimelineSeparator, } from "@mui/lab"; -const CreateTimeLine = ({ tabState }) => { +const CandUCreateTimeLine = ({ tabState }) => { return ( { ); }; -export default CreateTimeLine; +export default CandUCreateTimeLine; diff --git a/src/components/dashboard/azmayesh/Actions/Create/CreateDialog/index.jsx b/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/index.jsx similarity index 64% rename from src/components/dashboard/azmayesh/Actions/Create/CreateDialog/index.jsx rename to src/components/dashboard/azmayesh/Forms/CandUAzmayesh/index.jsx index 425725d..8f145d2 100644 --- a/src/components/dashboard/azmayesh/Actions/Create/CreateDialog/index.jsx +++ b/src/components/dashboard/azmayesh/Forms/CandUAzmayesh/index.jsx @@ -1,24 +1,24 @@ "use client"; import { Box, Button, Dialog, DialogActions, DialogContent, Tab, Tabs, useMediaQuery } from "@mui/material"; -import { useTheme } from "@emotion/react"; import React, { useState } from "react"; -import MapBox from "./MapBox"; -import TravelExploreIcon from "@mui/icons-material/TravelExplore"; -import TextSnippetIcon from "@mui/icons-material/TextSnippet"; -import KeyboardDoubleArrowRightIcon from "@mui/icons-material/KeyboardDoubleArrowRight"; -import KeyboardDoubleArrowLeftIcon from "@mui/icons-material/KeyboardDoubleArrowLeft"; -import ExitToAppIcon from "@mui/icons-material/ExitToApp"; -import BeenhereIcon from "@mui/icons-material/Beenhere"; -import CreateTimeLine from "./CreateTimeLine"; -import { useForm } from "react-hook-form"; -import StyledForm from "@/core/components/StyledForm"; -import { object, string } from "yup"; +import { useTheme } from "@emotion/react"; import useRequest from "@/lib/hooks/useRequest"; +import { object, string } from "yup"; +import { useForm } from "react-hook-form"; import { yupResolver } from "@hookform/resolvers/yup"; import moment from "jalali-moment"; -import { POST_AZMAYESH } from "@/core/utils/routes"; -import AzmayeshGeneralInfo from "./AzmayeshGeneralInfo"; +import { CREATE_AZMAYESH, UPDATE_AZMAYESH } from "@/core/utils/routes"; +import StyledForm from "@/core/components/StyledForm"; +import TravelExploreIcon from "@mui/icons-material/TravelExplore"; +import TextSnippetIcon from "@mui/icons-material/TextSnippet"; +import ExitToAppIcon from "@mui/icons-material/ExitToApp"; +import KeyboardDoubleArrowRightIcon from "@mui/icons-material/KeyboardDoubleArrowRight"; +import KeyboardDoubleArrowLeftIcon from "@mui/icons-material/KeyboardDoubleArrowLeft"; +import BeenhereIcon from "@mui/icons-material/Beenhere"; +import CandUMapBox from "./CandUMapBox"; +import CandUCreateTimeLine from "./CandUTimeLine"; +import CandUGeneralInfo from "./CandUGeneralInfo"; function TabPanel(props) { const { children, value, index } = props; @@ -30,11 +30,26 @@ function TabPanel(props) { ); } -const CreateDialog = ({ open, setOpen, mutate }) => { +const validationSchema = object({ + azmayesh_type_id: string().required("نوع آزمایش را مشخص کنید!"), + province_id: string().required("استان را وارد کنید!"), + project_name: string().required("عنوان پروژه را وارد کنید!"), + employer: string().required("کارفرما را وارد کنید!"), + consultant: string().required("مشاور را وارد کنید!"), + contractor: string().required("پیمانکار را وارد کنید!"), + applicant: string().required("متقاضی را وارد کنید!"), + work_number: string().required("شماره کار را وارد کنید!"), + request_number: string().required("شماره درخواست را وارد کنید!"), + request_date: string().required("تاریخ درخواست را وارد کنید!"), + report_date: string().required("تاریخ گزارش را وارد کنید!"), +}); + +const CandUAzmayesh = ({ open, setOpen, mutate, updateInfo, rowId }) => { const theme = useTheme(); + const requestServer = useRequest({ auth: true }); const isMobile = useMediaQuery(theme.breakpoints.down("sm")); const [tabState, setTabState] = useState(0); - const [mapBoxData, setMapBoxData] = useState(null); + const [mapBoxData, setMapBoxData] = useState(updateInfo ? { lat: updateInfo.lat, lng: updateInfo.lng } : null); const handleClose = () => { setOpen(false); @@ -52,35 +67,20 @@ const CreateDialog = ({ open, setOpen, mutate }) => { } }; - const validationSchema = object({ - azmayesh_type_id: string().required("نوع آزمایش را مشخص کنید!"), - province_id: string().required("استان را وارد کنید!"), - project_name: string().required("عنوان پروژه را وارد کنید!"), - employer: string().required("کارفرما را وارد کنید!"), - consultant: string().required("مشاور را وارد کنید!"), - contractor: string().required("پیمانکار را وارد کنید!"), - applicant: string().required("متقاضی را وارد کنید!"), - work_number: string().required("شماره کار را وارد کنید!"), - request_number: string().required("شماره درخواست را وارد کنید!"), - request_date: string().required("تاریخ درخواست را وارد کنید!"), - report_date: string().required("تاریخ گزارش را وارد کنید!"), - }); - const requestServer = useRequest({ auth: true }); - const defaultValues = { - azmayesh_type_id: "", - azmayesh_type_name: "", - province_id: "", - province_name: "", - project_name: "", - employer: "", - consultant: "", - contractor: "", - applicant: "", - work_number: "", - request_number: "", - request_date: "", - report_date: "", + azmayesh_type_id: updateInfo ? updateInfo.azmayesh_type_id : "", + azmayesh_type_name: updateInfo ? updateInfo.azmayesh_type_name : "", + province_id: updateInfo ? updateInfo.province_id : "", + province_name: updateInfo ? updateInfo.province_name : "", + project_name: updateInfo ? updateInfo.project_name : "", + employer: updateInfo ? updateInfo.employer : "", + consultant: updateInfo ? updateInfo.consultant : "", + contractor: updateInfo ? updateInfo.contractor : "", + applicant: updateInfo ? updateInfo.applicant : "", + work_number: updateInfo ? updateInfo.work_number : "", + request_number: updateInfo ? updateInfo.request_number : "", + request_date: updateInfo ? moment(updateInfo.request_date, "YYYY-MM-DD").toDate() : "", + report_date: updateInfo ? moment(updateInfo.report_date, "YYYY-MM-DD").toDate() : "", }; const { @@ -106,10 +106,10 @@ const CreateDialog = ({ open, setOpen, mutate }) => { formData.append("applicant", data.applicant); formData.append("work_number", data.work_number); formData.append("request_number", data.request_number); - formData.append("request_date", moment(data.request_date).format("YYYY-MM-DD")); - formData.append("report_date", moment(data.report_date).format("YYYY-MM-DD")); + formData.append("request_date", moment(new Date(data.request_date)).format("YYYY-MM-DD")); + formData.append("report_date", moment(new Date(data.report_date)).format("YYYY-MM-DD")); - requestServer(POST_AZMAYESH, "post", { + requestServer(updateInfo ? `${UPDATE_AZMAYESH}/${rowId}` : CREATE_AZMAYESH, "post", { data: formData, }) .then(() => { @@ -140,10 +140,10 @@ const CreateDialog = ({ open, setOpen, mutate }) => { - + - { {!isMobile && ( - + )} @@ -169,7 +169,10 @@ const CreateDialog = ({ open, setOpen, mutate }) => { {tabState === 0 ? ( )} @@ -193,4 +202,4 @@ const CreateDialog = ({ open, setOpen, mutate }) => { ); }; -export default CreateDialog; +export default CandUAzmayesh; diff --git a/src/components/dashboard/azmayesh/RowActions/AzmayeshUpdate/index.jsx b/src/components/dashboard/azmayesh/RowActions/AzmayeshUpdate/index.jsx new file mode 100644 index 0000000..c426685 --- /dev/null +++ b/src/components/dashboard/azmayesh/RowActions/AzmayeshUpdate/index.jsx @@ -0,0 +1,47 @@ +import { IconButton, Tooltip } from "@mui/material"; +import { useState } from "react"; +import useRequest from "@/lib/hooks/useRequest"; +import EditIcon from "@mui/icons-material/Edit"; +import { GET_AZMAYESH_LIST } from "@/core/utils/routes"; +import CandUAzmayesh from "@/components/dashboard/azmayesh/Forms/CandUAzmayesh"; + +const AzmayeshUpdate = ({ rowId, mutate }) => { + const requestServer = useRequest({ auth: true }); + const [openUpdateDialog, setOpenUpdateDialog] = useState(false); + const [updateInfo, setUpdateInfo] = useState(null); + + const handleGetInfo = () => { + requestServer(`${GET_AZMAYESH_LIST}/${rowId}`, "get") + .then((response) => { + setUpdateInfo(response.data.data); + }) + .catch(() => {}) + .finally(() => { + setOpenUpdateDialog(true); + }); + }; + + return ( + <> + + + + + + {openUpdateDialog && ( + + )} + + ); +}; +export default AzmayeshUpdate; diff --git a/src/components/dashboard/azmayesh/RowActions/DeleteAzmayesh/index.jsx b/src/components/dashboard/azmayesh/RowActions/DeleteAzmayesh/index.jsx new file mode 100644 index 0000000..c424e8e --- /dev/null +++ b/src/components/dashboard/azmayesh/RowActions/DeleteAzmayesh/index.jsx @@ -0,0 +1,78 @@ +import { + Button, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + IconButton, + Tooltip, + Typography, +} from "@mui/material"; +import { useState } from "react"; +import useRequest from "@/lib/hooks/useRequest"; +import DeleteIcon from "@mui/icons-material/Delete"; +import { DELETE_AZMAYESH } from "@/core/utils/routes"; + +const DeleteAzmayesh = ({ rowId, mutate }) => { + const requestServer = useRequest({ auth: true }); + const [openDeleteDialog, setOpenDeleteDialog] = useState(false); + const [isSubmitting, setIsSubmitting] = useState(false); + + const handleSubmit = () => { + setIsSubmitting(true); + requestServer(`${DELETE_AZMAYESH}/${rowId}`, "post") + .then(() => { + setOpenDeleteDialog(false); + mutate(); + }) + .catch(() => {}) + .finally(() => { + setIsSubmitting(false); + }); + }; + + return ( + <> + + { + setOpenDeleteDialog(true); + }} + > + + + + + حذف آزمایش + + آیا از حذف این آزمایش مطمئن هستید؟ + + + + + + + + ); +}; +export default DeleteAzmayesh; diff --git a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Actions/Create/index.jsx b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Actions/Create/index.jsx new file mode 100644 index 0000000..3cecfb6 --- /dev/null +++ b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Actions/Create/index.jsx @@ -0,0 +1,59 @@ +import { Button, IconButton, useMediaQuery } from "@mui/material"; +import useRequest from "@/lib/hooks/useRequest"; +import { useEffect, useState } from "react"; +import { GET_AZMAYESH_SAMPLE_FIELDS } from "@/core/utils/routes"; +import { AddCircle } from "@mui/icons-material"; +import { useTheme } from "@emotion/react"; +import CandUSampleOfAzmayesh from "@/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Forms/CandUSampleOfAzmayesh"; + +const AddSampleToAzmayesh = ({ azmayeshTypeId, mutate, rowId }) => { + const requestServer = useRequest({ auth: true }); + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down("sm")); + const [sampleInfo, setSampleInfo] = useState(null); + const [openAddSampleDialog, setOpenAddSampleDialog] = useState(false); + const [defaultValues, setDefaultValues] = useState({}); + + const handleGetFields = () => { + requestServer(`${GET_AZMAYESH_SAMPLE_FIELDS}/${azmayeshTypeId}`, "get") + .then((response) => { + setSampleInfo(response.data.data); + }) + .catch(() => {}) + .finally(() => { + setOpenAddSampleDialog(true); + }); + }; + + useEffect(() => { + const initialValues = sampleInfo?.reduce((acc, item) => { + acc[item.id] = ""; + return acc; + }, {}); + setDefaultValues(initialValues); + }, [sampleInfo]); + + return ( + <> + {isMobile ? ( + + + + ) : ( + + )} + + + ); +}; +export default AddSampleToAzmayesh; diff --git a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/AzmayeshInfo.jsx b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/AzmayeshInfo.jsx new file mode 100644 index 0000000..e33593c --- /dev/null +++ b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/AzmayeshInfo.jsx @@ -0,0 +1,82 @@ +"use client"; + +import { Box, Chip, Divider, Grid, Stack, Typography } from "@mui/material"; +import ScienceIcon from "@mui/icons-material/Science"; +import LocationCityIcon from "@mui/icons-material/LocationCity"; + +const AzmayeshInfo = ({ rowData }) => { + return ( + + + {rowData.project_name} + + + + + } + label={ + + نوع آزمایش + + } + /> + + + + {rowData.azmayesh_type_name} + + + + + } + label={ + + نام استان + + } + /> + + + + {rowData.province_name} + + + + + } + label={ + + شماره کار + + } + /> + + + + {rowData.work_number} + + + + + } + label={ + + شماره درخواست + + } + /> + + + + {rowData.request_number} + + + + + ); +}; +export default AzmayeshInfo; diff --git a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Forms/CandUSampleOfAzmayesh/index.jsx b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Forms/CandUSampleOfAzmayesh/index.jsx new file mode 100644 index 0000000..7709eda --- /dev/null +++ b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Forms/CandUSampleOfAzmayesh/index.jsx @@ -0,0 +1,74 @@ +import { Button, Dialog, DialogActions, DialogContent, DialogTitle } from "@mui/material"; +import useRequest from "@/lib/hooks/useRequest"; +import React, { useState } from "react"; +import { ADD_SAMPLE_TO_AZMAYESH, UPDATE_SAMPLE_OF_AZMAYESH } from "@/core/utils/routes"; +import FormMaker from "@/core/components/FormMaker"; +import { DialogHeader } from "next/dist/client/components/react-dev-overlay/internal/components/Dialog"; + +const CandUSampleOfAzmayesh = ({ + sampleInfo, + mutate, + rowId, + openSampleDialog, + setOpenSampleDialog, + defaultValues, + setDefaultValues, + isUpdate, + azmayesh_id, +}) => { + const requestServer = useRequest({ auth: true }); + const [isSubmitting, setIsSubmitting] = useState(false); + + const handleSubmit = () => { + const data = {}; + setIsSubmitting(true); + const formData = new FormData(); + formData.append("azmayesh_id", isUpdate ? azmayesh_id : rowId); + Object.entries(defaultValues).forEach(([key, value]) => { + data[key] = value; + }); + formData.append("data", JSON.stringify(data)); + requestServer(isUpdate ? `${UPDATE_SAMPLE_OF_AZMAYESH}/${rowId}` : `${ADD_SAMPLE_TO_AZMAYESH}`, "post", { + data: formData, + }) + .then(() => { + mutate(); + }) + .catch(() => {}) + .finally(() => { + setOpenSampleDialog(false); + setIsSubmitting(false); + }); + }; + + return ( + + + {isUpdate ? "ویرایش نمونه" : "افزودن نمونه"} + + + + + + + + + + ); +}; +export default CandUSampleOfAzmayesh; diff --git a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/RowActions/DeleteSample.jsx b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/RowActions/DeleteSample.jsx new file mode 100644 index 0000000..477afeb --- /dev/null +++ b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/RowActions/DeleteSample.jsx @@ -0,0 +1,78 @@ +import { + Button, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + IconButton, + Tooltip, + Typography, +} from "@mui/material"; +import { useState } from "react"; +import useRequest from "@/lib/hooks/useRequest"; +import DeleteIcon from "@mui/icons-material/Delete"; +import { DELETE_SAMPLE_LIST } from "@/core/utils/routes"; + +const DeleteSample = ({ rowId, mutate }) => { + const requestServer = useRequest({ auth: true }); + const [openDeleteDialog, setOpenDeleteDialog] = useState(false); + const [isSubmitting, setIsSubmitting] = useState(false); + + const handleSubmit = () => { + setIsSubmitting(true); + requestServer(`${DELETE_SAMPLE_LIST}/${rowId}`, "post") + .then(() => { + setOpenDeleteDialog(false); + mutate(); + }) + .catch(() => {}) + .finally(() => { + setIsSubmitting(false); + }); + }; + + return ( + <> + + { + setOpenDeleteDialog(true); + }} + > + + + + + حذف نمونه + + آیا از حذف این نمونه مطمئن هستید؟ + + + + + + + + ); +}; +export default DeleteSample; diff --git a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/RowActions/UpdateSample.jsx b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/RowActions/UpdateSample.jsx new file mode 100644 index 0000000..f16253a --- /dev/null +++ b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/RowActions/UpdateSample.jsx @@ -0,0 +1,60 @@ +import { IconButton, Tooltip } from "@mui/material"; +import useRequest from "@/lib/hooks/useRequest"; +import { useEffect, useState } from "react"; +import { GET_AZMAYESH_SAMPLE_FIELDS, GET_SAMPLE_LIST } from "@/core/utils/routes"; +import CandUSampleOfAzmayesh from "@/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Forms/CandUSampleOfAzmayesh"; +import EditIcon from "@mui/icons-material/Edit"; + +const UpdateSample = ({ azmayeshTypeId, mutate, rowId, azmayesh_id }) => { + const requestServer = useRequest({ auth: true }); + const [sampleInfo, setSampleInfo] = useState(null); + const [openUpdateSampleDialog, setOpenUpdateSampleDialog] = useState(false); + const [defaultValues, setDefaultValues] = useState({}); + const [sampleDetail, setSampleDetail] = useState({}); + + const handleGetFields = () => { + requestServer(`${GET_AZMAYESH_SAMPLE_FIELDS}/${azmayeshTypeId}`, "get") + .then((response) => { + setSampleInfo(response.data.data); + }) + .catch(() => {}); + requestServer(`${GET_SAMPLE_LIST}/${rowId}`, "get") + .then((response) => { + setSampleDetail(JSON.parse(response.data.data.data)); + }) + .catch(() => {}) + .finally(() => { + setOpenUpdateSampleDialog(true); + }); + }; + + useEffect(() => { + setDefaultValues(sampleDetail); + }, [sampleDetail]); + + return ( + <> + + + + + + + + ); +}; +export default UpdateSample; diff --git a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/RowActions/index.jsx b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/RowActions/index.jsx new file mode 100644 index 0000000..5770586 --- /dev/null +++ b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/RowActions/index.jsx @@ -0,0 +1,18 @@ +import { Box } from "@mui/material"; +import DeleteSample from "./DeleteSample"; +import UpdateSample from "./UpdateSample"; + +const RowActions = ({ rowData, row, mutate }) => { + return ( + + + + + ); +}; +export default RowActions; diff --git a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/ShowSampleList.jsx b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/ShowSampleList.jsx new file mode 100644 index 0000000..4d4bea7 --- /dev/null +++ b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/ShowSampleList.jsx @@ -0,0 +1,64 @@ +import { useMemo } from "react"; +import { Box } from "@mui/material"; +import DataTableWithAuth from "@/core/components/DataTableWithAuth"; +import { GET_SAMPLE_LIST } from "@/core/utils/routes"; +import RowActions from "./RowActions"; +import AzmayeshInfo from "@/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/AzmayeshInfo"; +import Toolbar from "./Toolbar"; + +const ShowSampleList = ({ sampleInfo, rowData }) => { + const parsedData = (data) => { + return data.data.map((item) => ({ + ...JSON.parse(item.data), + id: item.id, + })); + }; + + const columns = useMemo( + () => [ + { + accessorKey: "id", + header: "کد یکتا", + id: "id", + enableColumnFilter: false, + datatype: "text", + filterFn: "notEquals", + }, + ...sampleInfo.map((item) => ({ + accessorKey: item.id.toString(), + header: item.name, + id: item.id.toString(), + enableColumnFilter: false, + datatype: "text", + filterFn: "notEquals", + })), + ], + [sampleInfo] + ); + + const ToolbarWithRowData = (props) => ; + const RowActionsWithRowData = (props) => ; + + return ( + + + + + + + ); +}; + +export default ShowSampleList; diff --git a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Toolbar.jsx b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Toolbar.jsx new file mode 100644 index 0000000..53e3eb3 --- /dev/null +++ b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/Toolbar.jsx @@ -0,0 +1,10 @@ +import AddSampleToAzmayesh from "./Actions/Create"; + +const Toolbar = ({ mutate, rowData }) => { + return ( + <> + + + ); +}; +export default Toolbar; diff --git a/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/index.jsx b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/index.jsx new file mode 100644 index 0000000..1677d82 --- /dev/null +++ b/src/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh/index.jsx @@ -0,0 +1,46 @@ +import { Button, Dialog, DialogActions, DialogContent, IconButton, Tooltip } from "@mui/material"; +import AssignmentIcon from "@mui/icons-material/Assignment"; +import { useState } from "react"; +import ShowSampleList from "./ShowSampleList"; +import { GET_AZMAYESH_SAMPLE_FIELDS } from "@/core/utils/routes"; +import useRequest from "@/lib/hooks/useRequest"; + +const ShowSampleOfAzmayesh = ({ rowData }) => { + const requestServer = useRequest({ auth: true }); + const [openShowSampleDialog, setOpenShowSampleDialog] = useState(false); + const [sampleInfo, setSampleInfo] = useState(null); + const handleGetSampleFields = () => { + requestServer(`${GET_AZMAYESH_SAMPLE_FIELDS}/${rowData.azmayesh_type_id}`, "get") + .then((response) => { + setSampleInfo(response.data.data); + }) + .catch(() => {}) + .finally(() => { + setOpenShowSampleDialog(true); + }); + }; + return ( + <> + + + + + + + + + + + + + + + ); +}; +export default ShowSampleOfAzmayesh; diff --git a/src/components/dashboard/azmayesh/RowActions/index.jsx b/src/components/dashboard/azmayesh/RowActions/index.jsx new file mode 100644 index 0000000..19447cb --- /dev/null +++ b/src/components/dashboard/azmayesh/RowActions/index.jsx @@ -0,0 +1,15 @@ +import { Box } from "@mui/material"; +import DeleteAzmayesh from "./DeleteAzmayesh"; +import ShowSampleOfAzmayesh from "@/components/dashboard/azmayesh/RowActions/ShowSampleOfAzmayesh"; +import AzmayeshUpdate from "@/components/dashboard/azmayesh/RowActions/AzmayeshUpdate"; + +const RowActions = ({ row, mutate }) => { + return ( + + + + + + ); +}; +export default RowActions; diff --git a/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/Refer/ReferFormContext.jsx b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/Refer/ReferFormContext.jsx index 26f9bf8..e02512e 100644 --- a/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/Refer/ReferFormContext.jsx +++ b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/Refer/ReferFormContext.jsx @@ -100,7 +100,7 @@ const ReferFormContext = ({ setOpenReferDialog, rowId, mutate }) => { value={provinces.find((province) => province.id === value) || null} disablePortal options={provinces} - getOptionLabel={(province) => province.name} + getOptionLabel={(province) => province.name_fa} isOptionEqualToValue={(option, value) => option.id === value.id} onChange={(event, newValue) => { onChange(newValue ? newValue.id : ""); diff --git a/src/core/components/CustomDatePicker.jsx b/src/core/components/CustomDatePicker.jsx new file mode 100644 index 0000000..eb68fa7 --- /dev/null +++ b/src/core/components/CustomDatePicker.jsx @@ -0,0 +1,53 @@ +import React from "react"; +import { AdapterDateFnsJalali } from "@mui/x-date-pickers/AdapterDateFnsJalali"; +import { faIR } from "@mui/x-date-pickers/locales"; +import { LocalizationProvider, MobileDatePicker } from "@mui/x-date-pickers"; +import { IconButton, InputAdornment } from "@mui/material"; +import ClearIcon from "@mui/icons-material/Clear"; + +const CustomDatePicker = ({ dateValue, setDateValue, placeholder = "انتخاب تاریخ", size = "small" }) => { + const handleDateChange = (newValue) => { + setDateValue(newValue); + }; + + return ( + + + { + event.stopPropagation(); + setDateValue(null); + }} + sx={{ + color: "#bfbfbf", + "&:hover": { + backgroundColor: "rgba(189, 189, 189, 0.1)", + color: "#363434", + }, + }} + > + + + + ), + }, + }, + }} + > + + ); +}; +export default CustomDatePicker; diff --git a/src/core/components/DataTable/Main.js b/src/core/components/DataTable/Main.js index 5d0d98d..b94655e 100644 --- a/src/core/components/DataTable/Main.js +++ b/src/core/components/DataTable/Main.js @@ -22,6 +22,7 @@ const DataTable_Main = (props) => { TableToolbar, table_title, RowActions, + specific_data, } = props; const flatColumns = flattenArrayOfObjects(columns, "columns"); const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 }); @@ -50,7 +51,11 @@ const DataTable_Main = (props) => { const fetcher = async (url) => { try { const response = await request(url); - return response.data; + if (specific_data) { + return specific_data(response.data); + } else { + return response.data?.data; + } } catch (error) { throw error; } @@ -66,7 +71,7 @@ const DataTable_Main = (props) => { const table = useMaterialReactTable({ localization: FA_DATATABLE_LOCALIZATION, columns, - data: data?.data ?? [], + data: data ?? [], initialState: { density: "compact", columnVisibility: flattenHideData, diff --git a/src/core/components/DataTable/filter/FilterBody.jsx b/src/core/components/DataTable/filter/FilterBody.jsx index 11048c8..e03c752 100644 --- a/src/core/components/DataTable/filter/FilterBody.jsx +++ b/src/core/components/DataTable/filter/FilterBody.jsx @@ -81,7 +81,7 @@ function FilterBody({ columns, drawerState, setDrawerState, user_id, page_name, setDrawerState(false)} - sx={{ overflowY: "hidden", display: "flex", flexDirection: "column", height: "100%" }} + sx={{ overflowY: "hidden", display: "flex", flexDirection: "column", height: "100%", zIndex: "1300" }} > {Object.keys(initialValues).length > 0 && ( diff --git a/src/core/components/DataTable/hide/HideBody.jsx b/src/core/components/DataTable/hide/HideBody.jsx index c96e33f..8d34ea4 100644 --- a/src/core/components/DataTable/hide/HideBody.jsx +++ b/src/core/components/DataTable/hide/HideBody.jsx @@ -30,7 +30,7 @@ function HideBody({ columns, drawerState, setDrawerState }) { setDrawerState(false)} - sx={{ overflowY: "hidden", display: "flex", flexDirection: "column", height: "100%" }} + sx={{ overflowY: "hidden", display: "flex", flexDirection: "column", height: "100%", zIndex: "1300" }} > diff --git a/src/core/components/FormMaker/DateType.jsx b/src/core/components/FormMaker/DateType.jsx new file mode 100644 index 0000000..f928694 --- /dev/null +++ b/src/core/components/FormMaker/DateType.jsx @@ -0,0 +1,35 @@ +import { FormControl } from "@mui/material"; +import CustomDatePicker from "@/core/components/CustomDatePicker"; +import moment from "jalali-moment"; +import { useEffect, useState } from "react"; + +const DateType = ({ itemInfo, defaultValues, setDefaultValues }) => { + const [dateValue, setDateValue] = useState(null); + const handleDateChange = (newValue) => { + const date = new Date(newValue); + const formattedDate = moment(date).locale("fa").format("YYYY/MM/DD"); + setDefaultValues((prev) => ({ + ...prev, + [itemInfo.id]: newValue ? formattedDate : "", + })); + setDateValue(moment(date).format("YYYY/MM/DD")); + }; + + useEffect(() => { + if (defaultValues[itemInfo.id]) { + setDateValue(moment.from(defaultValues[itemInfo.id], "fa", "YYYY/MM/DD")); + } + }, []); + + return ( + + + + ); +}; + +export default DateType; diff --git a/src/core/components/FormMaker/InputType.jsx b/src/core/components/FormMaker/InputType.jsx new file mode 100644 index 0000000..0f36eb8 --- /dev/null +++ b/src/core/components/FormMaker/InputType.jsx @@ -0,0 +1,30 @@ +import { FormControl, InputLabel, OutlinedInput } from "@mui/material"; +import React from "react"; + +const InputType = ({ itemInfo, defaultValues, setDefaultValues }) => { + const handleChange = (event) => { + const { value } = event.target; + setDefaultValues((prevValues) => ({ + ...prevValues, + [itemInfo.id]: value, + })); + }; + + return ( + + {itemInfo.name} + + + ); +}; + +export default InputType; diff --git a/src/core/components/FormMaker/SelectType.jsx b/src/core/components/FormMaker/SelectType.jsx new file mode 100644 index 0000000..fe20940 --- /dev/null +++ b/src/core/components/FormMaker/SelectType.jsx @@ -0,0 +1,34 @@ +import { FormControl, InputLabel, MenuItem, Select } from "@mui/material"; +import React from "react"; + +const SelectType = ({ itemInfo, defaultValues, setDefaultValues }) => { + const handleChange = (event) => { + const newValue = event.target.value; + setDefaultValues((prev) => ({ + ...prev, + [itemInfo.id]: newValue, + })); + }; + + return ( + + {itemInfo.name} + + + ); +}; + +export default SelectType; diff --git a/src/core/components/FormMaker/index.jsx b/src/core/components/FormMaker/index.jsx new file mode 100644 index 0000000..2699eb6 --- /dev/null +++ b/src/core/components/FormMaker/index.jsx @@ -0,0 +1,33 @@ +import InputType from "./InputType"; +import SelectType from "./SelectType"; +import DateType from "./DateType"; +import { Grid } from "@mui/material"; + +const componentMap = { + input: InputType, + select: SelectType, + date: DateType, +}; + +const FormMaker = ({ formInfo, defaultValues, setDefaultValues }) => { + return ( + + {formInfo?.map((itemInfo) => { + const Component = componentMap[itemInfo.type] || null; + return ( + + {Component ? ( + + ) : null} + + ); + })} + + ); +}; + +export default FormMaker; diff --git a/src/core/utils/routes.js b/src/core/utils/routes.js index 4fcfff2..c507026 100644 --- a/src/core/utils/routes.js +++ b/src/core/utils/routes.js @@ -9,9 +9,16 @@ export const GET_SIDEBAR_BADGE_ROUTE = api + "/v2/activity_statistics"; 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"; -export const GET_PROVINCE_LISTS = "/v3/api/fake-provinces"; +export const GET_PROVINCE_LISTS = api + "/public/contents/provinces"; export const GET_PREV_STATE_OPINION = "/v3/api/fake-prev-state-opinion"; export const SUBMIT_ROAD_SAFETY_FORM = "/v3/api/fake-submit"; -export const POST_AZMAYESH = api + "/api/v3/azmayeshes/store"; +export const CREATE_AZMAYESH = api + "/api/v3/azmayeshes/store"; +export const UPDATE_AZMAYESH = api + "/api/v3/azmayeshes/update"; export const GET_AZMAYESH_TYPE_LIST = api + "/api/v3/azmayesh_types"; export const GET_AZMAYESH_LIST = api + "/api/v3/azmayeshes"; +export const DELETE_AZMAYESH = api + "/api/v3/azmayeshes/delete"; +export const GET_AZMAYESH_SAMPLE_FIELDS = api + "/api/v3/azmayesh_types/fields"; +export const ADD_SAMPLE_TO_AZMAYESH = api + "/api/v3/azmayesh_samples/store"; +export const UPDATE_SAMPLE_OF_AZMAYESH = api + "/api/v3/azmayesh_samples/update"; +export const GET_SAMPLE_LIST = api + "/api/v3/azmayesh_samples"; +export const DELETE_SAMPLE_LIST = api + "/api/v3/azmayesh_samples/delete"; diff --git a/src/lib/hooks/useProvince.js b/src/lib/hooks/useProvince.js index 0c5adb6..f6b98b8 100644 --- a/src/lib/hooks/useProvince.js +++ b/src/lib/hooks/useProvince.js @@ -11,18 +11,18 @@ const useProvinces = () => { useEffect(() => { const fetchCities = async () => { try { - const response = await requestServer(`${GET_PROVINCE_LISTS}`); // Fetch the cities from the API - setProvinces(response.data.data); // Set the cities data - setLoadingProvinces(false); // Set loading to false after successful fetch + const response = await requestServer(`${GET_PROVINCE_LISTS}`); + setProvinces(response.data.data); + setLoadingProvinces(false); } catch (e) { - console.error("Error fetching cities:", e); + console.error("Error fetching provinces:", e); setErrorProvinces(e); setLoadingProvinces(false); } }; - fetchCities(); // Call the fetch function - }, []); // Empty dependency array to ensure it only runs once + fetchCities(); + }, []); return { provinces, loadingProvinces, errorProvinces }; };