diff --git a/.env.local.example b/.env.local.example index 898913f..99ed3dd 100644 --- a/.env.local.example +++ b/.env.local.example @@ -1,3 +1,3 @@ -NEXT_PUBLIC_VERSION="0.6.1" +NEXT_PUBLIC_VERSION="0.7.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/package.json b/package.json index fee5c81..9641fc0 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,9 @@ "@emotion/cache": "^11.11.0", "@emotion/react": "^11.11.3", "@emotion/styled": "^11.11.0", + "@hookform/resolvers": "^3.9.0", "@mui/icons-material": "^5.15.6", + "@mui/lab": "^5.0.0-alpha.173", "@mui/material": "^5.15.6", "@mui/material-nextjs": "^5.15.6", "@mui/x-date-pickers": "^6.19.5", @@ -32,6 +34,7 @@ "react-dom": "^18", "react-hook-form": "^7.52.1", "react-leaflet": "^4.2.1", + "react-leaflet-draw": "^0.20.4", "react-toastify": "^10.0.5", "sass": "^1.75.0", "sharp": "^0.33.4", diff --git a/src/app/(withAuth)/dashboard/inquiry_privacy/fencing/page.js b/src/app/(withAuth)/dashboard/inquiry-privacy/_fencing/page.js similarity index 100% rename from src/app/(withAuth)/dashboard/inquiry_privacy/fencing/page.js rename to src/app/(withAuth)/dashboard/inquiry-privacy/_fencing/page.js diff --git a/src/app/(withAuth)/dashboard/inquiry-privacy/assistant/zamin-gov/page.js b/src/app/(withAuth)/dashboard/inquiry-privacy/assistant/zamin-gov/page.js new file mode 100644 index 0000000..0581720 --- /dev/null +++ b/src/app/(withAuth)/dashboard/inquiry-privacy/assistant/zamin-gov/page.js @@ -0,0 +1,7 @@ +import AssistantZaminGovComponent from "@/components/dashboard/inquiryPrivacy/assistant/zaminGov"; + +const Page = () => { + return ; +}; + +export default Page; diff --git a/src/app/(withAuth)/dashboard/inquiry-privacy/city-admin/zamin-gov/page.js b/src/app/(withAuth)/dashboard/inquiry-privacy/city-admin/zamin-gov/page.js new file mode 100644 index 0000000..2a45828 --- /dev/null +++ b/src/app/(withAuth)/dashboard/inquiry-privacy/city-admin/zamin-gov/page.js @@ -0,0 +1,7 @@ +import CityAdminZaminGovComponent from "@/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov"; + +const Page = () => { + return ; +}; + +export default Page; diff --git a/src/app/(withAuth)/dashboard/inquiry-privacy/general-manager/zamin-gov/page.js b/src/app/(withAuth)/dashboard/inquiry-privacy/general-manager/zamin-gov/page.js new file mode 100644 index 0000000..6c02a17 --- /dev/null +++ b/src/app/(withAuth)/dashboard/inquiry-privacy/general-manager/zamin-gov/page.js @@ -0,0 +1,7 @@ +import GeneralManagerZaminGovComponent from "@/components/dashboard/inquiryPrivacy/generalManager/zaminGov"; + +const Page = () => { + return ; +}; + +export default Page; diff --git a/src/app/(withAuth)/dashboard/inquiry-privacy/province-admin/zamin-gov/page.js b/src/app/(withAuth)/dashboard/inquiry-privacy/province-admin/zamin-gov/page.js new file mode 100644 index 0000000..735cd2c --- /dev/null +++ b/src/app/(withAuth)/dashboard/inquiry-privacy/province-admin/zamin-gov/page.js @@ -0,0 +1,7 @@ +import ProvinceAdminZaminGovComponent from "@/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov"; + +const Page = () => { + return ; +}; + +export default Page; diff --git a/src/app/(withAuth)/dashboard/layout.js b/src/app/(withAuth)/dashboard/layout.js index 5a85c25..219cee2 100644 --- a/src/app/(withAuth)/dashboard/layout.js +++ b/src/app/(withAuth)/dashboard/layout.js @@ -4,7 +4,7 @@ import { Stack } from "@mui/material"; const Layout = ({ children }) => { return ( - + {children} diff --git a/src/app/(withAuth)/dashboard/test/page.js b/src/app/(withAuth)/dashboard/test/page.js new file mode 100644 index 0000000..7baafa7 --- /dev/null +++ b/src/app/(withAuth)/dashboard/test/page.js @@ -0,0 +1,7 @@ +import TestPage from "@/components/dashboard/test"; + +const Page = () => { + return ; +}; + +export default Page; diff --git a/src/app/(withAuth)/layout.js b/src/app/(withAuth)/layout.js index b9c3d01..63d25a7 100644 --- a/src/app/(withAuth)/layout.js +++ b/src/app/(withAuth)/layout.js @@ -1,9 +1,7 @@ import WithAuthMiddleware from "@/core/middlewares/withAuth"; const Layout = ({ children }) => { - return ( - {children} - ); + return {children}; }; export default Layout; diff --git a/src/app/api/fake-cities/route.js b/src/app/api/fake-cities/route.js new file mode 100644 index 0000000..091e090 --- /dev/null +++ b/src/app/api/fake-cities/route.js @@ -0,0 +1,18 @@ +const data = [ + { + id: 1, + name: "تهران", + }, + { + id: 2, + name: "ری", + }, + { + id: 3, + name: "اندیشه", + }, +]; + +export async function GET() { + return Response.json({ data }); +} diff --git a/src/app/api/fake-data/route.js b/src/app/api/fake-data/route.js new file mode 100644 index 0000000..684c603 --- /dev/null +++ b/src/app/api/fake-data/route.js @@ -0,0 +1,41 @@ +const data = [ + { + id: 1, + aplication_number: 1, + application_date: "1", + province: "tehran", + city: "tehran", + }, + { + id: 2, + aplication_number: 2, + application_date: "1", + province: "tehran", + city: "tehran", + }, + { + id: 3, + aplication_number: 3, + application_date: "1", + province: "tehran", + city: "tehran", + }, + { + id: 4, + aplication_number: 4, + application_date: "1", + province: "tehran", + city: "tehran", + }, + { + id: 5, + aplication_number: 5, + application_date: "1", + province: "tehran", + city: "tehran", + }, +]; + +export async function GET() { + return Response.json({ data }); +} diff --git a/src/app/api/fake-prev-state-opinion/route.js b/src/app/api/fake-prev-state-opinion/route.js new file mode 100644 index 0000000..abd03e4 --- /dev/null +++ b/src/app/api/fake-prev-state-opinion/route.js @@ -0,0 +1,9 @@ +export async function GET() { + return Response.json({ + message: + "به موجب این نامه، به استحضار جنابعالی می رساند، این‌ جانب ……… از تاریخ ……… افتخار همکاری\n" + + "با مجموعه ……… را دارم. اما متاسفانه، به علت ………، تقاضای استعفای خود را از تاریخ ………\n" + + "اعلام میدارم. ضمن تشکر پیشاپیش از همکاری شما خواهشمند است، دستور اقدامات لازم در این\n" + + "زمینه را صادر فرمایید.", + }); +} diff --git a/src/app/api/fake-provinces/route.js b/src/app/api/fake-provinces/route.js new file mode 100644 index 0000000..d4bf49d --- /dev/null +++ b/src/app/api/fake-provinces/route.js @@ -0,0 +1,18 @@ +const data = [ + { + id: 1, + name: "تهران", + }, + { + id: 2, + name: "مشهد", + }, + { + id: 3, + name: "اصفهان", + }, +]; + +export async function GET() { + return Response.json({ data }); +} diff --git a/src/app/api/fake-submit/[id]/route.js b/src/app/api/fake-submit/[id]/route.js new file mode 100644 index 0000000..2ba57b2 --- /dev/null +++ b/src/app/api/fake-submit/[id]/route.js @@ -0,0 +1,3 @@ +export async function POST() { + return Response.json({ message: "Done" }); +} diff --git a/src/app/api/fake-tests-type/route.js b/src/app/api/fake-tests-type/route.js new file mode 100644 index 0000000..943b759 --- /dev/null +++ b/src/app/api/fake-tests-type/route.js @@ -0,0 +1,18 @@ +const data = [ + { + id: 1, + name: "تست نوع 1", + }, + { + id: 2, + name: "تست نوع 2", + }, + { + id: 3, + name: "تست نوع 3", + }, +]; + +export async function GET() { + return Response.json({data}); +} diff --git a/src/app/api/fake-tests/route.js b/src/app/api/fake-tests/route.js new file mode 100644 index 0000000..7d9c077 --- /dev/null +++ b/src/app/api/fake-tests/route.js @@ -0,0 +1,71 @@ +const data = [ + { + id: 1, + test_type_name: 1, + project_name: "نوع پروژه", + employer: "کارفرما", + consultant: "مشاور", + contractor: "پیمانکار", + applicant: "متقاضی", + work_number: "شماره کار", + request_number: "شماره درخواست", + request_date: "تاریخ درخواست", + report_date: "تاریخ گزارش" + }, + { + id: 2, + test_type_name: 5, + project_name: "نوع پروژه", + employer: "کارفرما", + consultant: "مشاور", + contractor: "پیمانکار", + applicant: "متقاضی", + work_number: "شماره کار", + request_number: "شماره درخواست", + request_date: "تاریخ درخواست", + report_date: "تاریخ گزارش" + }, + { + id: 3, + test_type_name: 2, + project_name: "نوع پروژه", + employer: "کارفرما", + consultant: "مشاور", + contractor: "پیمانکار", + applicant: "متقاضی", + work_number: "شماره کار", + request_number: "شماره درخواست", + request_date: "تاریخ درخواست", + report_date: "تاریخ گزارش" + }, + { + id: 4, + test_type_name: 4, + project_name: "نوع پروژه", + employer: "کارفرما", + consultant: "مشاور", + contractor: "پیمانکار", + applicant: "متقاضی", + work_number: "شماره کار", + request_number: "شماره درخواست", + request_date: "تاریخ درخواست", + report_date: "تاریخ گزارش" + }, + { + id: 5, + test_type_name: 3, + project_name: "نوع پروژه", + employer: "کارفرما", + consultant: "مشاور", + contractor: "پیمانکار", + applicant: "متقاضی", + work_number: "شماره کار", + request_number: "شماره درخواست", + request_date: "تاریخ درخواست", + report_date: "تاریخ گزارش" + }, +]; + +export async function GET() { + return Response.json({data}); +} diff --git a/src/app/layout.js b/src/app/layout.js index 580ae26..237d222 100644 --- a/src/app/layout.js +++ b/src/app/layout.js @@ -8,7 +8,7 @@ export const metadata = { export default function RootLayout({ children }) { return ( - + {children} diff --git a/src/app/lfwd/page.js b/src/app/lfwd/page.js index 61ebe16..70708e4 100644 --- a/src/app/lfwd/page.js +++ b/src/app/lfwd/page.js @@ -8,7 +8,7 @@ import Link from "next/link"; import { useEffect, useState } from "react"; const Page = ({ searchParams }) => { - const { getUser } = useAuth() + const { getUser } = useAuth(); const { username } = searchParams; const [login, setLogin] = useState(0); const request = useRequest(); @@ -17,7 +17,7 @@ const Page = ({ searchParams }) => { const login = async () => { try { await request(`${GET_LOGIN_ROUTE}?username=${username}`); - await getUser() + await getUser(); setLogin(1); } catch (error) { setLogin(2); @@ -31,7 +31,7 @@ const Page = ({ searchParams }) => { setLogin(0); try { await request(`${GET_LOGIN_ROUTE}?username=${username}`); - await getUser() + await getUser(); setLogin(1); } catch (error) { setLogin(2); @@ -44,8 +44,8 @@ const Page = ({ searchParams }) => { {login === 0 ? "درحال دریافت مجوز برای ارتباط با سرور..." : login === 1 - ? "ارتباط با سرور برقرار شد." - : "ارتباط با سرور برقرار نشد. مشکلی وجود دارد."} + ? "ارتباط با سرور برقرار شد." + : "ارتباط با سرور برقرار نشد. مشکلی وجود دارد."} + + + ); +}; +export default ManagerOrAssistantSubmit; diff --git a/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/RoadSafetyForm/PrevCartableOpinion.jsx b/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/RoadSafetyForm/PrevCartableOpinion.jsx new file mode 100644 index 0000000..6197267 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/RoadSafetyForm/PrevCartableOpinion.jsx @@ -0,0 +1,25 @@ +import { Card, CardContent, CardHeader, CircularProgress, Divider, Stack, Typography } from "@mui/material"; + +const PrevCartableOpinion = ({ message, loadingMessage, errorMessage }) => { + return ( + + + + + {errorMessage ? ( + خطا در دریافت اطلاعات !!! + ) : loadingMessage ? ( + + + درحال دریافت اطلاعات + + ) : ( + {message} + )} + + + + + ); +}; +export default PrevCartableOpinion; diff --git a/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/RoadSafetyForm/QuestionSafetyForm.jsx b/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/RoadSafetyForm/QuestionSafetyForm.jsx new file mode 100644 index 0000000..cc9be16 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/RoadSafetyForm/QuestionSafetyForm.jsx @@ -0,0 +1,33 @@ +import { Card, CardContent, FormControl, FormLabel, Stack, Typography } from "@mui/material"; + +const QuestionSafetyForm = () => { + return ( + + + + + + + آیا ایمنی راه این طرح مورد تایید است ؟ + + + + دفتر حریم راه : + + بله + + + + + + + ); +}; +export default QuestionSafetyForm; diff --git a/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/RoadSafetyForm/RoadSafetyFormContext.jsx b/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/RoadSafetyForm/RoadSafetyFormContext.jsx new file mode 100644 index 0000000..def0666 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/RoadSafetyForm/RoadSafetyFormContext.jsx @@ -0,0 +1,82 @@ +import { DialogActions, DialogContent, Stack } from "@mui/material"; +import StyledForm from "@/core/components/StyledForm"; +import useRequest from "@/lib/hooks/useRequest"; +import { useForm } from "react-hook-form"; +import { yupResolver } from "@hookform/resolvers/yup"; +import { object, string } from "yup"; +import { SUBMIT_ROAD_SAFETY_FORM } from "@/core/utils/routes"; +import usePrevStateOpinion from "@/lib/hooks/usePrevStateopinion"; +import QuestionSafetyForm from "./QuestionSafetyForm"; +import PrevCartableOpinion from "./PrevCartableOpinion"; +import DescriptionForm from "./DescriptionForm"; +import ManagerOrAssistantSubmit from "./ManagerOrAssistantSubmit"; +import ApplicantRequestDetail from "@/core/components/ApplicantRequestDetail"; +const fakeData = { + id: 1, + shomareh_darkhast: "2124", + ostan: "ostan", + shahr: "shahr", + shahrestan: "shahrestan", + bakhsh: "bakhsh", + roosta: "roosta", + tarikh_darkhast: "tarikh_darkhast", + sazman: "sazman", + masahat_zamin: "masahat_zamin", + masahat_tarh: "masahat_tarh", + gorooh_tarh: "gorooh_tarh", + onvane_tarh: "onvane_tarh", + address: "کرج - فلان جا - جنب پاساژ - نزدیک اونجا - اونور خیابون - زیر رو گذر - روی زیر گذر", + file_mosavab: "file", + polygon: [ + [51.515, -0.09], + [51.52, -0.1], + [51.52, -0.12], + ], +}; +const validationSchema = object({ + description: string().required("وارد کردن توضیحات الزامیست!"), +}); +const RoadSafetyFormContext = ({ rowId, mutate, setOpenRoadSafetyForm }) => { + const defaultValues = { + description: "", + }; + const requestServer = useRequest({ notification: { success: true, show: true } }); + const { message, loadingMessage, errorMessage } = usePrevStateOpinion(); + const { + register, + handleSubmit, + formState: { isSubmitting, errors }, + } = useForm({ defaultValues, resolver: yupResolver(validationSchema), mode: "onBlur" }); + const onSubmit = async (data) => { + const formData = new FormData(); + formData.append("description", data.description); + requestServer(`${SUBMIT_ROAD_SAFETY_FORM}/${rowId}`, "post", { + data: formData, + }) + .then(() => { + setOpenRoadSafetyForm(false); + mutate(); + }) + .catch(() => {}); + }; + return ( + + + + + + + + + + + + + + ); +}; +export default RoadSafetyFormContext; diff --git a/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/RoadSafetyForm/index.jsx b/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/RoadSafetyForm/index.jsx new file mode 100644 index 0000000..9c57473 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/RoadSafetyForm/index.jsx @@ -0,0 +1,52 @@ +import { Dialog, IconButton, Stack, Tooltip } from "@mui/material"; +import EngineeringIcon from "@mui/icons-material/Engineering"; +import DialogTransition from "@/core/components/DialogTransition"; +import { useState } from "react"; +import { Close } from "@mui/icons-material"; +import RoadSafetyFormContext from "./RoadSafetyFormContext"; + +const RoadSafetyForm = ({ rowId, mutate }) => { + const [openRoadSafetyForm, setOpenRoadSafetyForm] = useState(false); + return ( + + + { + setOpenRoadSafetyForm(true); + }} + > + + + + + setOpenRoadSafetyForm(false)} + sx={{ + position: "absolute", + right: 8, + top: 8, + zIndex: 10, + color: (theme) => theme.palette.grey[500], + }} + > + + + + + + ); +}; +export default RoadSafetyForm; diff --git a/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/TaskDetail/DetailDialog.jsx b/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/TaskDetail/DetailDialog.jsx new file mode 100644 index 0000000..aff1058 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/TaskDetail/DetailDialog.jsx @@ -0,0 +1,75 @@ +"use client"; + +import { Dialog, DialogContent } from "@mui/material"; +import { object, string } from "yup"; +import useRequest from "@/lib/hooks/useRequest"; +import { useForm } from "react-hook-form"; +import { yupResolver } from "@hookform/resolvers/yup"; +import StyledForm from "@/core/components/StyledForm"; +import ApplicantRequestDetail from "@/core/components/ApplicantRequestDetail"; + +const fakeData = { + id: 1, + shomareh_darkhast: "2124", + ostan: "ostan", + shahr: "shahr", + shahrestan: "shahrestan", + bakhsh: "bakhsh", + roosta: "roosta", + tarikh_darkhast: "tarikh_darkhast", + sazman: "sazman", + masahat_zamin: "masahat_zamin", + masahat_tarh: "masahat_tarh", + gorooh_tarh: "gorooh_tarh", + onvane_tarh: "onvane_tarh", + address: "کرج - فلان جا - جنب پاساژ - نزدیک اونجا - اونور خیابون - زیر رو گذر - روی زیر گذر", + file_mosavab: "file", + polygon: [ + [51.515, -0.09], + [51.52, -0.1], + [51.52, -0.12], + ], +}; + +const validationSchema = object({ + description: string().required("وارد کردن توضیحات الزامیست!"), +}); + +const DetailDialog = ({ taskModal, setTaskModal, rowId, mutate }) => { + const requestServer = useRequest({ auth: true }); + const defaultValues = { + description: "", + }; + const handleClose = () => { + setTaskModal(false); + }; + + const { + register, + handleSubmit, + formState: { isSubmitting, errors, touchedFields }, + } = useForm({ defaultValues, resolver: yupResolver(validationSchema), mode: "onBlur" }); + + const onSubmit = async (data) => { + const formData = new FormData(); + formData.append("description", data.description); + requestServer(`api-for-send-to-harim/${rowId}`, "post", { + data: formData, + }) + .then(() => { + handleClose(); + mutate(); + }) + .catch(() => {}); + }; + return ( + + + + + + + + ); +}; +export default DetailDialog; diff --git a/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/TaskDetail/index.jsx b/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/TaskDetail/index.jsx new file mode 100644 index 0000000..24f6b31 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/TaskDetail/index.jsx @@ -0,0 +1,26 @@ +"use client"; + +import { IconButton, Tooltip } from "@mui/material"; +import AssignmentIcon from "@mui/icons-material/Assignment"; +import DetailDialog from "./DetailDialog"; +import { useState } from "react"; + +const TaskDetail = ({ rowId, mutate }) => { + const [taskModal, setTaskModal] = useState(false); + + const openDetailDialog = () => { + setTaskModal(true); + }; + + return ( + <> + + + + + + + + ); +}; +export default TaskDetail; diff --git a/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/index.jsx b/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/index.jsx new file mode 100644 index 0000000..b7434f8 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/RowActions/index.jsx @@ -0,0 +1,13 @@ +import TaskDetail from "./TaskDetail"; +import { Box } from "@mui/material"; +import RoadSafetyForm from "./RoadSafetyForm"; + +const RowActions = ({ row, mutate }) => { + return ( + + + + + ); +}; +export default RowActions; diff --git a/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/TaskList.jsx b/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/TaskList.jsx new file mode 100644 index 0000000..8f158d9 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/TaskList.jsx @@ -0,0 +1,145 @@ +"use client"; + +import { useMemo } from "react"; +import { Box } from "@mui/material"; +import DataTableWithAuth from "@/core/components/DataTableWithAuth"; +import RowActions from "./RowActions"; + +const TaskList = () => { + const columns = useMemo( + () => [ + { + accessorKey: "id", + header: "کد یکتا", + id: "id", + enableColumnFilter: false, + datatype: "text", + filterFn: "notEquals", + }, + { + accessorKey: "aplication_number", + header: "شماره درخواست", + id: "aplication_number", + enableColumnFilter: false, + datatype: "text", + filterFn: "notEquals", + }, + { + accessorKey: "application_date", + header: "تاریخ درخواست", + id: "application_date", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "province", + header: "استان", + id: "province", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "township", + header: "شهرستان", + id: "township", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "city", + header: "شهر", + id: "city", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "county", + header: "بخش", + id: "county", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "village", + header: "روستا", + id: "village", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "land_area", + header: "مساحت زمین", + id: "land_area", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "design_area", + header: "مساحت طرح", + id: "design_area", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "organization", + header: "سازمان", + id: "organization", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "design_group", + header: "گروه طرح", + id: "design_group", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "design_title", + header: "عنوان طرح", + id: "design_title", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "state", + header: "وضعیت درخواست", + id: "state", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + ], + [] + ); + + return ( + <> + + + + + ); +}; +export default TaskList; diff --git a/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/index.jsx b/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/index.jsx new file mode 100644 index 0000000..6de55e0 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/assistant/zaminGov/index.jsx @@ -0,0 +1,15 @@ +"use client"; + +import PageTitle from "@/core/components/PageTitle"; +import { Stack } from "@mui/material"; +import TaskList from "./TaskList"; + +const AssistantZaminGovComponent = () => { + return ( + + + + + ); +}; +export default AssistantZaminGovComponent; diff --git a/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/RowActions/Refer/ReferFormContext.jsx b/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/RowActions/Refer/ReferFormContext.jsx new file mode 100644 index 0000000..10b8e38 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/RowActions/Refer/ReferFormContext.jsx @@ -0,0 +1,138 @@ +import { + Autocomplete, + Button, + CircularProgress, + DialogActions, + DialogContent, + FormControl, + FormHelperText, + InputLabel, + OutlinedInput, + Stack, + TextField, + Typography, +} from "@mui/material"; +import { Controller, useForm } from "react-hook-form"; +import { yupResolver } from "@hookform/resolvers/yup"; +import { object, string } from "yup"; +import StyledForm from "@/core/components/StyledForm"; +import useCities from "@/lib/hooks/useCities"; +import useRequest from "@/lib/hooks/useRequest"; +import { REFER_ADMIN_CITY } from "@/core/utils/routes"; + +const validationSchema = object({ + description: string().required("وارد کردن توضیحات الزامیست!"), + city: string().required("وارد کردن شهرستان الزامیست!"), +}); + +const ReferFormContext = ({ setOpenReferDialog, rowId, mutate }) => { + const defaultValues = { + description: "", + city: "", + }; + const { cities, loadingCities, errorCities } = useCities(); + const requestServer = useRequest({ notification: { show: true, success: true } }); + const { + control, + register, + handleSubmit, + formState: { isSubmitting, errors, touchedFields }, + } = useForm({ defaultValues, resolver: yupResolver(validationSchema), mode: "onBlur" }); + + const onSubmit = async (data) => { + const formData = new FormData(); + formData.append("description", data.description); + formData.append("cityId", data.city); + requestServer(`${REFER_ADMIN_CITY}/${rowId}`, "post", { + data: formData, + }) + .then(() => { + setOpenReferDialog(false); + mutate(); + }) + .catch(() => {}); + }; + return ( + + + + + + + توضیحات + + + + {errors.description ? errors.description.message : null} + + + + + ( + + + {errorCities ? ( + خطایی در دریافت شهرستان ها رخ داده است! + ) : loadingCities ? ( + + + درحال دریافت لیست شهرستان ها + + ) : ( + city.id === value) || null} + disablePortal + options={cities} + getOptionLabel={(city) => city.name} + isOptionEqualToValue={(option, value) => option.id === value.id} + onChange={(event, newValue) => { + onChange(newValue ? newValue.id : ""); + }} + renderInput={(params) => ( + + )} + /> + )} + + {errors.city ? errors.city.message : null} + + + )} + /> + + + + + + + + + ); +}; +export default ReferFormContext; diff --git a/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/RowActions/Refer/index.jsx b/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/RowActions/Refer/index.jsx new file mode 100644 index 0000000..8e77435 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/RowActions/Refer/index.jsx @@ -0,0 +1,41 @@ +import { Dialog, DialogTitle, IconButton, Stack, Tooltip } from "@mui/material"; +import ReplyIcon from "@mui/icons-material/Reply"; +import DialogTransition from "@/core/components/DialogTransition"; +import ReferFormContext from "./ReferFormContext"; +import { useState } from "react"; + +const ReferForm = ({ rowId, mutate }) => { + const [openReferDialog, setOpenReferDialog] = useState(false); + return ( + + + { + setOpenReferDialog(true); + }} + > + + + + + + ارجاع به شهرستان دیگر + + + + + ); +}; +export default ReferForm; diff --git a/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/RowActions/TaskDetail/DetailDialog.jsx b/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/RowActions/TaskDetail/DetailDialog.jsx new file mode 100644 index 0000000..a91fd31 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/RowActions/TaskDetail/DetailDialog.jsx @@ -0,0 +1,109 @@ +"use client"; + +import { + Button, + Dialog, + DialogActions, + DialogContent, + FormControl, + FormHelperText, + InputLabel, + OutlinedInput, +} from "@mui/material"; +import { object, string } from "yup"; +import useRequest from "@/lib/hooks/useRequest"; +import { useForm } from "react-hook-form"; +import { yupResolver } from "@hookform/resolvers/yup"; +import StyledForm from "@/core/components/StyledForm"; +import ApplicantRequestDetail from "@/core/components/ApplicantRequestDetail"; + +const fakeData = { + id: 1, + shomareh_darkhast: "2124", + ostan: "ostan", + shahr: "shahr", + shahrestan: "shahrestan", + bakhsh: "bakhsh", + roosta: "roosta", + tarikh_darkhast: "tarikh_darkhast", + sazman: "sazman", + masahat_zamin: "masahat_zamin", + masahat_tarh: "masahat_tarh", + gorooh_tarh: "gorooh_tarh", + onvane_tarh: "onvane_tarh", + address: "کرج - فلان جا - جنب پاساژ - نزدیک اونجا - اونور خیابون - زیر رو گذر - روی زیر گذر", + file_mosavab: "file", + polygon: [ + [51.515, -0.09], + [51.52, -0.1], + [51.52, -0.12], + ], +}; + +const validationSchema = object({ + description: string().required("وارد کردن توضیحات الزامیست!"), +}); + +const DetailDialog = ({ taskModal, setTaskModal, rowId, mutate }) => { + const requestServer = useRequest({ auth: true }); + const defaultValues = { + description: "", + }; + const handleClose = () => { + setTaskModal(false); + }; + + const { + register, + handleSubmit, + formState: { isSubmitting, errors, touchedFields }, + } = useForm({ defaultValues, resolver: yupResolver(validationSchema), mode: "onBlur" }); + + const onSubmit = async (data) => { + const formData = new FormData(); + formData.append("description", data.description); + requestServer(`api-for-send-to-harim/${rowId}`, "post", { + data: formData, + }) + .then(() => { + handleClose(); + mutate(); + }) + .catch(() => {}); + }; + return ( + + + + + + + توضیحات + + + + {errors.description ? errors.description.message : null} + + + + + + + + + ); +}; +export default DetailDialog; diff --git a/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/RowActions/TaskDetail/index.jsx b/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/RowActions/TaskDetail/index.jsx new file mode 100644 index 0000000..24f6b31 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/RowActions/TaskDetail/index.jsx @@ -0,0 +1,26 @@ +"use client"; + +import { IconButton, Tooltip } from "@mui/material"; +import AssignmentIcon from "@mui/icons-material/Assignment"; +import DetailDialog from "./DetailDialog"; +import { useState } from "react"; + +const TaskDetail = ({ rowId, mutate }) => { + const [taskModal, setTaskModal] = useState(false); + + const openDetailDialog = () => { + setTaskModal(true); + }; + + return ( + <> + + + + + + + + ); +}; +export default TaskDetail; diff --git a/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/RowActions/index.jsx b/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/RowActions/index.jsx new file mode 100644 index 0000000..0b936c3 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/RowActions/index.jsx @@ -0,0 +1,15 @@ +"use client"; + +import ReferForm from "./Refer"; +import TaskDetail from "./TaskDetail"; +import { Box } from "@mui/material"; + +const RowActions = ({ row, mutate }) => { + return ( + + + + + ); +}; +export default RowActions; diff --git a/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/TaskList.jsx b/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/TaskList.jsx new file mode 100644 index 0000000..83e2f6c --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/TaskList.jsx @@ -0,0 +1,145 @@ +"use client"; + +import { useMemo } from "react"; +import { Box } from "@mui/material"; +import DataTableWithAuth from "@/core/components/DataTableWithAuth"; +import RowActions from "./RowActions"; + +const TaskList = () => { + const columns = useMemo( + () => [ + { + accessorKey: "id", + header: "کد یکتا", + id: "id", + enableColumnFilter: false, + datatype: "text", + filterFn: "notEquals", + }, + { + accessorKey: "aplication_number", + header: "شماره درخواست", + id: "aplication_number", + enableColumnFilter: false, + datatype: "text", + filterFn: "notEquals", + }, + { + accessorKey: "application_date", + header: "تاریخ درخواست", + id: "application_date", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "province", + header: "استان", + id: "province", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "township", + header: "شهرستان", + id: "township", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "city", + header: "شهر", + id: "city", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "county", + header: "بخش", + id: "county", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "village", + header: "روستا", + id: "village", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "land_area", + header: "مساحت زمین", + id: "land_area", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "design_area", + header: "مساحت طرح", + id: "design_area", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "organization", + header: "سازمان", + id: "organization", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "design_group", + header: "گروه طرح", + id: "design_group", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "design_title", + header: "عنوان طرح", + id: "design_title", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "state", + header: "وضعیت درخواست", + id: "state", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + ], + [] + ); + + return ( + <> + + + + + ); +}; +export default TaskList; diff --git a/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/index.jsx b/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/index.jsx new file mode 100644 index 0000000..49ba4a2 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/cityAdmin/zaminGov/index.jsx @@ -0,0 +1,14 @@ +"use client"; +import PageTitle from "@/core/components/PageTitle"; +import { Stack } from "@mui/material"; +import TaskList from "./TaskList"; + +const CityAdminZaminGovComponent = () => { + return ( + + + + + ); +}; +export default CityAdminZaminGovComponent; diff --git a/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/RoadSafetyForm/DescriptionForm.jsx b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/RoadSafetyForm/DescriptionForm.jsx new file mode 100644 index 0000000..49ffa3c --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/RoadSafetyForm/DescriptionForm.jsx @@ -0,0 +1,29 @@ +import { FormControl, FormHelperText, InputLabel, OutlinedInput, Stack } from "@mui/material"; + +const DescriptionForm = ({ errors, register }) => { + return ( + + + + توضیحات + + + + {errors.description ? errors.description.message : null} + + + + ); +}; +export default DescriptionForm; diff --git a/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/RoadSafetyForm/ManagerOrAssistantSubmit.jsx b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/RoadSafetyForm/ManagerOrAssistantSubmit.jsx new file mode 100644 index 0000000..a515950 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/RoadSafetyForm/ManagerOrAssistantSubmit.jsx @@ -0,0 +1,15 @@ +import { Button } from "@mui/material"; + +const ManagerOrAssistantSubmit = ({ isSubmitting }) => { + return ( + <> + + + + ); +}; +export default ManagerOrAssistantSubmit; diff --git a/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/RoadSafetyForm/PrevCartableOpinion.jsx b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/RoadSafetyForm/PrevCartableOpinion.jsx new file mode 100644 index 0000000..d2587c5 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/RoadSafetyForm/PrevCartableOpinion.jsx @@ -0,0 +1,26 @@ +import { Card, CardContent, CardHeader, CircularProgress, Divider, Stack, Typography } from "@mui/material"; +import usePrevStateOpinion from "@/lib/hooks/usePrevStateopinion"; + +const PrevCartableOpinion = ({ message, loadingMessage, errorMessage }) => { + return ( + + + + + {errorMessage ? ( + خطا در دریافت اطلاعات !!! + ) : loadingMessage ? ( + + + درحال دریافت اطلاعات + + ) : ( + {message} + )} + + + + + ); +}; +export default PrevCartableOpinion; diff --git a/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/RoadSafetyForm/QuestionSafetyForm.jsx b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/RoadSafetyForm/QuestionSafetyForm.jsx new file mode 100644 index 0000000..cc9be16 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/RoadSafetyForm/QuestionSafetyForm.jsx @@ -0,0 +1,33 @@ +import { Card, CardContent, FormControl, FormLabel, Stack, Typography } from "@mui/material"; + +const QuestionSafetyForm = () => { + return ( + + + + + + + آیا ایمنی راه این طرح مورد تایید است ؟ + + + + دفتر حریم راه : + + بله + + + + + + + ); +}; +export default QuestionSafetyForm; diff --git a/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/RoadSafetyForm/RoadSafetyFormContext.jsx b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/RoadSafetyForm/RoadSafetyFormContext.jsx new file mode 100644 index 0000000..7ced8b8 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/RoadSafetyForm/RoadSafetyFormContext.jsx @@ -0,0 +1,82 @@ +import { DialogActions, DialogContent, Stack } from "@mui/material"; +import StyledForm from "@/core/components/StyledForm"; +import useRequest from "@/lib/hooks/useRequest"; +import { useForm } from "react-hook-form"; +import { yupResolver } from "@hookform/resolvers/yup"; +import { object, string } from "yup"; +import { SUBMIT_ROAD_SAFETY_FORM } from "@/core/utils/routes"; +import QuestionSafetyForm from "./QuestionSafetyForm"; +import PrevCartableOpinion from "./PrevCartableOpinion"; +import DescriptionForm from "./DescriptionForm"; +import ManagerOrAssistantSubmit from "./ManagerOrAssistantSubmit"; +import usePrevStateOpinion from "@/lib/hooks/usePrevStateopinion"; +import ApplicantRequestDetail from "@/core/components/ApplicantRequestDetail"; +const fakeData = { + id: 1, + shomareh_darkhast: "2124", + ostan: "ostan", + shahr: "shahr", + shahrestan: "shahrestan", + bakhsh: "bakhsh", + roosta: "roosta", + tarikh_darkhast: "tarikh_darkhast", + sazman: "sazman", + masahat_zamin: "masahat_zamin", + masahat_tarh: "masahat_tarh", + gorooh_tarh: "gorooh_tarh", + onvane_tarh: "onvane_tarh", + address: "کرج - فلان جا - جنب پاساژ - نزدیک اونجا - اونور خیابون - زیر رو گذر - روی زیر گذر", + file_mosavab: "file", + polygon: [ + [51.515, -0.09], + [51.52, -0.1], + [51.52, -0.12], + ], +}; +const validationSchema = object({ + description: string().required("وارد کردن توضیحات الزامیست!"), +}); +const RoadSafetyFormContext = ({ rowId, mutate, setOpenRoadSafetyForm }) => { + const defaultValues = { + description: "", + }; + const requestServer = useRequest({ notification: { success: true, show: true } }); + const { message, loadingMessage, errorMessage } = usePrevStateOpinion(); + const { + register, + handleSubmit, + formState: { isSubmitting, errors }, + } = useForm({ defaultValues, resolver: yupResolver(validationSchema), mode: "onBlur" }); + const onSubmit = async (data) => { + const formData = new FormData(); + formData.append("description", data.description); + requestServer(`${SUBMIT_ROAD_SAFETY_FORM}/${rowId}`, "post", { + data: formData, + }) + .then(() => { + setOpenRoadSafetyForm(false); + mutate(); + }) + .catch(() => {}); + }; + return ( + + + + + + + + + + + + + + ); +}; +export default RoadSafetyFormContext; diff --git a/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/RoadSafetyForm/index.jsx b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/RoadSafetyForm/index.jsx new file mode 100644 index 0000000..9c57473 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/RoadSafetyForm/index.jsx @@ -0,0 +1,52 @@ +import { Dialog, IconButton, Stack, Tooltip } from "@mui/material"; +import EngineeringIcon from "@mui/icons-material/Engineering"; +import DialogTransition from "@/core/components/DialogTransition"; +import { useState } from "react"; +import { Close } from "@mui/icons-material"; +import RoadSafetyFormContext from "./RoadSafetyFormContext"; + +const RoadSafetyForm = ({ rowId, mutate }) => { + const [openRoadSafetyForm, setOpenRoadSafetyForm] = useState(false); + return ( + + + { + setOpenRoadSafetyForm(true); + }} + > + + + + + setOpenRoadSafetyForm(false)} + sx={{ + position: "absolute", + right: 8, + top: 8, + zIndex: 10, + color: (theme) => theme.palette.grey[500], + }} + > + + + + + + ); +}; +export default RoadSafetyForm; diff --git a/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/TaskDetail/DetailDialog.jsx b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/TaskDetail/DetailDialog.jsx new file mode 100644 index 0000000..aff1058 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/TaskDetail/DetailDialog.jsx @@ -0,0 +1,75 @@ +"use client"; + +import { Dialog, DialogContent } from "@mui/material"; +import { object, string } from "yup"; +import useRequest from "@/lib/hooks/useRequest"; +import { useForm } from "react-hook-form"; +import { yupResolver } from "@hookform/resolvers/yup"; +import StyledForm from "@/core/components/StyledForm"; +import ApplicantRequestDetail from "@/core/components/ApplicantRequestDetail"; + +const fakeData = { + id: 1, + shomareh_darkhast: "2124", + ostan: "ostan", + shahr: "shahr", + shahrestan: "shahrestan", + bakhsh: "bakhsh", + roosta: "roosta", + tarikh_darkhast: "tarikh_darkhast", + sazman: "sazman", + masahat_zamin: "masahat_zamin", + masahat_tarh: "masahat_tarh", + gorooh_tarh: "gorooh_tarh", + onvane_tarh: "onvane_tarh", + address: "کرج - فلان جا - جنب پاساژ - نزدیک اونجا - اونور خیابون - زیر رو گذر - روی زیر گذر", + file_mosavab: "file", + polygon: [ + [51.515, -0.09], + [51.52, -0.1], + [51.52, -0.12], + ], +}; + +const validationSchema = object({ + description: string().required("وارد کردن توضیحات الزامیست!"), +}); + +const DetailDialog = ({ taskModal, setTaskModal, rowId, mutate }) => { + const requestServer = useRequest({ auth: true }); + const defaultValues = { + description: "", + }; + const handleClose = () => { + setTaskModal(false); + }; + + const { + register, + handleSubmit, + formState: { isSubmitting, errors, touchedFields }, + } = useForm({ defaultValues, resolver: yupResolver(validationSchema), mode: "onBlur" }); + + const onSubmit = async (data) => { + const formData = new FormData(); + formData.append("description", data.description); + requestServer(`api-for-send-to-harim/${rowId}`, "post", { + data: formData, + }) + .then(() => { + handleClose(); + mutate(); + }) + .catch(() => {}); + }; + return ( + + + + + + + + ); +}; +export default DetailDialog; diff --git a/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/TaskDetail/index.jsx b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/TaskDetail/index.jsx new file mode 100644 index 0000000..24f6b31 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/TaskDetail/index.jsx @@ -0,0 +1,26 @@ +"use client"; + +import { IconButton, Tooltip } from "@mui/material"; +import AssignmentIcon from "@mui/icons-material/Assignment"; +import DetailDialog from "./DetailDialog"; +import { useState } from "react"; + +const TaskDetail = ({ rowId, mutate }) => { + const [taskModal, setTaskModal] = useState(false); + + const openDetailDialog = () => { + setTaskModal(true); + }; + + return ( + <> + + + + + + + + ); +}; +export default TaskDetail; diff --git a/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/index.jsx b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/index.jsx new file mode 100644 index 0000000..b7434f8 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/RowActions/index.jsx @@ -0,0 +1,13 @@ +import TaskDetail from "./TaskDetail"; +import { Box } from "@mui/material"; +import RoadSafetyForm from "./RoadSafetyForm"; + +const RowActions = ({ row, mutate }) => { + return ( + + + + + ); +}; +export default RowActions; diff --git a/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/TaskList.jsx b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/TaskList.jsx new file mode 100644 index 0000000..92f500b --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/TaskList.jsx @@ -0,0 +1,145 @@ +"use client"; + +import { useMemo } from "react"; +import { Box } from "@mui/material"; +import DataTableWithAuth from "@/core/components/DataTableWithAuth"; +import RowActions from "./RowActions"; + +const TaskList = () => { + const columns = useMemo( + () => [ + { + accessorKey: "id", + header: "کد یکتا", + id: "id", + enableColumnFilter: false, + datatype: "text", + filterFn: "notEquals", + }, + { + accessorKey: "aplication_number", + header: "شماره درخواست", + id: "aplication_number", + enableColumnFilter: false, + datatype: "text", + filterFn: "notEquals", + }, + { + accessorKey: "application_date", + header: "تاریخ درخواست", + id: "application_date", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "province", + header: "استان", + id: "province", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "township", + header: "شهرستان", + id: "township", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "city", + header: "شهر", + id: "city", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "county", + header: "بخش", + id: "county", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "village", + header: "روستا", + id: "village", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "land_area", + header: "مساحت زمین", + id: "land_area", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "design_area", + header: "مساحت طرح", + id: "design_area", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "organization", + header: "سازمان", + id: "organization", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "design_group", + header: "گروه طرح", + id: "design_group", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "design_title", + header: "عنوان طرح", + id: "design_title", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "state", + header: "وضعیت درخواست", + id: "state", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + ], + [] + ); + + return ( + <> + + + + + ); +}; +export default TaskList; diff --git a/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/index.jsx b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/index.jsx new file mode 100644 index 0000000..f348745 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/generalManager/zaminGov/index.jsx @@ -0,0 +1,15 @@ +"use client"; + +import PageTitle from "@/core/components/PageTitle"; +import { Stack } from "@mui/material"; +import TaskList from "./TaskList"; + +const GeneralManagerZaminGovComponent = () => { + return ( + + + + + ); +}; +export default GeneralManagerZaminGovComponent; diff --git a/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/MapModify/MapActionButtons.jsx b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/MapModify/MapActionButtons.jsx new file mode 100644 index 0000000..4986160 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/MapModify/MapActionButtons.jsx @@ -0,0 +1,96 @@ +import {Box, Button, ButtonGroup} from "@mui/material"; +import AutoModeIcon from "@mui/icons-material/AutoMode"; +import DeleteIcon from "@mui/icons-material/Delete"; +import EditLocationAltIcon from "@mui/icons-material/EditLocationAlt"; +import SaveIcon from "@mui/icons-material/Save"; +import CancelIcon from "@mui/icons-material/Cancel"; + +const MapActionButtons = ({ + disableToCreate, + disableToEditAndDelete, + disableToSaveAndCancel, + onDraw, + onEdit, + onRemove, + onSave, + onCancel, + }) => ( + <> + + + + + + + + + + + + + +); + +export default MapActionButtons; \ No newline at end of file diff --git a/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/MapModify/MapModifyDialog.jsx b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/MapModify/MapModifyDialog.jsx new file mode 100644 index 0000000..55566a2 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/MapModify/MapModifyDialog.jsx @@ -0,0 +1,91 @@ +"use client"; + +import { + Box, + Button, + Chip, + Dialog, + DialogActions, + DialogContent, + Divider, + FormControl, + FormControlLabel, + FormLabel, + Radio, + RadioGroup, + Typography, +} from "@mui/material"; +import dynamic from "next/dynamic"; +import MapLoading from "@/core/components/MapLayer/Loading"; +import "leaflet-draw/dist/leaflet.draw.css"; +import GppMaybeIcon from "@mui/icons-material/GppMaybe"; +import PolygonForDesign from "./PolygonForDesign"; + +const MapLayer = dynamic(() => import("@/core/components/MapLayer"), { + loading: () => , + ssr: false, +}); + +const MapModifyDialog = ({mapModifyModal, setMapModifyModal}) => { + const handleClose = () => { + setMapModifyModal(false); + }; + + return ( + + + + + + + + + + + + + + نکته: اصلاح ننمودن طرح به منزله تایید طرح میباشد. + + + + + آیا + طرح نیاز به ایجاد راه + دسترسی + دارد؟ + + } label="بله"/> + } label="خیر"/> + + + + + + + + + + ); +}; + +export default MapModifyDialog; diff --git a/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/MapModify/PolygonForDesign.jsx b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/MapModify/PolygonForDesign.jsx new file mode 100644 index 0000000..9dd400f --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/MapModify/PolygonForDesign.jsx @@ -0,0 +1,118 @@ +"use client"; + +import "leaflet-draw/dist/leaflet.draw.css"; +import "@/assets/scss/map-styles.scss" +import {FeatureGroup, useMap} from "react-leaflet"; +import {EditControl} from "react-leaflet-draw"; +import {useEffect, useRef, useState} from "react"; +import MapActionButtons from "./MapActionButtons"; + + +const PolygonForDesign = () => { + const map = useMap(); + const editableFG = useRef(null); + const [polygonLayer, setPolygonLayer] = useState(null); + const [disableToCreate, setDisableToCreate] = useState(false); + const [disableToEditAndDelete, setDisableToEditAndDelete] = useState(true); + const [disableToSaveAndCancel, setDisableToSaveAndCancel] = useState(true); + const [editToolbar, setEditToolbar] = useState(null); + + useEffect(() => { + const {L} = window; + L.drawLocal.draw.handlers.polygon.tooltip = { + start: "برای شروع کشیدن پلیگان، کلیک کنید.", + cont: "گوشه های دیگر پلیگان را نیز انتخاب کنید.", + end: "برای اتمام رسم پلیگان، نقطه آخر را به اول متصل نمایید.", + }; + L.drawLocal.edit.handlers.edit.tooltip = { + text: "برای ذخیر یا لغو تغییرات، از دکمه های بالا سمت چپ استفاده نمایید.", + subtext: "نقاط مشخص شده را گرفته و برای ویرایش جابجا نمایید.", + }; + }, []); + + const handleDrawPolygon = () => { + const {L} = window; + const drawControl = new L.Draw.Polygon(map); + drawControl.enable(); + setDisableToCreate(true); + }; + + const handleEditPolygon = () => { + const {L} = window; + if (editableFG.current && polygonLayer) { + const editControlInstance = new L.EditToolbar.Edit(map, { + featureGroup: editableFG.current, + }); + editControlInstance.enable(); + setEditToolbar(editControlInstance); + setDisableToEditAndDelete(true); + setDisableToSaveAndCancel(false); + } + }; + + const handleRemovePolygon = () => { + if (polygonLayer && editableFG.current) { + editableFG.current.removeLayer(polygonLayer); + setPolygonLayer(null); + setDisableToEditAndDelete(true); + setDisableToCreate(false); + } + }; + + const handleSavePolygon = () => { + if (editToolbar) { + editToolbar.save(); + editToolbar.disable(); + setDisableToEditAndDelete(false); + setDisableToSaveAndCancel(true); + } + }; + + const handleCancelEdit = () => { + if (editToolbar) { + editToolbar.revertLayers(); + editToolbar.disable(); + setDisableToEditAndDelete(false); + setDisableToSaveAndCancel(true); + } + }; + + const handlePolygonCreate = (e) => { + const layer = e.layer; + setPolygonLayer(layer); + editableFG.current.addLayer(layer); + setDisableToEditAndDelete(false); + }; + + return ( + <> + + + + + + ); +}; + +export default PolygonForDesign; \ No newline at end of file diff --git a/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/MapModify/index.jsx b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/MapModify/index.jsx new file mode 100644 index 0000000..5a96741 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/MapModify/index.jsx @@ -0,0 +1,25 @@ +import {IconButton, Tooltip} from "@mui/material"; +import MapIcon from "@mui/icons-material/Map"; +import {useState} from "react"; +import MapModifyDialog from "./MapModifyDialog"; + +const MapModify = ({rowId, mutate}) => { + const [mapModifyModal, setMapModifyModal] = useState(false); + + const openMapModifyDialog = () => { + setMapModifyModal(true); + }; + + return ( + <> + + + + + + + + ); +}; +export default MapModify; diff --git a/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/Refer/ReferFormContext.jsx b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/Refer/ReferFormContext.jsx new file mode 100644 index 0000000..26f9bf8 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/Refer/ReferFormContext.jsx @@ -0,0 +1,139 @@ +import { + Autocomplete, + Button, + CircularProgress, + DialogActions, + DialogContent, + FormControl, + FormHelperText, + InputLabel, + OutlinedInput, + Stack, + TextField, + Typography, +} from "@mui/material"; +import { Controller, useForm } from "react-hook-form"; +import { yupResolver } from "@hookform/resolvers/yup"; +import { object, string } from "yup"; +import StyledForm from "@/core/components/StyledForm"; +import useProvinces from "@/lib/hooks/useProvince"; +import useRequest from "@/lib/hooks/useRequest"; +import { REFER_ADMIN_PROVINCE } from "@/core/utils/routes"; + +const validationSchema = object({ + description: string().required("وارد کردن توضیحات الزامیست!"), + province: string().required("وارد کردن استان الزامیست!"), +}); + +const ReferFormContext = ({ setOpenReferDialog, rowId, mutate }) => { + const defaultValues = { + description: "", + province: "", + }; + const { provinces, loadingProvinces, errorProvinces } = useProvinces(); + const requestServer = useRequest({ notification: { show: true, success: true } }); + const { + control, + register, + handleSubmit, + formState: { isSubmitting, errors, touchedFields }, + } = useForm({ defaultValues, resolver: yupResolver(validationSchema), mode: "onBlur" }); + + const onSubmit = async (data) => { + const formData = new FormData(); + formData.append("description", data.description); + formData.append("provinceId", data.province); + + requestServer(`${REFER_ADMIN_PROVINCE}/${rowId}`, "post", { + data: formData, + }) + .then(() => { + setOpenReferDialog(false); + mutate(); + }) + .catch(() => {}); + }; + return ( + + + + + + + توضیحات + + + + {errors.description ? errors.description.message : null} + + + + + ( + + + {errorProvinces ? ( + خطایی در دریافت استان ها رخ داده است! + ) : loadingProvinces ? ( + + + درحال دریافت لیست استان ها + + ) : ( + province.id === value) || null} + disablePortal + options={provinces} + getOptionLabel={(province) => province.name} + isOptionEqualToValue={(option, value) => option.id === value.id} + onChange={(event, newValue) => { + onChange(newValue ? newValue.id : ""); + }} + renderInput={(params) => ( + + )} + /> + )} + + {errors.province ? errors.province.message : null} + + + )} + /> + + + + + + + + + ); +}; +export default ReferFormContext; diff --git a/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/Refer/index.jsx b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/Refer/index.jsx new file mode 100644 index 0000000..c3a3012 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/Refer/index.jsx @@ -0,0 +1,41 @@ +import { Dialog, DialogTitle, IconButton, Stack, Tooltip } from "@mui/material"; +import ReplyIcon from "@mui/icons-material/Reply"; +import DialogTransition from "@/core/components/DialogTransition"; +import { useState } from "react"; +import ReferFormContext from "./ReferFormContext"; + +const ReferForm = ({ rowId, mutate }) => { + const [openReferDialog, setOpenReferDialog] = useState(false); + return ( + + + { + setOpenReferDialog(true); + }} + > + + + + + + ارجاع به استان دیگر + + + + + ); +}; +export default ReferForm; diff --git a/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/RoadSafetyForm/DescriptionForm.jsx b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/RoadSafetyForm/DescriptionForm.jsx new file mode 100644 index 0000000..49ffa3c --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/RoadSafetyForm/DescriptionForm.jsx @@ -0,0 +1,29 @@ +import { FormControl, FormHelperText, InputLabel, OutlinedInput, Stack } from "@mui/material"; + +const DescriptionForm = ({ errors, register }) => { + return ( + + + + توضیحات + + + + {errors.description ? errors.description.message : null} + + + + ); +}; +export default DescriptionForm; diff --git a/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/RoadSafetyForm/PrevCartableOpinion.jsx b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/RoadSafetyForm/PrevCartableOpinion.jsx new file mode 100644 index 0000000..8d14fd0 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/RoadSafetyForm/PrevCartableOpinion.jsx @@ -0,0 +1,27 @@ +import { Card, CardContent, CardHeader, CircularProgress, Divider, Stack, Typography } from "@mui/material"; +import usePrevStateOpinion from "@/lib/hooks/usePrevStateopinion"; + +const PrevCartableOpinion = () => { + const { message, loadingMessage, errorMessage } = usePrevStateOpinion(); + return ( + + + + + {errorMessage ? ( + خطا در دریافت اطلاعات !!! + ) : loadingMessage ? ( + + + درحال دریافت اطلاعات + + ) : ( + {message} + )} + + + + + ); +}; +export default PrevCartableOpinion; diff --git a/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/RoadSafetyForm/QuestionSafetyForm.jsx b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/RoadSafetyForm/QuestionSafetyForm.jsx new file mode 100644 index 0000000..4c5faae --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/RoadSafetyForm/QuestionSafetyForm.jsx @@ -0,0 +1,57 @@ +import { + Card, + CardContent, + FormControl, + FormControlLabel, + FormLabel, + RadioGroup, + Stack, + Typography, +} from "@mui/material"; +import Radio from "@mui/material/Radio"; + +const QuestionSafetyForm = ({ register, errors }) => { + return ( + + + + + + + آیا ایمنی راه این طرح مورد تایید است ؟ + + + + + } + label="بله" + {...register("RadioGroup")} + /> + } + label="خیر" + {...register("RadioGroup")} + /> + + + {errors.RadioGroup && ( + + {errors.RadioGroup.message} + + )} + + + + + ); +}; +export default QuestionSafetyForm; diff --git a/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/RoadSafetyForm/RoadSaftyFormContext.jsx b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/RoadSafetyForm/RoadSaftyFormContext.jsx new file mode 100644 index 0000000..861400a --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/RoadSafetyForm/RoadSaftyFormContext.jsx @@ -0,0 +1,80 @@ +import { DialogActions, DialogContent, Stack } from "@mui/material"; +import StyledForm from "@/core/components/StyledForm"; +import useRequest from "@/lib/hooks/useRequest"; +import { useForm } from "react-hook-form"; +import { yupResolver } from "@hookform/resolvers/yup"; +import { object, string } from "yup"; +import QuestionSafetyForm from "./QuestionSafetyForm"; +import PrevCartableOpinion from "./PrevCartableOpinion"; +import DescriptionForm from "./DescriptionForm"; +import SubmitButtonsAdmin from "./SubmitButtonsAdmin"; +import { SUBMIT_ROAD_SAFETY_FORM } from "@/core/utils/routes"; +import ApplicantRequestDetail from "@/core/components/ApplicantRequestDetail"; +const fakeData = { + id: 1, + shomareh_darkhast: "2124", + ostan: "ostan", + shahr: "shahr", + shahrestan: "shahrestan", + bakhsh: "bakhsh", + roosta: "roosta", + tarikh_darkhast: "tarikh_darkhast", + sazman: "sazman", + masahat_zamin: "masahat_zamin", + masahat_tarh: "masahat_tarh", + gorooh_tarh: "gorooh_tarh", + onvane_tarh: "onvane_tarh", + address: "کرج - فلان جا - جنب پاساژ - نزدیک اونجا - اونور خیابون - زیر رو گذر - روی زیر گذر", + file_mosavab: "file", + polygon: [ + [51.515, -0.09], + [51.52, -0.1], + [51.52, -0.12], + ], +}; +const validationSchema = object({ + description: string().required("وارد کردن توضیحات الزامیست!"), + RadioGroup: string().required("تاییدیه ایمنی راه ضروریست!"), +}); +const RoadSafetyFormContext = ({ rowId, mutate, setOpenRoadSafetyForm }) => { + const defaultValues = { + description: "", + RadioGroup: "", + }; + const requestServer = useRequest({ notification: { success: true, show: true } }); + const { + register, + handleSubmit, + formState: { isSubmitting, errors }, + } = useForm({ defaultValues, resolver: yupResolver(validationSchema), mode: "onBlur" }); + const onSubmit = async (data) => { + const formData = new FormData(); + formData.append("description", data.description); + formData.append("provinceId", data.RadioGroup); + + requestServer(`${SUBMIT_ROAD_SAFETY_FORM}/${rowId}`, "post", { + data: formData, + }) + .then(() => { + setOpenRoadSafetyForm(false); + mutate(); + }) + .catch(() => {}); + }; + return ( + + + + + + + + + + + + + + ); +}; +export default RoadSafetyFormContext; diff --git a/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/RoadSafetyForm/SubmitButtonsAdmin.jsx b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/RoadSafetyForm/SubmitButtonsAdmin.jsx new file mode 100644 index 0000000..6b46447 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/RoadSafetyForm/SubmitButtonsAdmin.jsx @@ -0,0 +1,21 @@ +import { Button } from "@mui/material"; + +const SubmitButtonsAdmin = ({ setOpenRoadSafetyForm, isSubmitting }) => { + return ( + <> + + + + ); +}; +export default SubmitButtonsAdmin; diff --git a/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/RoadSafetyForm/index.jsx b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/RoadSafetyForm/index.jsx new file mode 100644 index 0000000..652e809 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/RoadSafetyForm/index.jsx @@ -0,0 +1,52 @@ +import { Dialog, IconButton, Stack, Tooltip } from "@mui/material"; +import EngineeringIcon from "@mui/icons-material/Engineering"; +import DialogTransition from "@/core/components/DialogTransition"; +import { useState } from "react"; +import RoadSafetyFormContext from "./RoadSaftyFormContext"; +import { Close } from "@mui/icons-material"; + +const RoadSafetyForm = ({ rowId, mutate }) => { + const [openRoadSafetyForm, setOpenRoadSafetyForm] = useState(false); + return ( + + + { + setOpenRoadSafetyForm(true); + }} + > + + + + + setOpenRoadSafetyForm(false)} + sx={{ + position: "absolute", + right: 8, + top: 8, + zIndex: 10, + color: (theme) => theme.palette.grey[500], + }} + > + + + + + + ); +}; +export default RoadSafetyForm; diff --git a/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/TaskDetail/DetailDialog.jsx b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/TaskDetail/DetailDialog.jsx new file mode 100644 index 0000000..aff1058 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/TaskDetail/DetailDialog.jsx @@ -0,0 +1,75 @@ +"use client"; + +import { Dialog, DialogContent } from "@mui/material"; +import { object, string } from "yup"; +import useRequest from "@/lib/hooks/useRequest"; +import { useForm } from "react-hook-form"; +import { yupResolver } from "@hookform/resolvers/yup"; +import StyledForm from "@/core/components/StyledForm"; +import ApplicantRequestDetail from "@/core/components/ApplicantRequestDetail"; + +const fakeData = { + id: 1, + shomareh_darkhast: "2124", + ostan: "ostan", + shahr: "shahr", + shahrestan: "shahrestan", + bakhsh: "bakhsh", + roosta: "roosta", + tarikh_darkhast: "tarikh_darkhast", + sazman: "sazman", + masahat_zamin: "masahat_zamin", + masahat_tarh: "masahat_tarh", + gorooh_tarh: "gorooh_tarh", + onvane_tarh: "onvane_tarh", + address: "کرج - فلان جا - جنب پاساژ - نزدیک اونجا - اونور خیابون - زیر رو گذر - روی زیر گذر", + file_mosavab: "file", + polygon: [ + [51.515, -0.09], + [51.52, -0.1], + [51.52, -0.12], + ], +}; + +const validationSchema = object({ + description: string().required("وارد کردن توضیحات الزامیست!"), +}); + +const DetailDialog = ({ taskModal, setTaskModal, rowId, mutate }) => { + const requestServer = useRequest({ auth: true }); + const defaultValues = { + description: "", + }; + const handleClose = () => { + setTaskModal(false); + }; + + const { + register, + handleSubmit, + formState: { isSubmitting, errors, touchedFields }, + } = useForm({ defaultValues, resolver: yupResolver(validationSchema), mode: "onBlur" }); + + const onSubmit = async (data) => { + const formData = new FormData(); + formData.append("description", data.description); + requestServer(`api-for-send-to-harim/${rowId}`, "post", { + data: formData, + }) + .then(() => { + handleClose(); + mutate(); + }) + .catch(() => {}); + }; + return ( + + + + + + + + ); +}; +export default DetailDialog; diff --git a/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/TaskDetail/index.jsx b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/TaskDetail/index.jsx new file mode 100644 index 0000000..24f6b31 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/TaskDetail/index.jsx @@ -0,0 +1,26 @@ +"use client"; + +import { IconButton, Tooltip } from "@mui/material"; +import AssignmentIcon from "@mui/icons-material/Assignment"; +import DetailDialog from "./DetailDialog"; +import { useState } from "react"; + +const TaskDetail = ({ rowId, mutate }) => { + const [taskModal, setTaskModal] = useState(false); + + const openDetailDialog = () => { + setTaskModal(true); + }; + + return ( + <> + + + + + + + + ); +}; +export default TaskDetail; diff --git a/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/index.jsx b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/index.jsx new file mode 100644 index 0000000..778eaa7 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/RowActions/index.jsx @@ -0,0 +1,17 @@ +import ReferForm from "./Refer"; +import TaskDetail from "./TaskDetail"; +import {Box} from "@mui/material"; +import RoadSafetyForm from "./RoadSafetyForm"; +import MapModify from "./MapModify"; + +const RowActions = ({row, mutate}) => { + return ( + + + + + + + ); +}; +export default RowActions; diff --git a/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/TaskList.jsx b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/TaskList.jsx new file mode 100644 index 0000000..550e152 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/TaskList.jsx @@ -0,0 +1,145 @@ +"use client"; + +import { useMemo } from "react"; +import { Box } from "@mui/material"; +import DataTableWithAuth from "@/core/components/DataTableWithAuth"; +import RowActions from "./RowActions"; + +const TaskList = () => { + const columns = useMemo( + () => [ + { + accessorKey: "id", + header: "کد یکتا", + id: "id", + enableColumnFilter: false, + datatype: "text", + filterFn: "notEquals", + }, + { + accessorKey: "aplication_number", + header: "شماره درخواست", + id: "aplication_number", + enableColumnFilter: false, + datatype: "text", + filterFn: "notEquals", + }, + { + accessorKey: "application_date", + header: "تاریخ درخواست", + id: "application_date", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "province", + header: "استان", + id: "province", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "township", + header: "شهرستان", + id: "township", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "city", + header: "شهر", + id: "city", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "county", + header: "بخش", + id: "county", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "village", + header: "روستا", + id: "village", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "land_area", + header: "مساحت زمین", + id: "land_area", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "design_area", + header: "مساحت طرح", + id: "design_area", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "organization", + header: "سازمان", + id: "organization", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "design_group", + header: "گروه طرح", + id: "design_group", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "design_title", + header: "عنوان طرح", + id: "design_title", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "state", + header: "وضعیت درخواست", + id: "state", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + ], + [] + ); + + return ( + <> + + + + + ); +}; +export default TaskList; diff --git a/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/index.jsx b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/index.jsx new file mode 100644 index 0000000..a8609f8 --- /dev/null +++ b/src/components/dashboard/inquiryPrivacy/provinceAdmin/zaminGov/index.jsx @@ -0,0 +1,15 @@ +"use client"; + +import PageTitle from "@/core/components/PageTitle"; +import { Stack } from "@mui/material"; +import TaskList from "./TaskList"; + +const ProvinceAdminZaminGovComponent = () => { + return ( + + + + + ); +}; +export default ProvinceAdminZaminGovComponent; diff --git a/src/components/dashboard/inquiryPrivacyFencing/Actions/Create/index.jsx b/src/components/dashboard/inquiryPrivacyFencing/Actions/Create/index.jsx index de81370..a564394 100644 --- a/src/components/dashboard/inquiryPrivacyFencing/Actions/Create/index.jsx +++ b/src/components/dashboard/inquiryPrivacyFencing/Actions/Create/index.jsx @@ -27,12 +27,7 @@ const InquiryPrivacyFencingCreate = ({ mutate }) => { ) : ( - )} diff --git a/src/components/dashboard/inquiryPrivacyFencing/Forms/CreateOrUpdate.jsx b/src/components/dashboard/inquiryPrivacyFencing/Forms/CreateOrUpdate.jsx index 435f39b..f3483ae 100644 --- a/src/components/dashboard/inquiryPrivacyFencing/Forms/CreateOrUpdate.jsx +++ b/src/components/dashboard/inquiryPrivacyFencing/Forms/CreateOrUpdate.jsx @@ -1,7 +1,21 @@ import LtrTextField from "@/core/components/LtrTextField"; import StyledForm from "@/core/components/StyledForm"; import useRequest from "@/lib/hooks/useRequest"; -import { Autocomplete, Box, Button, Chip, Container, DialogActions, DialogContent, Fade, Grid, InputAdornment, Stack, TextField, Typography } from "@mui/material"; +import { + Autocomplete, + Box, + Button, + Chip, + Container, + DialogActions, + DialogContent, + Fade, + Grid, + InputAdornment, + Stack, + TextField, + Typography, +} from "@mui/material"; import { DatePicker, LocalizationProvider, faIR } from "@mui/x-date-pickers"; import { AdapterDateFnsJalali } from "@mui/x-date-pickers/AdapterDateFnsJalali"; import moment from "jalali-moment"; @@ -9,130 +23,135 @@ import { Controller, useForm } from "react-hook-form"; import LocationOnMap from "./LocationOnMap"; const initValues = { - dabirkhaneh_number: '', + dabirkhaneh_number: "", nameh_date: moment(), - nameh_date_fa: '', - marjae_pasokh: '', + nameh_date_fa: "", + marjae_pasokh: "", motaghazi_is_legal_id: null, - motaghazi_is_legal: '', - motaghazi_type_id: '', + motaghazi_is_legal: "", + motaghazi_type_id: "", motaghazi_type: null, - motaghazi_firstname: '', - motaghazi_lastname: '', - national_id: '', - shenase_melli: '', - tel_number: '', - mobile_number: '', - address: '', + motaghazi_firstname: "", + motaghazi_lastname: "", + national_id: "", + shenase_melli: "", + tel_number: "", + mobile_number: "", + address: "", edare_kol_id: null, - edare_kol: '', + edare_kol: "", edare_shahri_id: null, - edare_shahri: '', + edare_shahri: "", rah_type_id: null, - rah_type: '', - name_mehvar_id: '', + rah_type: "", + name_mehvar_id: "", name_mehvar_fa: null, mizan_harim: null, arze_navar: null, samt_id: null, - samt: '', - kilometr: '', - lat: '', - lon: '', + samt: "", + kilometr: "", + lat: "", + lon: "", zone: null, karbari_type_id: null, - karbari_type: '', - tarh_title: '', - masahat_zirbana: '', + karbari_type: "", + tarh_title: "", + masahat_zirbana: "", ehdasat_type_id: [], - ehdasat_type: '', - divarkeshi_distance: '', - mostahadesat_distance: '', + ehdasat_type: "", + divarkeshi_distance: "", + mostahadesat_distance: "", mahale_ejra_id: null, - mahale_ejra: '', + mahale_ejra: "", traffic_id: null, - traffic: '', + traffic: "", vaziat_eghtesadi_id: null, - vaziat_eghtesadi: '', + vaziat_eghtesadi: "", has_access_id: null, - has_access: '', - shomare_estelam_harim: '', - max_month: '', - max_day: '', - shomare_tahaodname: '', - shomare_daftarkhaneh: '', - description: '', - ronevesht: '', -} + has_access: "", + shomare_estelam_harim: "", + max_month: "", + max_day: "", + shomare_tahaodname: "", + shomare_daftarkhaneh: "", + description: "", + ronevesht: "", +}; const CreateOrUpdateForm = ({ handleClose, mutate, defaultValues, url }) => { - const request = useRequest() - const { control, watch, register, handleSubmit, setValue, formState: { isSubmitting } } = useForm({ defaultValues: defaultValues || initValues }); + const request = useRequest(); + const { + control, + watch, + register, + handleSubmit, + setValue, + formState: { isSubmitting }, + } = useForm({ defaultValues: defaultValues || initValues }); const onSubmit = async (data) => { - const formData = new FormData() - formData.append('dabirkhaneh_number', data.dabirkhaneh_number) - formData.append('nameh_date', data.nameh_date.format('YYYY-MM-DD')) - formData.append('nameh_date_fa', data.nameh_date) - formData.append('marjae_pasokh', data.marjae_pasokh) - formData.append('motaghazi_is_legal_id', data.motaghazi_is_legal_id) - formData.append('motaghazi_is_legal', data.motaghazi_is_legal_id) - formData.append('motaghazi_type_id', 1) - formData.append('motaghazi_type', data.motaghazi_type) - formData.append('motaghazi_firstname', data.motaghazi_firstname) - formData.append('motaghazi_lastname', data.motaghazi_lastname) - formData.append('national_id', data.national_id) - formData.append('shenase_melli', data.national_id) - formData.append('tel_number', data.tel_number) - formData.append('mobile_number', data.mobile_number) - formData.append('address', data.address) - formData.append('edare_kol_id', data.edare_kol_id) - formData.append('edare_kol', data.edare_kol_id) - formData.append('edare_shahri_id', data.edare_shahri_id) - formData.append('edare_shahri', data.edare_shahri_id) - formData.append('rah_type_id', data.rah_type_id) - formData.append('rah_type', data.rah_type_id) - formData.append('name_mehvar_id', 1) - formData.append('name_mehvar_fa', data.name_mehvar_fa) - formData.append('mizan_harim', data.mizan_harim) - formData.append('arze_navar', data.arze_navar) - formData.append('samt_id', data.samt_id) - formData.append('samt', data.samt_id) - formData.append('kilometr', data.kilometr) - formData.append('lat', data.lat) - formData.append('lon', data.lon) - formData.append('zone', data.zone) - formData.append('karbari_type_id', data.karbari_type_id) - formData.append('karbari_type', data.karbari_type_id) - formData.append('tarh_title', data.tarh_title) - formData.append('masahat_zirbana', data.masahat_zirbana) - formData.append('ehdasat_type_id', data.ehdasat_type_id.join("|")) - formData.append('ehdasat_type', data.ehdasat_type_id.join("|")) - formData.append('divarkeshi_distance', data.divarkeshi_distance) - formData.append('mostahadesat_distance', data.mostahadesat_distance) - formData.append('mahale_ejra_id', data.mahale_ejra_id) - formData.append('mahale_ejra', data.mahale_ejra) - formData.append('traffic_id', data.traffic_id) - formData.append('traffic', data.traffic_id) - formData.append('vaziat_eghtesadi_id', data.vaziat_eghtesadi_id) - formData.append('vaziat_eghtesadi', data.vaziat_eghtesadi) - formData.append('has_access_id', data.has_access_id) - formData.append('has_access', data.has_access_id) - formData.append('shomare_estelam_harim', data.shomare_estelam_harim) - formData.append('max_month', data.max_month) - formData.append('max_day', data.max_day) - formData.append('shomare_tahaodname', data.shomare_tahaodname) - formData.append('shomare_daftarkhaneh', data.shomare_daftarkhaneh) - formData.append('description', data.description) - formData.append('ronevesht', data.ronevesht) + const formData = new FormData(); + formData.append("dabirkhaneh_number", data.dabirkhaneh_number); + formData.append("nameh_date", data.nameh_date.format("YYYY-MM-DD")); + formData.append("nameh_date_fa", data.nameh_date); + formData.append("marjae_pasokh", data.marjae_pasokh); + formData.append("motaghazi_is_legal_id", data.motaghazi_is_legal_id); + formData.append("motaghazi_is_legal", data.motaghazi_is_legal_id); + formData.append("motaghazi_type_id", 1); + formData.append("motaghazi_type", data.motaghazi_type); + formData.append("motaghazi_firstname", data.motaghazi_firstname); + formData.append("motaghazi_lastname", data.motaghazi_lastname); + formData.append("national_id", data.national_id); + formData.append("shenase_melli", data.national_id); + formData.append("tel_number", data.tel_number); + formData.append("mobile_number", data.mobile_number); + formData.append("address", data.address); + formData.append("edare_kol_id", data.edare_kol_id); + formData.append("edare_kol", data.edare_kol_id); + formData.append("edare_shahri_id", data.edare_shahri_id); + formData.append("edare_shahri", data.edare_shahri_id); + formData.append("rah_type_id", data.rah_type_id); + formData.append("rah_type", data.rah_type_id); + formData.append("name_mehvar_id", 1); + formData.append("name_mehvar_fa", data.name_mehvar_fa); + formData.append("mizan_harim", data.mizan_harim); + formData.append("arze_navar", data.arze_navar); + formData.append("samt_id", data.samt_id); + formData.append("samt", data.samt_id); + formData.append("kilometr", data.kilometr); + formData.append("lat", data.lat); + formData.append("lon", data.lon); + formData.append("zone", data.zone); + formData.append("karbari_type_id", data.karbari_type_id); + formData.append("karbari_type", data.karbari_type_id); + formData.append("tarh_title", data.tarh_title); + formData.append("masahat_zirbana", data.masahat_zirbana); + formData.append("ehdasat_type_id", data.ehdasat_type_id.join("|")); + formData.append("ehdasat_type", data.ehdasat_type_id.join("|")); + formData.append("divarkeshi_distance", data.divarkeshi_distance); + formData.append("mostahadesat_distance", data.mostahadesat_distance); + formData.append("mahale_ejra_id", data.mahale_ejra_id); + formData.append("mahale_ejra", data.mahale_ejra); + formData.append("traffic_id", data.traffic_id); + formData.append("traffic", data.traffic_id); + formData.append("vaziat_eghtesadi_id", data.vaziat_eghtesadi_id); + formData.append("vaziat_eghtesadi", data.vaziat_eghtesadi); + formData.append("has_access_id", data.has_access_id); + formData.append("has_access", data.has_access_id); + formData.append("shomare_estelam_harim", data.shomare_estelam_harim); + formData.append("max_month", data.max_month); + formData.append("max_day", data.max_day); + formData.append("shomare_tahaodname", data.shomare_tahaodname); + formData.append("shomare_daftarkhaneh", data.shomare_daftarkhaneh); + formData.append("description", data.description); + formData.append("ronevesht", data.ronevesht); try { - await request(url, 'post', { data: formData }) - handleClose() - mutate() - } catch (error) { - - } + await request(url, "post", { data: formData }); + handleClose(); + mutate(); + } catch (error) {} }; return ( @@ -141,11 +160,18 @@ const CreateOrUpdateForm = ({ handleClose, mutate, defaultValues, url }) => { localeText={faIR.components.MuiLocalizationProvider.defaultProps.localeText} > - - + + - + { onChange={(newValue) => onChange(moment(newValue))} label="تاریخ نامه درخواست *" slotProps={{ - textField: { fullWidth: true, size: "small", autoComplete: 'off' }, + textField: { fullWidth: true, size: "small", autoComplete: "off" }, }} /> )} /> - + { disablePortal value={value} onChange={(event, newValue) => { - onChange(newValue) + onChange(newValue); }} options={["حقوقی", "حقیقی"]} - renderInput={(params) => } + renderInput={(params) => ( + + )} /> )} /> - + { disablePortal value={value} onChange={(event, newValue) => { - onChange(newValue) + onChange(newValue); }} options={["دولتی", "خصوصی"]} - renderInput={(params) => } + renderInput={(params) => ( + + )} /> )} /> @@ -208,26 +253,76 @@ const CreateOrUpdateForm = ({ handleClose, mutate, defaultValues, url }) => { - + - - + + - + - + - - + + - + { disablePortal value={value} onChange={(event, newValue) => { - onChange(newValue) + onChange(newValue); }} options={["تهران"]} renderInput={(params) => ( - { disablePortal value={value} onChange={(event, newValue) => { - onChange(newValue) + onChange(newValue); }} options={["تهران"]} - renderInput={(params) => } + renderInput={(params) => ( + + )} /> )} /> @@ -281,10 +384,12 @@ const CreateOrUpdateForm = ({ handleClose, mutate, defaultValues, url }) => { disablePortal value={value} onChange={(event, newValue) => { - onChange(newValue) + onChange(newValue); }} - options={["آزاد راه", "بزرگراه", 'راه فرعی درجه 3']} - renderInput={(params) => } + options={["آزاد راه", "بزرگراه", "راه فرعی درجه 3"]} + renderInput={(params) => ( + + )} /> )} /> @@ -299,16 +404,23 @@ const CreateOrUpdateForm = ({ handleClose, mutate, defaultValues, url }) => { disablePortal value={value} onChange={(event, newValue) => { - onChange(newValue) + onChange(newValue); }} options={["سایر"]} - renderInput={(params) => } + renderInput={(params) => ( + + )} /> )} /> - + @@ -322,10 +434,12 @@ const CreateOrUpdateForm = ({ handleClose, mutate, defaultValues, url }) => { disablePortal value={value} onChange={(event, newValue) => { - onChange(newValue) + onChange(newValue); }} options={["چپ", "راست"]} - renderInput={(params) => } + renderInput={(params) => ( + + )} /> )} /> @@ -340,16 +454,27 @@ const CreateOrUpdateForm = ({ handleClose, mutate, defaultValues, url }) => { disablePortal value={value} onChange={(event, newValue) => { - onChange(newValue) + onChange(newValue); }} options={["12.5", "17.5"]} - renderInput={(params) => } + renderInput={(params) => ( + + )} /> )} /> - + { disablePortal value={value} onChange={(event, newValue) => { - onChange(newValue) + onChange(newValue); }} options={["15", "30"]} - renderInput={(params) => } + renderInput={(params) => ( + + )} /> )} /> @@ -371,15 +503,40 @@ const CreateOrUpdateForm = ({ handleClose, mutate, defaultValues, url }) => { - + - + - - + + { disablePortal value={value} onChange={(event, newValue) => { - onChange(newValue) + onChange(newValue); }} options={["38", "39"]} - renderInput={(params) => } + renderInput={(params) => ( + + )} /> )} /> @@ -408,22 +572,42 @@ const CreateOrUpdateForm = ({ handleClose, mutate, defaultValues, url }) => { disablePortal value={value} onChange={(event, newValue) => { - onChange(newValue) + onChange(newValue); }} options={["اتاقک نگهبانی", "دولتی"]} - renderInput={(params) => } + renderInput={(params) => ( + + )} /> )} /> - + - - مترمربع, - }} /> + مترمربع, + }} + /> { disablePortal value={value} onChange={(event, newValue) => { - onChange(newValue) + onChange(newValue); }} renderTags={(value, getTagProps) => value.map((option, index) => { const { key, ...tagProps } = getTagProps({ index }); return ( - + ); }) } options={["تعمیرات", "احداث بنا"]} - renderInput={(params) => } + renderInput={(params) => ( + + )} /> )} /> - متر, - }} /> + متر, + }} + /> - متر, - }} /> + متر, + }} + /> { disablePortal value={value} onChange={(event, newValue) => { - onChange(newValue) + onChange(newValue); }} options={["داخل حریم"]} - renderInput={(params) => } + renderInput={(params) => ( + + )} /> )} /> @@ -490,10 +705,17 @@ const CreateOrUpdateForm = ({ handleClose, mutate, defaultValues, url }) => { disablePortal value={value} onChange={(event, newValue) => { - onChange(newValue) + onChange(newValue); }} options={["سبک (ضریب ۱)"]} - renderInput={(params) => } + renderInput={(params) => ( + + )} /> )} /> @@ -508,10 +730,17 @@ const CreateOrUpdateForm = ({ handleClose, mutate, defaultValues, url }) => { disablePortal value={value} onChange={(event, newValue) => { - onChange(newValue) + onChange(newValue); }} options={["تست"]} - renderInput={(params) => } + renderInput={(params) => ( + + )} /> )} /> @@ -526,46 +755,115 @@ const CreateOrUpdateForm = ({ handleClose, mutate, defaultValues, url }) => { disablePortal value={value} onChange={(event, newValue) => { - onChange(newValue) + onChange(newValue); }} options={["بله", "خیر"]} - renderInput={(params) => } + renderInput={(params) => ( + + )} /> )} /> - + - - حداکثر مدت زمان شروع عملیات: * - - + + + حداکثر مدت زمان شروع عملیات: * + + + - + - + - + - + - - + + - + ); }; export default CreateOrUpdateForm; diff --git a/src/components/dashboard/inquiryPrivacyFencing/Forms/LocationOnMap/MarkerLocation/index.jsx b/src/components/dashboard/inquiryPrivacyFencing/Forms/LocationOnMap/MarkerLocation/index.jsx index d673679..c79c266 100644 --- a/src/components/dashboard/inquiryPrivacyFencing/Forms/LocationOnMap/MarkerLocation/index.jsx +++ b/src/components/dashboard/inquiryPrivacyFencing/Forms/LocationOnMap/MarkerLocation/index.jsx @@ -12,21 +12,26 @@ const MarkerLocation = ({ setValue, defaultLatLon }) => { const location = useRef(); const map = useMapEvents({ move: (e) => { - const latlon = e.target.getCenter() + const latlon = e.target.getCenter(); location.current?.setLatLng(latlon); - setValue('lat', latlon.lat) - setValue('lon', latlon.lng) + setValue("lat", latlon.lat); + setValue("lon", latlon.lng); }, zoom: (e) => { - const latlon = e.target.getCenter() + const latlon = e.target.getCenter(); location.current?.setLatLng(latlon); - setValue('lat', latlon.lat) - setValue('lon', latlon.lng) + setValue("lat", latlon.lat); + setValue("lon", latlon.lng); }, }); return ( - - ) -} -export default MarkerLocation \ No newline at end of file + + ); +}; +export default MarkerLocation; diff --git a/src/components/dashboard/inquiryPrivacyFencing/Forms/LocationOnMap/index.jsx b/src/components/dashboard/inquiryPrivacyFencing/Forms/LocationOnMap/index.jsx index fe65106..dfd8854 100644 --- a/src/components/dashboard/inquiryPrivacyFencing/Forms/LocationOnMap/index.jsx +++ b/src/components/dashboard/inquiryPrivacyFencing/Forms/LocationOnMap/index.jsx @@ -11,12 +11,12 @@ const MapLayer = dynamic(() => import("@/core/components/MapLayer"), { const LocationOnMap = ({ setValue, defaultLatLon }) => { return ( - - + + - ) -} -export default LocationOnMap \ No newline at end of file + ); +}; +export default LocationOnMap; diff --git a/src/components/dashboard/inquiryPrivacyFencing/Toolbar.jsx b/src/components/dashboard/inquiryPrivacyFencing/Toolbar.jsx index 73cee6d..843492b 100644 --- a/src/components/dashboard/inquiryPrivacyFencing/Toolbar.jsx +++ b/src/components/dashboard/inquiryPrivacyFencing/Toolbar.jsx @@ -1,7 +1,6 @@ import InquiryPrivacyFencingCreate from "./Actions/Create"; const Toolbar = ({ mutate }) => { - return ( <> diff --git a/src/components/dashboard/inquiryPrivacyFencing/index.jsx b/src/components/dashboard/inquiryPrivacyFencing/index.jsx index c8dd8c9..794be55 100644 --- a/src/components/dashboard/inquiryPrivacyFencing/index.jsx +++ b/src/components/dashboard/inquiryPrivacyFencing/index.jsx @@ -6,11 +6,10 @@ import { Stack } from "@mui/material"; const InquiryPrivacyFencingPage = () => { return ( - + ); }; export default InquiryPrivacyFencingPage; - diff --git a/src/components/dashboard/inquiryPrivacyFencing/inquiryPrivacyFencingList/index.jsx b/src/components/dashboard/inquiryPrivacyFencing/inquiryPrivacyFencingList/index.jsx index 86a2840..24871ed 100644 --- a/src/components/dashboard/inquiryPrivacyFencing/inquiryPrivacyFencingList/index.jsx +++ b/src/components/dashboard/inquiryPrivacyFencing/inquiryPrivacyFencingList/index.jsx @@ -231,12 +231,12 @@ const InquiryPrivacyFencingList = () => { enableColumnFilter: false, }, ], - [], + [] ); return ( <> - + { ); }; export default InquiryPrivacyFencingList; - diff --git a/src/components/dashboard/test/Actions/create/CreateDialog/ChooseLocation.jsx b/src/components/dashboard/test/Actions/create/CreateDialog/ChooseLocation.jsx new file mode 100644 index 0000000..433543e --- /dev/null +++ b/src/components/dashboard/test/Actions/create/CreateDialog/ChooseLocation.jsx @@ -0,0 +1,162 @@ +"use client"; + +import {Marker, useMapEvents} from "react-leaflet"; +import {useEffect, useRef} from "react"; +import L from "leaflet"; +import TestIcon from "@/assets/images/examine_marker.png"; +import TestActiveIcon from "@/assets/images/examine_marker_active.png"; +import { + Box, + Button, + FormControl, + InputAdornment, + InputLabel, + OutlinedInput, + Stack, + Tooltip, + useMediaQuery +} from "@mui/material"; +import NewReleasesIcon from '@mui/icons-material/NewReleases'; +import VerifiedIcon from '@mui/icons-material/Verified'; +import EditIcon from '@mui/icons-material/Edit'; +import {useTheme} from "@emotion/react"; + +const ChooseLocation = ({mapBoxData, setMapBoxData}) => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down("sm")); + + const mapTestMarker = useRef(); + const defaultIconSize = [35, 35]; + const createCustomIcon = (size, iconUrl) => { + return L.icon({ + iconUrl: iconUrl, + iconSize: size, + iconAnchor: [size[0] / 2, size[1]], + popupAnchor: [0, -size[1]] + }); + }; + + const map = useMapEvents({ + move(e) { + if (!mapBoxData) { + mapTestMarker.current.setLatLng(e.target.getCenter()); + } + }, + movestart() { + if (!mapBoxData) { + mapTestMarker.current.setIcon(createCustomIcon([45, 45], TestIcon.src)); + } + }, + moveend() { + if (!mapBoxData) { + mapTestMarker.current.setIcon(createCustomIcon(defaultIconSize, TestIcon.src)); + } + } + }); + + useEffect(() => { + if (mapTestMarker.current) { + const newIcon = mapBoxData + ? createCustomIcon([45, 45], TestActiveIcon.src) + : createCustomIcon(defaultIconSize, TestIcon.src); + mapTestMarker.current.setIcon(newIcon); + } + if (mapBoxData) { + mapTestMarker.current.setLatLng(mapBoxData); + map.flyTo(mapBoxData, 14); + } + }, [mapBoxData]); + + const handleMarkerClick = () => { + if (!mapBoxData) { + setMapBoxData({lat: mapTestMarker.current.getLatLng().lat, lng: mapTestMarker.current.getLatLng().lng}); + } + }; + + const handleEditLocation = () => { + setMapBoxData(null); + } + + return ( + <> + + + + + + + طول جغرافیایی + + + {mapBoxData ? : + } + + } + label="طول جغرافیایی" + /> + + + + + + عرض جغرافیایی + + + {mapBoxData ? : + } + + } + label="عرض جغرافیایی" + /> + + + + + + + ); +}; + +export default ChooseLocation; \ No newline at end of file diff --git a/src/components/dashboard/test/Actions/create/CreateDialog/CreateTimeLine.jsx b/src/components/dashboard/test/Actions/create/CreateDialog/CreateTimeLine.jsx new file mode 100644 index 0000000..49a7d90 --- /dev/null +++ b/src/components/dashboard/test/Actions/create/CreateDialog/CreateTimeLine.jsx @@ -0,0 +1,59 @@ +"use client"; + +import {Box, Typography} from "@mui/material"; +import TextSnippetIcon from '@mui/icons-material/TextSnippet'; +import TravelExploreIcon from '@mui/icons-material/TravelExplore'; +import { + Timeline, + TimelineConnector, + TimelineContent, + TimelineDot, + TimelineItem, + timelineItemClasses, + TimelineSeparator +} from "@mui/lab"; + +const CreateTimeLine = ({tabState}) => { + return ( + + + + + + + + + + + + + نقشه + + ثبت مختصات محل + آزمایش + + + + + + + + + + + + + مشخصات آزمایش + + ثبت مشخصات اولیه + + + + + ); +}; +export default CreateTimeLine; diff --git a/src/components/dashboard/test/Actions/create/CreateDialog/MapBox.jsx b/src/components/dashboard/test/Actions/create/CreateDialog/MapBox.jsx new file mode 100644 index 0000000..8b1611c --- /dev/null +++ b/src/components/dashboard/test/Actions/create/CreateDialog/MapBox.jsx @@ -0,0 +1,39 @@ +"use client"; + +import {Box, Stack} from "@mui/material"; +import dynamic from "next/dynamic"; +import MapLoading from "@/core/components/MapLayer/Loading"; +import ChooseLocation from "./ChooseLocation"; + +const MapLayer = dynamic(() => import("@/core/components/MapLayer"), { + loading: () => , + ssr: false, +}); + +const MapBox = ({mapBoxData, setMapBoxData}) => { + return ( + + + + + + + + + + ); +}; +export default MapBox; diff --git a/src/components/dashboard/test/Actions/create/CreateDialog/TestGeneralInfo.jsx b/src/components/dashboard/test/Actions/create/CreateDialog/TestGeneralInfo.jsx new file mode 100644 index 0000000..d424a1a --- /dev/null +++ b/src/components/dashboard/test/Actions/create/CreateDialog/TestGeneralInfo.jsx @@ -0,0 +1,387 @@ +"use client"; + +import {Controller} from "react-hook-form"; +import { + Autocomplete, + CircularProgress, + FormControl, + FormHelperText, + Grid, + IconButton, + InputAdornment, + InputLabel, + OutlinedInput, + TextField, + Typography +} from "@mui/material"; +import useTest from "@/lib/hooks/useTest"; +import useProvinces from "@/lib/hooks/useProvince"; +import {LocalizationProvider, MobileDatePicker} from "@mui/x-date-pickers"; +import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali"; +import {faIR} from "@mui/x-date-pickers/locales"; +import ClearIcon from "@mui/icons-material/Clear"; +import React from "react"; + +const TestGeneralInfo = ({control, register, setValue, errors}) => { + const {tests, errorTests, loadingTests} = useTest(); + const {provinces, errorProvinces, loadingProvinces} = useProvinces(); + + return ( + + + ( + + + {errorTests ? ( + + خطایی در دریافت لیست آزمایش ها رخ داده است! + + ) : loadingTests ? ( + + + درحال دریافت لیست آزمایش ها + + ) : ( + test.id === value) || null} + disablePortal + options={tests} + getOptionLabel={(test) => test.name} + isOptionEqualToValue={(option, value) => option.id === value?.id} + onChange={(event, newValue) => { + onChange(newValue ? newValue.id : ""); + setValue("azmayesh_type_name", newValue ? newValue.name : ""); + }} + renderInput={(params) => ( + + )} + /> + )} + + {errors.azmayesh_type_id ? errors.azmayesh_type_id.message : null} + + + )} + /> + + + ( + + + {errorProvinces ? ( + + خطایی در دریافت لیست استان ها رخ داده است! + + ) : loadingProvinces ? ( + + + درحال دریافت لیست استان ها + + ) : ( + province.id === value) || null} + disablePortal + options={provinces} + getOptionLabel={(province) => province.name} + isOptionEqualToValue={(option, value) => option.id === value?.id} + onChange={(event, newValue) => { + onChange(newValue ? newValue.id : ""); + setValue("province_name", newValue ? newValue.name : ""); + }} + renderInput={(params) => ( + + )} + /> + )} + + {errors.province_id ? errors.province_id.message : null} + + + )} + /> + + + + + پروژه + + + + {errors.project_name ? errors.project_name.message : null} + + + + + + + کارفرما + + + + {errors.employer ? errors.employer.message : null} + + + + + + + مشاور + + + + {errors.consultant ? errors.consultant.message : null} + + + + + + + پیمانکار + + + + {errors.contractor ? errors.contractor.message : null} + + + + + + + متقاضی + + + + {errors.applicant ? errors.applicant.message : null} + + + + + + + شماره کار + + + + {errors.work_number ? errors.work_number.message : null} + + + + + + + شماره درخواست + + + + {errors.request_number ? errors.request_number.message : null} + + + + + ( + + + { + onChange(newValue); + }} + slotProps={{ + textField: { + size: "small", + error: !!errors.request_date, + placeholder: "تاریخ درخواست", + InputProps: { + endAdornment: ( + + { + event.stopPropagation(); + setValue("request_date", ""); + }} + sx={{ + color: "#bfbfbf", + "&:hover": { + backgroundColor: "rgba(189, 189, 189, 0.1)", + color: "#363434", + }, + }} + > + + + + ), + }, + }, + }} + /> + + + {errors.request_date ? errors.request_date.message : null} + + + )} + /> + + + ( + + + { + onChange(newValue); + }} + slotProps={{ + textField: { + size: "small", + error: !!errors.report_date, + placeholder: "تاریخ گزارش", + InputProps: { + endAdornment: ( + + { + event.stopPropagation(); + setValue("report_date", ""); + }} + sx={{ + color: "#bfbfbf", + "&:hover": { + backgroundColor: "rgba(189, 189, 189, 0.1)", + color: "#363434", + }, + }} + > + + + + ), + }, + }, + }} + /> + + + {errors.report_date ? errors.report_date.message : null} + + + )} + /> + + + ); +}; +export default TestGeneralInfo; \ No newline at end of file diff --git a/src/components/dashboard/test/Actions/create/CreateDialog/index.jsx b/src/components/dashboard/test/Actions/create/CreateDialog/index.jsx new file mode 100644 index 0000000..f52c42a --- /dev/null +++ b/src/components/dashboard/test/Actions/create/CreateDialog/index.jsx @@ -0,0 +1,187 @@ +"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 useRequest from "@/lib/hooks/useRequest"; +import {yupResolver} from "@hookform/resolvers/yup"; +import moment from "jalali-moment"; +import {POST_TEST} from "@/core/utils/routes"; +import TestGeneralInfo from "@/components/dashboard/test/Actions/create/CreateDialog/TestGeneralInfo"; + +function TabPanel(props) { + const {children, value, index} = props; + + return ( + + ); +} + +const CreateDialog = ({open, setOpen}) => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down("sm")); + const [tabState, setTabState] = useState(0); + const [mapBoxData, setMapBoxData] = useState(null); + + const handleClose = () => { + setOpen(false); + }; + + const handleChangeTab = (event, newValue) => { + setTabState(newValue); + }; + + const handlePrev = () => { + if (tabState === 0) { + handleClose(); + } else { + setTabState(tabState - 1) + } + }; + + 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: "", + }; + + const { + control, + register, + handleSubmit, + setValue, + formState: {isSubmitting, errors, touchedFields}, + } = useForm({defaultValues, resolver: yupResolver(validationSchema), mode: "onBlur"}); + + const onSubmit = async (data) => { + console.log("data", data); + const formData = new FormData(); + formData.append("lat", mapBoxData.lat); + formData.append("lng", mapBoxData.lng); + formData.append("azmayesh_type_id", data.azmayesh_type_id); + formData.append("azmayesh_type_name", data.azmayesh_type_name); + formData.append("province_id", data.province_id); + formData.append("province_name", data.province_name); + formData.append("project_name", data.project_name); + formData.append("employer", data.employer); + formData.append("consultant", data.consultant); + formData.append("contractor", data.contractor); + 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")); + + for (var pair of formData.entries()) { + console.log(pair[0] + ', ' + pair[1]); + } + + requestServer(POST_TEST, "post", { + data: formData, + }) + .then(() => { + handleClose(); + }) + .catch(() => { + }); + }; + + return ( + + + + } label="انتخاب محل آزمایش"> + } label="مشخصات آزمایش"> + + + + + + + + + + + {!isMobile && ( + + + + )} + + + + { + tabState === 0 ? : + } + + + + ); +}; +export default CreateDialog; diff --git a/src/components/dashboard/test/Actions/create/index.jsx b/src/components/dashboard/test/Actions/create/index.jsx new file mode 100644 index 0000000..9d59d00 --- /dev/null +++ b/src/components/dashboard/test/Actions/create/index.jsx @@ -0,0 +1,33 @@ +"use client"; + +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"; + +const TestCreate = () => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down("sm")); + const [open, setOpen] = useState(false); + + const handleOpen = () => { + setOpen(true); + }; + + return ( + <> + {isMobile ? ( + + + + ) : ( + + )} + {open && } + + ); +}; +export default TestCreate; diff --git a/src/components/dashboard/test/ShowLocation/ShowLocationMarker.jsx b/src/components/dashboard/test/ShowLocation/ShowLocationMarker.jsx new file mode 100644 index 0000000..6b65250 --- /dev/null +++ b/src/components/dashboard/test/ShowLocation/ShowLocationMarker.jsx @@ -0,0 +1,105 @@ +"use client"; + +import {Marker, useMap} from "react-leaflet"; +import {useEffect, useRef} from "react"; +import L from "leaflet"; +import TestActiveIcon from "@/assets/images/examine_marker_active.png"; +import {Box, FormControl, InputAdornment, InputLabel, OutlinedInput, Stack, useMediaQuery} from "@mui/material"; +import VerifiedIcon from '@mui/icons-material/Verified'; +import {useTheme} from "@emotion/react"; + +const ShowLocationMarker = ({lat, lng}) => { + const map = useMap(); + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down("sm")); + + const mapTestMarker = useRef(); + const defaultIconSize = [35, 35]; + const createCustomIcon = (size, iconUrl) => { + return L.icon({ + iconUrl: iconUrl, + iconSize: size, + iconAnchor: [size[0] / 2, size[1]], + popupAnchor: [0, -size[1]] + }); + }; + + useEffect(() => { + map.flyTo({lat: lat, lng: lng}, 14); + }, []); + + + return ( + <> + + + + + + طول جغرافیایی + + + + + } + label="طول جغرافیایی" + /> + + + + عرض جغرافیایی + + + + + } + label="عرض جغرافیایی" + /> + + + + + ); +}; + +export default ShowLocationMarker; \ No newline at end of file diff --git a/src/components/dashboard/test/ShowLocation/index.jsx b/src/components/dashboard/test/ShowLocation/index.jsx new file mode 100644 index 0000000..557a780 --- /dev/null +++ b/src/components/dashboard/test/ShowLocation/index.jsx @@ -0,0 +1,50 @@ +"use client"; + +import ExploreIcon from "@mui/icons-material/Explore"; +import {Box, Button, Dialog, DialogActions, DialogContent, IconButton} from "@mui/material"; +import {useState} from "react"; +import dynamic from "next/dynamic"; +import MapLoading from "@/core/components/MapLayer/Loading"; +import ShowLocationMarker from "./ShowLocationMarker"; + +const MapLayer = dynamic(() => import("@/core/components/MapLayer"), { + loading: () => , + ssr: false, +}); + +const ShowLocation = ({lat, lng}) => { + const [openShowLocationModal, setOpenShowLocationModal] = useState(false); + + const handleOpenShowLocationModal = () => { + setOpenShowLocationModal(true); + }; + + const handleCloseShowLocationModal = () => { + setOpenShowLocationModal(false); + }; + + return ( + + + + + + + + + + + + + + + + ); +}; +export default ShowLocation; diff --git a/src/components/dashboard/test/TestList.jsx b/src/components/dashboard/test/TestList.jsx new file mode 100644 index 0000000..2c735f4 --- /dev/null +++ b/src/components/dashboard/test/TestList.jsx @@ -0,0 +1,135 @@ +"use client"; + +import {useMemo} from "react"; +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"; + +const TestList = () => { + const columns = useMemo( + () => [ + { + accessorKey: "id", + header: "کد یکتا", + id: "id", + enableColumnFilter: false, + datatype: "text", + filterFn: "notEquals", + }, + { + accessorKey: "azmayesh_type_name", + header: "نوع آزمایش", + id: "azmayesh_type_name", + enableColumnFilter: false, + datatype: "text", + filterFn: "notEquals", + }, + { + accessorKey: "project_name", + header: "پروژه", + id: "project_name", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "lat", + header: "نمایش مختصات", + id: "lat", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + Cell: ({row}) => (), + }, + { + accessorKey: "employer", + header: "کارفرما", + id: "employer", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "consultant", + header: "مشاور", + id: "consultant", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "contractor", + header: "پیمانکار", + id: "contractor", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "applicant", + header: "متقاضی", + id: "applicant", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "work_number", + header: "شماره کار", + id: "work_number", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "request_number", + header: "شماره درخواست", + id: "request_number", + enableColumnFilter: false, + datatype: "text", + filterFn: "equals", + }, + { + accessorKey: "request_date", + header: "تاریخ درخواست", + id: "request_date", + enableColumnFilter: false, + datatype: "date", + filterFn: "equals", + Cell: ({renderedCellValue}) => ({moment(renderedCellValue).locale("fa").format("YYYY/MM/DD")}), + }, + { + accessorKey: "report_date", + header: "تاریخ گزارش", + id: "report_date", + enableColumnFilter: false, + datatype: "date", + filterFn: "equals", + Cell: ({renderedCellValue}) => ({moment(renderedCellValue).locale("fa").format("YYYY/MM/DD")}), + }, + ], + [] + ); + + return ( + <> + + + + + ); +}; +export default TestList; diff --git a/src/components/dashboard/test/Toolbar.jsx b/src/components/dashboard/test/Toolbar.jsx new file mode 100644 index 0000000..8aaa0a9 --- /dev/null +++ b/src/components/dashboard/test/Toolbar.jsx @@ -0,0 +1,10 @@ +import TestCreate from "./Actions/Create"; + +const Toolbar = ({mutate}) => { + return ( + <> + + + ); +}; +export default Toolbar; diff --git a/src/components/dashboard/test/index.jsx b/src/components/dashboard/test/index.jsx new file mode 100644 index 0000000..d2503a0 --- /dev/null +++ b/src/components/dashboard/test/index.jsx @@ -0,0 +1,15 @@ +"use client"; + +import PageTitle from "@/core/components/PageTitle"; +import {Stack} from "@mui/material"; +import TestList from "./TestList"; + +const TestPage = () => { + return ( + + + + + ); +}; +export default TestPage; diff --git a/src/components/layouts/dashboard/headerWithLogo/HaederBottom/index.jsx b/src/components/layouts/dashboard/headerWithLogo/HaederBottom/index.jsx index f23833c..1ab9f22 100644 --- a/src/components/layouts/dashboard/headerWithLogo/HaederBottom/index.jsx +++ b/src/components/layouts/dashboard/headerWithLogo/HaederBottom/index.jsx @@ -15,9 +15,9 @@ const HeaderBottom = () => { alignItems={"center"} direction={"row"} > - + - theme.palette.primary2.contrastText }}> + theme.palette.primary2.contrastText }}> سامانه جامع راهداری theme.palette.primary2.contrastText }}>rms.rmto.ir diff --git a/src/components/layouts/dashboard/headerWithLogo/HaederTop/index.jsx b/src/components/layouts/dashboard/headerWithLogo/HaederTop/index.jsx index 2c0c3b6..4926625 100644 --- a/src/components/layouts/dashboard/headerWithLogo/HaederTop/index.jsx +++ b/src/components/layouts/dashboard/headerWithLogo/HaederTop/index.jsx @@ -5,7 +5,7 @@ import HeaderLogo from "@/assets/images/headerLogo.png"; const HeaderTop = () => { return ( - + ); }; diff --git a/src/components/layouts/dashboard/headerWithLogo/index.jsx b/src/components/layouts/dashboard/headerWithLogo/index.jsx index 2d0b7bc..9b59fa6 100644 --- a/src/components/layouts/dashboard/headerWithLogo/index.jsx +++ b/src/components/layouts/dashboard/headerWithLogo/index.jsx @@ -4,7 +4,7 @@ import HeaderBottom from "./HaederBottom"; const HeaderWithLogo = () => { return ( - + diff --git a/src/components/layouts/dashboard/headerWithSidebar/HeaderMenu/index.jsx b/src/components/layouts/dashboard/headerWithSidebar/HeaderMenu/index.jsx index c705242..47decdf 100644 --- a/src/components/layouts/dashboard/headerWithSidebar/HeaderMenu/index.jsx +++ b/src/components/layouts/dashboard/headerWithSidebar/HeaderMenu/index.jsx @@ -1,4 +1,45 @@ -const HeaderMenu = () => { - return <>منو; +import { ExpandLess, ExpandMore, Link } from "@mui/icons-material"; +import { Button, Divider, ListItemIcon, ListItemText, Menu, MenuItem } from "@mui/material"; +import NextLink from "next/link"; +import { useState } from "react"; + +const HeaderMenu = ({ menu }) => { + const [anchorEl, setAnchorEl] = useState(null); + const open = Boolean(anchorEl); + + const handleClick = (event) => { + setAnchorEl(event.currentTarget); + }; + const handleClose = () => { + setAnchorEl(null); + }; + + return ( + <> + + + {menu.subMenu.flatMap((subMenu, index) => [ + ...subMenu.map((sub) => ( + + + + + {sub.title} + + )), + index < menu.subMenu.length - 1 && , + ])} + + + ); }; + export default HeaderMenu; diff --git a/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarBadge.jsx b/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarBadge.jsx new file mode 100644 index 0000000..4ee1a83 --- /dev/null +++ b/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarBadge.jsx @@ -0,0 +1,19 @@ +import { getValueByPath } from "@/core/utils/getValueByPath"; +import { useSidebarBadge } from "@/lib/hooks/useSidebarBadge"; +import { Chip } from "@mui/material"; +import { useEffect, useState } from "react"; + +const SidebarBadge = ({ badge, chipProps = {} }) => { + const { data } = useSidebarBadge(); + const [value, setValue] = useState(); + + useEffect(() => { + setValue(getValueByPath(data, badge)); + }, [data, badge]); + + if (!data) return null; + if (!value) return null; + + return ; +}; +export default SidebarBadge; diff --git a/src/core/components/SidebarListItems.jsx b/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarListItems.jsx similarity index 78% rename from src/core/components/SidebarListItems.jsx rename to src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarListItems.jsx index 050d9a6..7b0aabc 100644 --- a/src/core/components/SidebarListItems.jsx +++ b/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarListItems.jsx @@ -1,14 +1,15 @@ -import SidebarSubitems from "@/core/components/SidebarSubitems"; import { ExpandLess, ExpandMore } from "@mui/icons-material"; -import { Collapse, List, ListItem, ListItemButton, ListItemIcon, ListItemText } from "@mui/material"; +import { Collapse, List, ListItem, ListItemButton, ListItemIcon, ListItemText, Stack } from "@mui/material"; import Link from "next/link"; +import SidebarBadge from "./SidebarBadge"; +import SidebarSubitems from "./SidebarSubitems"; const SidebarListItems = ({ menuItem, dispatch }) => { return ( <> { {menuItem.icon} + {menuItem.badges && ( + + {menuItem.badges.map((badge, i) => ( + + ))} + + )} {menuItem.hasSubitems ? menuItem.showSubitems ? : : null} diff --git a/src/core/components/SidebarMenu.jsx b/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarMenu.jsx similarity index 54% rename from src/core/components/SidebarMenu.jsx rename to src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarMenu.jsx index 625972a..4142b7f 100644 --- a/src/core/components/SidebarMenu.jsx +++ b/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarMenu.jsx @@ -1,11 +1,12 @@ "use client"; -import SidebarListItems from "@/core/components/SidebarListItems"; import { usePermissions } from "@/lib/hooks/usePermissions"; import { List } from "@mui/material"; import { usePathname } from "next/navigation"; import { useEffect, useReducer, useState } from "react"; -import { filterMenuItems } from "../utils/filterMenuItems"; -import { pageMenu } from "../utils/pageMenu"; +import Profile from "@/core/components/Profile"; +import { filterMenuItems } from "@/core/utils/filterMenuItems"; +import { pageMenu } from "@/core/utils/pageMenu"; +import SidebarListItems from "./SidebarListItems"; function selectPage(item, route) { if (item.type === "page") { @@ -25,60 +26,46 @@ function selectPage(item, route) { return item; } +function toggleSubitems(items, actionId) { + return items.map((item) => + actionId === item.id ? { ...item, showSubitems: !item.showSubitems } : { ...item, showSubitems: false } + ); +} + function reducer(state, action) { switch (action.type) { case "UPDATE_MENU": const _permissions = action.permissions || []; - const filteredPageMenu = filterMenuItems(state, ["all", ..._permissions]); - return filteredPageMenu; + return filterMenuItems(state, ["all", ..._permissions]); + case "COLLAPSE_MENU": - return state.map((item) => - action.id == item.id - ? { - ...item, - showSubitems: !item.showSubitems, - } - : item - ); + return state.map((item) => ({ + ...item, + showSubitems: item.id === action.id ? !item.showSubitems : false, + })); + case "COLLAPSE_SUB_ITEMS": - return state.map((item) => { - return item.hasSubitems + return state.map((item) => + item.hasSubitems ? { ...item, Subitems: toggleSubitems(item.Subitems, action.id) } : item + ); + + case "COLLAPSE_SUB_SECOND_ITEMS": + return state.map((item) => + item.hasSubitems ? { ...item, Subitems: item.Subitems.map((subitem) => - action.id === subitem.id + subitem.hasSubitems ? { ...subitem, - showSubitems: !subitem.showSubitems, + Subitems: toggleSubitems(subitem.Subitems, action.id), } : subitem ), } - : item; - }); - case "COLLAPSE_SUB_SECOND_ITEMS": - return state.map((item) => { - return item.hasSubitems - ? { - ...item, - Subitems: item.Subitems.map((subitem) => { - return subitem.hasSubitems - ? { - ...subitem, - Subitems: subitem.Subitems.map((secondSubitem) => - action.id === secondSubitem.id - ? { - ...secondSubitem, - showSubitems: !secondSubitem.showSubitems, - } - : secondSubitem - ), - } - : subitem; - }), - } - : item; - }); + : item + ); + case "SELECTED": return state.map((item) => selectPage(item, action.route)); @@ -112,13 +99,16 @@ const SidebarMenu = () => { }, [selectedKey]); return ( - userPermissions && ( - - {menuItems.map((menuItem) => { - return ; - })} - - ) + <> + + {userPermissions && ( + + {menuItems.map((menuItem) => { + return ; + })} + + )} + ); }; export default SidebarMenu; diff --git a/src/core/components/SidebarSubitems.jsx b/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarSubitems.jsx similarity index 67% rename from src/core/components/SidebarSubitems.jsx rename to src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarSubitems.jsx index 69418ea..3018520 100644 --- a/src/core/components/SidebarSubitems.jsx +++ b/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarSubitems.jsx @@ -1,6 +1,7 @@ import { ExpandLess, ExpandMore } from "@mui/icons-material"; -import { Collapse, List, ListItem, ListItemButton, ListItemIcon, ListItemText } from "@mui/material"; +import { Box, Collapse, List, ListItem, ListItemButton, ListItemIcon, ListItemText, Stack } from "@mui/material"; import Link from "next/link"; +import SidebarBadge from "./SidebarBadge"; const SidebarSubitems = ({ subitem, dispatch }) => { return ( @@ -8,7 +9,7 @@ const SidebarSubitems = ({ subitem, dispatch }) => { { {subitem.icon} - {subitem.hasSubitems ? subitem.showSubitems ? : : null} + {subitem.badges && ( + + {subitem.badges.map((badge, i) => ( + + ))} + + )} + {subitem.hasSubitems ? ( + subitem.showSubitems ? ( + + ) : ( + + ) + ) : ( + + )} diff --git a/src/components/layouts/dashboard/headerWithSidebar/index.jsx b/src/components/layouts/dashboard/headerWithSidebar/index.jsx index 68f4bc6..a0ffad2 100644 --- a/src/components/layouts/dashboard/headerWithSidebar/index.jsx +++ b/src/components/layouts/dashboard/headerWithSidebar/index.jsx @@ -1,13 +1,16 @@ "use client"; -import SidebarMenu from "@/core/components/SidebarMenu"; import ChevronRightIcon from "@mui/icons-material/ChevronRight"; import MenuIcon from "@mui/icons-material/Menu"; -import { Box, Drawer, IconButton, Stack, styled, Toolbar } from "@mui/material"; +import { Box, Drawer, IconButton, Stack, styled, Toolbar, Typography } from "@mui/material"; import MuiAppBar from "@mui/material/AppBar"; import { useState } from "react"; import HeaderMenu from "./HeaderMenu"; +import moment from "jalali-moment"; +import { headerMenu } from "@/core/utils/headerMenu"; +import SidebarMenu from "./Sidebar/SidebarMenu"; const drawerWidth = 300; +const headersHeight = 136; const Main = styled(Stack, { shouldForwardProp: (prop) => prop !== "open" })(({ theme, open }) => ({ flexGrow: 1, @@ -48,12 +51,13 @@ const DrawerHeader = styled("div")(({ theme }) => ({ alignItems: "center", padding: theme.spacing(0, 1), ...theme.mixins.toolbar, - minHeight: "48px !important", + minHeight: "40px !important", justifyContent: "flex-end", })); const HeaderWithSidebar = ({ children }) => { const [open, setOpen] = useState(true); + const now = moment().locale("fa").format("YYYY/MM/DD"); const handleDrawerOpen = () => { setOpen(true); @@ -62,9 +66,16 @@ const HeaderWithSidebar = ({ children }) => { setOpen(false); }; return ( - + - + { - + {headerMenu.map((menu) => ( + + ))} @@ -90,27 +103,33 @@ const HeaderWithSidebar = ({ children }) => { boxSizing: "border-box", borderTop: 1, borderTopColor: "divider", - position: 'inherit' + position: "inherit", }, }} variant="persistent" anchor="left" open={open} > - + + + تاریخ امروز: {now} + + + v{process.env.NEXT_PUBLIC_VERSION} +
- + {children}
); }; -export default HeaderWithSidebar; \ No newline at end of file +export default HeaderWithSidebar; diff --git a/src/core/components/ApplicantRequestDetail/DetailItem.jsx b/src/core/components/ApplicantRequestDetail/DetailItem.jsx new file mode 100644 index 0000000..099e955 --- /dev/null +++ b/src/core/components/ApplicantRequestDetail/DetailItem.jsx @@ -0,0 +1,52 @@ +"use client"; + +import { Box, Chip, Divider, Grid, Typography } from "@mui/material"; +import QrCode2Icon from "@mui/icons-material/QrCode2"; +import HomeWorkIcon from "@mui/icons-material/HomeWork"; +import DomainIcon from "@mui/icons-material/Domain"; +import CottageIcon from "@mui/icons-material/Cottage"; +import AccountTreeIcon from "@mui/icons-material/AccountTree"; +import HolidayVillageIcon from "@mui/icons-material/HolidayVillage"; +import CalendarMonthIcon from "@mui/icons-material/CalendarMonth"; +import FaxIcon from "@mui/icons-material/Fax"; +import FullscreenIcon from "@mui/icons-material/Fullscreen"; +import ArchitectureIcon from "@mui/icons-material/Architecture"; +import Diversity2Icon from "@mui/icons-material/Diversity2"; +import SubtitlesIcon from "@mui/icons-material/Subtitles"; +import FingerprintIcon from "@mui/icons-material/Fingerprint"; + +const findItem = { + id: { title: "کد یکتا", icon: }, + shomareh_darkhast: { title: "شماره درخواست", icon: }, + ostan: { title: "استان", icon: }, + shahr: { title: "شهر", icon: }, + shahrestan: { title: "شهرستان", icon: }, + bakhsh: { title: "بخش", icon: }, + roosta: { title: "روستا", icon: }, + tarikh_darkhast: { title: "تاریخ درخواست", icon: }, + sazman: { title: "سازمان", icon: }, + masahat_zamin: { title: "مساحت زمین", icon: }, + masahat_tarh: { title: "مساحت طرح", icon: }, + gorooh_tarh: { title: "گروه طرح", icon: }, + onvane_tarh: { title: "عنوان طرح", icon: }, +}; + +const DetailItem = ({ item }) => { + const currentItem = findItem[item.key]; + if (!currentItem) return null; + + return ( + + + + + {item.value} + + + ); +}; +export default DetailItem; diff --git a/src/core/components/ApplicantRequestDetail/DetailMap.jsx b/src/core/components/ApplicantRequestDetail/DetailMap.jsx new file mode 100644 index 0000000..902ec3a --- /dev/null +++ b/src/core/components/ApplicantRequestDetail/DetailMap.jsx @@ -0,0 +1,39 @@ +"use client"; + +import { Box } from "@mui/material"; +import dynamic from "next/dynamic"; +import MapLoading from "@/core/components/MapLayer/Loading"; +import FlyToPolyGon from "./FlyToPolygon"; + +const MapLayer = dynamic(() => import("@/core/components/MapLayer"), { + loading: () => , + ssr: false, +}); + +const DetailMap = ({ data }) => { + return ( + + + + + + + + ); +}; +export default DetailMap; diff --git a/src/core/components/ApplicantRequestDetail/FlyToPolygon.jsx b/src/core/components/ApplicantRequestDetail/FlyToPolygon.jsx new file mode 100644 index 0000000..4a39edd --- /dev/null +++ b/src/core/components/ApplicantRequestDetail/FlyToPolygon.jsx @@ -0,0 +1,22 @@ +"use client"; + +import { Polygon, useMap } from "react-leaflet"; +import { useEffect } from "react"; + +const purpleOptions = { color: "purple" }; + +const FlyToPolygon = ({ polygon }) => { + const map = useMap(); + + useEffect(() => { + if (map) { + const leafletPolygon = L.polygon(polygon); + const bounds = leafletPolygon.getBounds(); + map.flyToBounds(bounds, { padding: [50, 50] }); + } + }, [map, polygon]); + + return ; +}; + +export default FlyToPolygon; diff --git a/src/core/components/ApplicantRequestDetail/index.jsx b/src/core/components/ApplicantRequestDetail/index.jsx new file mode 100644 index 0000000..bfdbf35 --- /dev/null +++ b/src/core/components/ApplicantRequestDetail/index.jsx @@ -0,0 +1,57 @@ +"use client"; + +import { Box, Button, Chip, Divider, Grid, Typography } from "@mui/material"; +import AttachFileIcon from "@mui/icons-material/AttachFile"; +import DownloadingIcon from "@mui/icons-material/Downloading"; +import DetailItem from "./DetailItem"; +import DetailMap from "./DetailMap"; +import ContactMailIcon from "@mui/icons-material/ContactMail"; + +const ApplicantRequestDetail = ({ data }) => { + return ( + <> + + + + + {Object.entries(data).map(([key, value]) => ( + + ))} + + + } + sx={{ fontSize: "12px", fontWeight: 500, pl: "5px" }} + label="فایل مصوب" + /> + + + + + + + + + } + label="آدرس" + /> + + + {data.address} + + + + + + ); +}; +export default ApplicantRequestDetail; diff --git a/src/core/components/DataTable/Main.js b/src/core/components/DataTable/Main.js index 1f51695..5d0d98d 100644 --- a/src/core/components/DataTable/Main.js +++ b/src/core/components/DataTable/Main.js @@ -21,6 +21,7 @@ const DataTable_Main = (props) => { initialStateProps, TableToolbar, table_title, + RowActions, } = props; const flatColumns = flattenArrayOfObjects(columns, "columns"); const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 }); @@ -32,13 +33,11 @@ const DataTable_Main = (props) => { const fetchUrl = useMemo(() => { const isValueEmpty = (value) => { if (Array.isArray(value)) { - return value.length === 0 || value.every(v => v === ""); + return value.length === 0 || value.every((v) => v === ""); } return value === "" || value === null || value === undefined; }; - const filteredFilterData = Object.values(filterData).filter( - (filter) => !isValueEmpty(filter.value), - ); + const filteredFilterData = Object.values(filterData).filter((filter) => !isValueEmpty(filter.value)); const params = new URLSearchParams(); params.set("start", `${pagination.pageIndex * pagination.pageSize}`); @@ -108,11 +107,8 @@ const DataTable_Main = (props) => { manualSorting: true, onPaginationChange: setPagination, onSortingChange: onSortingChange, - renderTopToolbarCustomActions: ({ table }) => ( - <> - - - ), + renderTopToolbarCustomActions: ({ table }) => <>{TableToolbar && }, + renderRowActions: ({ row }) => , ...props, }); diff --git a/src/core/components/DataTable/body/TableBodyCell.js b/src/core/components/DataTable/body/TableBodyCell.js index 902f9c7..292f39e 100644 --- a/src/core/components/DataTable/body/TableBodyCell.js +++ b/src/core/components/DataTable/body/TableBodyCell.js @@ -1,11 +1,10 @@ +import { getCommonMRTCellStyles, parseFromValuesOrFunc } from "@/core/utils/utils"; +import { useTheme } from "@emotion/react"; +import { Skeleton, TableCell } from "@mui/material"; import { isCellEditable, openEditingCell } from "material-react-table"; - -const { parseFromValuesOrFunc, getCommonMRTCellStyles } = require("@/core/utils/utils"); -const { useTheme } = require("@emotion/react"); -const { TableCell, Skeleton } = require("@mui/material"); -const { useState, useEffect, useMemo, memo } = require("react"); -const { default: DataTable_CopyButton } = require("../buttons/CopyButton"); -const { default: DataTable_TableBodyCellValue } = require("./TableBodyCellValue"); +import { memo, useEffect, useMemo, useState } from "react"; +import DataTable_CopyButton from "../buttons/CopyButton"; +import DataTable_TableBodyCellValue from "./TableBodyCellValue"; const DataTable_TableBodyCell = ({ cell, numRows, rowRef, staticColumnIndex, staticRowIndex, table, ...rest }) => { const theme = useTheme(); @@ -83,10 +82,10 @@ const DataTable_TableBodyCell = ({ cell, numRows, rowRef, staticColumnIndex, sta const borderStyle = showResizeBorder ? `2px solid ${draggingBorderColor} !important` : isDraggingColumn || isDraggingRow - ? `1px dashed ${theme.palette.grey[500]} !important` - : isHoveredColumn || isHoveredRow || isResizingColumn - ? `2px dashed ${draggingBorderColor} !important` - : undefined; + ? `1px dashed ${theme.palette.grey[500]} !important` + : isHoveredColumn || isHoveredRow || isResizingColumn + ? `2px dashed ${draggingBorderColor} !important` + : undefined; if (showResizeBorder) { return columnResizeDirection === "ltr" ? { borderRight: borderStyle } : { borderLeft: borderStyle }; @@ -94,18 +93,18 @@ const DataTable_TableBodyCell = ({ cell, numRows, rowRef, staticColumnIndex, sta return borderStyle ? { - borderBottom: - isDraggingRow || isHoveredRow || (isLastRow && !isResizingColumn) ? borderStyle : undefined, - borderLeft: - isDraggingColumn || isHoveredColumn || ((isDraggingRow || isHoveredRow) && isFirstColumn) - ? borderStyle - : undefined, - borderRight: - isDraggingColumn || isHoveredColumn || ((isDraggingRow || isHoveredRow) && isLastColumn) - ? borderStyle - : undefined, - borderTop: isDraggingRow || isHoveredRow ? borderStyle : undefined, - } + borderBottom: + isDraggingRow || isHoveredRow || (isLastRow && !isResizingColumn) ? borderStyle : undefined, + borderLeft: + isDraggingColumn || isHoveredColumn || ((isDraggingRow || isHoveredRow) && isFirstColumn) + ? borderStyle + : undefined, + borderRight: + isDraggingColumn || isHoveredColumn || ((isDraggingRow || isHoveredRow) && isLastColumn) + ? borderStyle + : undefined, + borderTop: isDraggingRow || isHoveredRow ? borderStyle : undefined, + } : undefined; }, [columnSizingInfo.isResizingColumn, draggingColumn, draggingRow, hoveredColumn, hoveredRow, staticRowIndex]); @@ -179,8 +178,8 @@ const DataTable_TableBodyCell = ({ cell, numRows, rowRef, staticColumnIndex, sta "&:hover": { outline: actionCell?.id === cell.id || - (editDisplayMode === "cell" && isEditable) || - (editDisplayMode === "table" && (isCreating || isEditing)) + (editDisplayMode === "cell" && isEditable) || + (editDisplayMode === "table" && (isCreating || isEditing)) ? `1px solid ${theme.palette.grey[500]}` : undefined, textOverflow: "clip", @@ -189,8 +188,8 @@ const DataTable_TableBodyCell = ({ cell, numRows, rowRef, staticColumnIndex, sta cursor: isRightClickable ? "context-menu" : isEditable && editDisplayMode === "cell" - ? "pointer" - : "inherit", + ? "pointer" + : "inherit", outline: actionCell?.id === cell.id ? `1px solid ${theme.palette.grey[500]}` : undefined, outlineOffset: "-1px", overflow: "hidden", @@ -200,12 +199,12 @@ const DataTable_TableBodyCell = ({ cell, numRows, rowRef, staticColumnIndex, sta ? "0 0.5rem" : "0.5rem" : density === "comfortable" - ? columnDefType === "display" - ? "0.5rem 0.75rem" - : "1rem" - : columnDefType === "display" - ? "1rem 1.25rem" - : "1.5rem", + ? columnDefType === "display" + ? "0.5rem 0.75rem" + : "1rem" + : columnDefType === "display" + ? "1rem 1.25rem" + : "1.5rem", textOverflow: columnDefType !== "display" ? "ellipsis" : undefined, whiteSpace: row.getIsPinned() || density === "compact" ? "nowrap" : "normal", @@ -216,18 +215,18 @@ const DataTable_TableBodyCell = ({ cell, numRows, rowRef, staticColumnIndex, sta theme, }), ...draggingBorders, - backgroundColor: baseBackgroundColor + backgroundColor: baseBackgroundColor, })} > {tableCellProps.children ?? ( <> {cell.getIsPlaceholder() ? ( - columnDef.PlaceholderCell?.({ cell, column, row, table }) ?? null + (columnDef.PlaceholderCell?.({ cell, column, row, table }) ?? null) ) : showSkeletons !== false && (isLoading || showSkeletons) ? ( ) : columnDefType === "display" && - (["mrt-row-expand", "mrt-row-numbers", "mrt-row-select"].includes(column.id) || - !row.getIsGrouped()) ? ( + (["mrt-row-expand", "mrt-row-numbers", "mrt-row-select"].includes(column.id) || + !row.getIsGrouped()) ? ( columnDef.Cell?.({ cell, column, diff --git a/src/core/components/DataTable/body/TableBodyRow.js b/src/core/components/DataTable/body/TableBodyRow.js index e35f29a..2d21f32 100644 --- a/src/core/components/DataTable/body/TableBodyRow.js +++ b/src/core/components/DataTable/body/TableBodyRow.js @@ -91,16 +91,16 @@ const DataTable_TableBodyRow = ({ const cellHighlightColor = isRowSelected ? selectedRowBackgroundColor : isRowPinned - ? pinnedRowBackgroundColor - : undefined; + ? pinnedRowBackgroundColor + : undefined; const cellHighlightColorHover = tableRowProps?.hover !== false ? isRowSelected ? cellHighlightColor : theme.palette.mode === "dark" - ? `${lighten(baseBackgroundColor, 0.2)}` - : `${darken(baseBackgroundColor, 0.2)}` + ? `${lighten(baseBackgroundColor, 0.2)}` + : `${darken(baseBackgroundColor, 0.2)}` : undefined; return ( @@ -126,9 +126,9 @@ const DataTable_TableBodyRow = ({ sx={(theme) => ({ "&:hover td:after": cellHighlightColorHover ? { - backgroundColor: alpha(cellHighlightColorHover, 0.3), - ...commonCellBeforeAfterStyles, - } + backgroundColor: alpha(cellHighlightColorHover, 0.3), + ...commonCellBeforeAfterStyles, + } : undefined, bottom: !virtualRow && bottomPinnedIndex !== undefined && isRowPinned @@ -140,24 +140,25 @@ const DataTable_TableBodyRow = ({ position: virtualRow ? "absolute" : rowPinningDisplayMode?.includes("sticky") && isRowPinned - ? "sticky" - : "relative", + ? "sticky" + : "relative", td: { ...getCommonPinnedCellStyles({ table, theme }), }, "td:after": cellHighlightColor ? { - backgroundColor: cellHighlightColor, - ...commonCellBeforeAfterStyles, - } + backgroundColor: cellHighlightColor, + ...commonCellBeforeAfterStyles, + } : undefined, top: virtualRow ? 0 : topPinnedIndex !== undefined && isRowPinned - ? `${topPinnedIndex * rowHeight + - (enableStickyHeader || isFullScreen ? tableHeadHeight - 1 : 0) + ? `${ + topPinnedIndex * rowHeight + + (enableStickyHeader || isFullScreen ? tableHeadHeight - 1 : 0) }px` - : undefined, + : undefined, transition: virtualRow ? "none" : "all 150ms ease-in-out", width: "100%", zIndex: rowPinningDisplayMode?.includes("sticky") && isRowPinned ? 2 : 0, @@ -181,11 +182,11 @@ const DataTable_TableBodyRow = ({ }; return cell ? ( memoMode === "cells" && - cell.column.columnDef.columnDefType === "data" && - !draggingColumn && - !draggingRow && - editingCell?.id !== cell.id && - editingRow?.id !== row.id ? ( + cell.column.columnDef.columnDefType === "data" && + !draggingColumn && + !draggingRow && + editingCell?.id !== cell.id && + editingRow?.id !== row.id ? ( ) : ( diff --git a/src/core/components/DataTable/filter/FilterBodyField.jsx b/src/core/components/DataTable/filter/FilterBodyField.jsx index 7f0337e..a9bef12 100644 --- a/src/core/components/DataTable/filter/FilterBodyField.jsx +++ b/src/core/components/DataTable/filter/FilterBodyField.jsx @@ -18,15 +18,15 @@ const columnFilterModeOptionFa = { }; function FilterBodyField({ - column, - filterParameters, - handleChange, - handleBlur, - setFieldValue, - errors, - touched, - resetForm, - }) { + column, + filterParameters, + handleChange, + handleBlur, + setFieldValue, + errors, + touched, + resetForm, +}) { const [anchorEl, setAnchorEl] = useState(null); const defaultFilterTranslation = columnFilterModeOptionFa[filterParameters.filterFn] || filterParameters.filterFn; @@ -48,8 +48,8 @@ function FilterBodyField({ touched={touched} /> ) : filterParameters.datatype === "numeric" && - filterParameters.filterFn === "equals" && - Array.isArray(column.columnSelectOption) ? ( + filterParameters.filterFn === "equals" && + Array.isArray(column.columnSelectOption) ? ( { diff --git a/src/core/components/DataTable/head/TableHeadCell.js b/src/core/components/DataTable/head/TableHeadCell.js index 046f833..631a122 100644 --- a/src/core/components/DataTable/head/TableHeadCell.js +++ b/src/core/components/DataTable/head/TableHeadCell.js @@ -67,20 +67,20 @@ const DataTable_TableHeadCell = ({ columnVirtualizer, header, staticColumnIndex, const borderStyle = showResizeBorder ? `2px solid ${draggingBorderColor} !important` : draggingColumn?.id === column.id - ? `1px dashed ${theme.palette.grey[500]}` - : hoveredColumn?.id === column.id - ? `2px dashed ${draggingBorderColor}` - : undefined; + ? `1px dashed ${theme.palette.grey[500]}` + : hoveredColumn?.id === column.id + ? `2px dashed ${draggingBorderColor}` + : undefined; if (showResizeBorder) { return columnResizeDirection === "ltr" ? { borderRight: borderStyle } : { borderLeft: borderStyle }; } const draggingBorders = borderStyle ? { - borderLeft: borderStyle, - borderRight: borderStyle, - borderTop: borderStyle, - } + borderLeft: borderStyle, + borderRight: borderStyle, + borderTop: borderStyle, + } : undefined; return draggingBorders; @@ -151,19 +151,19 @@ const DataTable_TableHeadCell = ({ columnVirtualizer, header, staticColumnIndex, density === "compact" ? "0.5rem" : density === "comfortable" - ? columnDefType === "display" - ? "0.75rem" - : "1rem" - : columnDefType === "display" - ? "1rem 1.25rem" - : "1.5rem", + ? columnDefType === "display" + ? "0.75rem" + : "1rem" + : columnDefType === "display" + ? "1rem 1.25rem" + : "1.5rem", pb: columnDefType === "display" ? 0 : showColumnFilters || density === "compact" ? "0.4rem" : "0.6rem", pt: columnDefType === "group" || density === "compact" ? "0.25rem" : density === "comfortable" - ? ".75rem" - : "1.25rem", + ? ".75rem" + : "1.25rem", userSelect: enableMultiSort && column.getCanSort() ? "none" : undefined, verticalAlign: "middle", ...getCommonMRTCellStyles({ @@ -188,8 +188,8 @@ const DataTable_TableHeadCell = ({ columnVirtualizer, header, staticColumnIndex, columnDefType === "group" || tableCellProps?.align === "center" ? "center" : column.getCanResize() - ? "space-between" - : "flex-start", + ? "space-between" + : "flex-start", position: "relative", width: "100%", }} @@ -218,7 +218,7 @@ const DataTable_TableHeadCell = ({ columnVirtualizer, header, staticColumnIndex, textAlign: "start", color: "#fff", fontWeight: "400", - whiteSpace: "nowrap" + whiteSpace: "nowrap", }} > {HeaderElement} @@ -226,9 +226,10 @@ const DataTable_TableHeadCell = ({ columnVirtualizer, header, staticColumnIndex, {column.getCanSort() && columnDefType !== "group" && ( {columns.map((column) => ( - + ))} @@ -50,4 +45,4 @@ function HideBody({ columns, drawerState, setDrawerState }) { ); } -export default HideBody; \ No newline at end of file +export default HideBody; diff --git a/src/core/components/DataTable/hide/HideBodyField.jsx b/src/core/components/DataTable/hide/HideBodyField.jsx index fe3dc2d..6b60966 100644 --- a/src/core/components/DataTable/hide/HideBodyField.jsx +++ b/src/core/components/DataTable/hide/HideBodyField.jsx @@ -22,7 +22,7 @@ const CustomTreeItem = styled(TreeItem)(({ theme }) => ({ function HideBodyField({ column, hideData, setHideData }) { const handleCheckboxChange = () => { - setHideData(prevData => { + setHideData((prevData) => { const updateHideData = (data, id) => { if (data.hasOwnProperty(id)) { return { ...data, [id]: !data[id] }; @@ -44,11 +44,7 @@ function HideBodyField({ column, hideData, setHideData }) { if (typeof hideData[column.id] === "boolean") { return ( - + {column.header} ); @@ -77,4 +73,4 @@ function HideBodyField({ column, hideData, setHideData }) { ); } -export default HideBodyField; \ No newline at end of file +export default HideBodyField; diff --git a/src/core/components/DataTable/hide/HideOrShowAll.jsx b/src/core/components/DataTable/hide/HideOrShowAll.jsx index ee3a903..c0d2e8d 100644 --- a/src/core/components/DataTable/hide/HideOrShowAll.jsx +++ b/src/core/components/DataTable/hide/HideOrShowAll.jsx @@ -67,4 +67,4 @@ function HideOrShowAll({ hideData, setHideData }) { ); } -export default HideOrShowAll; \ No newline at end of file +export default HideOrShowAll; diff --git a/src/core/components/DataTable/reset/ResetStorage.jsx b/src/core/components/DataTable/reset/ResetStorage.jsx index 6d8a534..9f6abd5 100644 --- a/src/core/components/DataTable/reset/ResetStorage.jsx +++ b/src/core/components/DataTable/reset/ResetStorage.jsx @@ -19,4 +19,4 @@ function ResetStorage({ user_id, page_name, table_name }) { ); } -export default ResetStorage; \ No newline at end of file +export default ResetStorage; diff --git a/src/core/components/DataTable/table/Paper.js b/src/core/components/DataTable/table/Paper.js index 05a0dbb..f972030 100644 --- a/src/core/components/DataTable/table/Paper.js +++ b/src/core/components/DataTable/table/Paper.js @@ -5,17 +5,17 @@ import DataTable_TopToolbar from "../toolbar/TopToolbar"; import DataTable_TableContainer from "./TableContainer"; const DataTable_Paper = ({ - table, - table_name, - columns, - user_id, - page_name, - mutate, - need_filter, - table_url, - table_title, - ...rest - }) => { + table, + table_name, + columns, + user_id, + page_name, + mutate, + need_filter, + table_url, + table_title, + ...rest +}) => { const { getState, options: { @@ -50,19 +50,19 @@ const DataTable_Paper = ({ style={{ ...(isFullScreen ? { - bottom: 0, - height: "100dvh", - left: 0, - margin: 0, - maxHeight: "100dvh", - maxWidth: "100dvw", - padding: 0, - position: "fixed", - right: 0, - top: 0, - width: "100dvw", - zIndex: 999, - } + bottom: 0, + height: "100dvh", + left: 0, + margin: 0, + maxHeight: "100dvh", + maxWidth: "100dvw", + padding: 0, + position: "fixed", + right: 0, + top: 0, + width: "100dvw", + zIndex: 999, + } : {}), ...paperProps?.style, }} diff --git a/src/core/components/DataTable/table/TableContainer.js b/src/core/components/DataTable/table/TableContainer.js index bc1d80c..3e1320e 100644 --- a/src/core/components/DataTable/table/TableContainer.js +++ b/src/core/components/DataTable/table/TableContainer.js @@ -27,9 +27,10 @@ const DataTable_TableContainer = ({ table, ...rest }) => { }; useIsomorphicLayoutEffect(() => { - const topToolbarHeight = typeof document !== "undefined" ? topToolbarRef.current?.offsetHeight ?? 0 : 0; + const topToolbarHeight = typeof document !== "undefined" ? (topToolbarRef.current?.offsetHeight ?? 0) : 0; - const bottomToolbarHeight = typeof document !== "undefined" ? bottomToolbarRef?.current?.offsetHeight ?? 0 : 0; + const bottomToolbarHeight = + typeof document !== "undefined" ? (bottomToolbarRef?.current?.offsetHeight ?? 0) : 0; setTotalToolbarHeight(topToolbarHeight + bottomToolbarHeight); }); diff --git a/src/core/components/DataTable/toolbar/TopToolbar.js b/src/core/components/DataTable/toolbar/TopToolbar.js index fc21ae7..a4d9db7 100644 --- a/src/core/components/DataTable/toolbar/TopToolbar.js +++ b/src/core/components/DataTable/toolbar/TopToolbar.js @@ -8,16 +8,16 @@ import ResetStorage from "@/core/components/DataTable/reset/ResetStorage"; import HideColumn from "@/core/components/DataTable/hide"; const DataTable_TopToolbar = ({ - mutate, - need_filter, - table, - columns, - table_url, - user_id, - page_name, - table_name, - table_title, - }) => { + mutate, + need_filter, + table, + columns, + table_url, + user_id, + page_name, + table_name, + table_title, +}) => { const { getState, options: { @@ -70,13 +70,21 @@ const DataTable_TopToolbar = ({ width: "100%", }} > - {renderTopToolbarCustomActions?.({ table })} - {table_title || ""} + + {renderTopToolbarCustomActions?.({ table })} + + + {table_title || ""} + {enableToolbarInternalActions && ( - + + table_name={table_name} + /> {need_filter && ( { + const { user } = useAuth(); + return ; +}; +export default DataTableWithAuth; diff --git a/src/core/components/DialogTransition.jsx b/src/core/components/DialogTransition.jsx index f289140..1232e48 100644 --- a/src/core/components/DialogTransition.jsx +++ b/src/core/components/DialogTransition.jsx @@ -5,4 +5,4 @@ const DialogTransition = React.forwardRef(function Transition(props, ref) { return ; }); -export default DialogTransition \ No newline at end of file +export default DialogTransition; diff --git a/src/core/components/MapLayer/Loading/index.jsx b/src/core/components/MapLayer/Loading/index.jsx index 5d42012..806168c 100644 --- a/src/core/components/MapLayer/Loading/index.jsx +++ b/src/core/components/MapLayer/Loading/index.jsx @@ -2,11 +2,7 @@ import { Box, LinearProgress, Stack } from "@mui/material"; function MapLoading() { return ( - + @@ -14,4 +10,4 @@ function MapLoading() { ); } -export default MapLoading; \ No newline at end of file +export default MapLoading; diff --git a/src/core/components/MapLayer/index.jsx b/src/core/components/MapLayer/index.jsx index 52209da..1a07c9c 100644 --- a/src/core/components/MapLayer/index.jsx +++ b/src/core/components/MapLayer/index.jsx @@ -1,7 +1,7 @@ "use client"; import { MapContainer, TileLayer, useMap } from "react-leaflet"; -export const IRAN_CENTER = L.latLng(32.4279, 53.6880); +export const IRAN_CENTER = L.latLng(32.4279, 53.688); const MapOptions = ({ options }) => { const map = useMap(); @@ -40,4 +40,4 @@ function MapLayer({ children, style, otherLayers, options }) { ); } -export default MapLayer; \ No newline at end of file +export default MapLayer; diff --git a/src/core/components/NotificationDesign/AskForKeepData.jsx b/src/core/components/NotificationDesign/AskForKeepData.jsx index fa9bfa6..9e1cbd9 100644 --- a/src/core/components/NotificationDesign/AskForKeepData.jsx +++ b/src/core/components/NotificationDesign/AskForKeepData.jsx @@ -10,9 +10,7 @@ import { flattenObjectOfObjects } from "@/core/utils/flattenObjectOfObjects"; function AskForKeepData({ filterData, sortData, hideData, user_id, page_name, table_name, columns }) { const { filterAction, sortAction, hideAction } = useTableSetting(); - const filteredHideData = Object.fromEntries( - Object.entries(hideData).filter(([key, value]) => value === false), - ); + const filteredHideData = Object.fromEntries(Object.entries(hideData).filter(([key, value]) => value === false)); const flattenHideData = flattenObjectOfObjects(filteredHideData); @@ -53,19 +51,10 @@ function AskForKeepData({ filterData, sortData, hideData, user_id, page_name, ta آیا مایل به ذخیره تغییر های اعمال شده برای دفعات بعد هستید؟ - - @@ -73,4 +62,4 @@ function AskForKeepData({ filterData, sortData, hideData, user_id, page_name, ta ); } -export default AskForKeepData; \ No newline at end of file +export default AskForKeepData; diff --git a/src/core/components/PageTitle.jsx b/src/core/components/PageTitle.jsx index 605ad47..4c93098 100644 --- a/src/core/components/PageTitle.jsx +++ b/src/core/components/PageTitle.jsx @@ -4,9 +4,15 @@ import { Chip, Divider, Typography } from "@mui/material"; const PageTitle = ({ title }) => { return ( - {title}
} /> + + + {title} + + } + /> + ); }; export default PageTitle; - diff --git a/src/core/components/Profile/ChangePass/Form.jsx b/src/core/components/Profile/ChangePass/Form.jsx new file mode 100644 index 0000000..80d1890 --- /dev/null +++ b/src/core/components/Profile/ChangePass/Form.jsx @@ -0,0 +1,152 @@ +"use client"; + +import { + Chip, + Divider, + FormControl, + FormHelperText, + Grid, + IconButton, + InputAdornment, + InputLabel, + OutlinedInput, +} from "@mui/material"; +import StyledForm from "@/core/components/StyledForm"; +import { useForm } from "react-hook-form"; +import useRequest from "@/lib/hooks/useRequest"; +import { CHANGE_USER_PASSWORD } from "@/core/utils/routes"; +import { object, string } from "yup"; +import { yupResolver } from "@hookform/resolvers/yup"; +import { useEffect, useState } from "react"; +import Visibility from "@mui/icons-material/Visibility"; +import VisibilityOff from "@mui/icons-material/VisibilityOff"; + +const validationSchema = object({ + current_password: string().required("اجباری"), + new_password: string().required("اجباری"), + repeat_new_password: string() + .required("اجباری") + .test("password-match", "رمز عبور جدید و تکرار آن باید یکسان باشند", function (value) { + return this.parent.new_password === value; + }), +}); + +const Form = ({ handleCloseForm, setLoading }) => { + const request = useRequest(); + const [showNewPassword, setShowNewPassword] = useState(); + const [showRepeatNewPassword, setShowRepeatNewPassword] = useState(); + + const defaultValues = { + current_password: "", + new_password: "", + repeat_new_password: "", + }; + + const { + register, + handleSubmit, + formState: { isSubmitting, errors }, + } = useForm({ defaultValues, resolver: yupResolver(validationSchema) }); + + useEffect(() => { + setLoading(isSubmitting); + }, [isSubmitting]); + + const onSubmit = async (data) => { + const formData = new FormData(); + formData.append("current_password", data.current_password); + formData.append("new_password", data.new_password); + try { + await request(CHANGE_USER_PASSWORD, "post", { data: formData, signal: controller.signal }); + handleCloseForm(); + } catch (error) {} + }; + + return ( + <> + + + + + + + + رمز عبور فعلی + + + {errors.current_password ? errors.current_password.message : null} + + + + + + رمز عبور جدید + + setShowNewPassword(!showNewPassword)} + onMouseDown={(event) => event.preventDefault()} + edge="end" + > + {showNewPassword ? : } + + + } + /> + + {errors.new_password ? errors.new_password.message : null} + + + + + + تکرار رمز عبور جدید + + setShowRepeatNewPassword(!showRepeatNewPassword)} + onMouseDown={(event) => event.preventDefault()} + edge="end" + > + {showRepeatNewPassword ? : } + + + } + /> + + {errors.repeat_new_password ? errors.repeat_new_password.message : null} + + + + + + + ); +}; +export default Form; diff --git a/src/core/components/Profile/ChangePass/index.jsx b/src/core/components/Profile/ChangePass/index.jsx new file mode 100644 index 0000000..4b388da --- /dev/null +++ b/src/core/components/Profile/ChangePass/index.jsx @@ -0,0 +1,47 @@ +"use client"; + +import { Dialog, DialogActions, DialogContent } from "@mui/material"; +import Form from "./Form"; +import SaveIcon from "@mui/icons-material/Save"; +import { LoadingButton } from "@mui/lab"; +import { useState } from "react"; + +const ChangePass = ({ open, setOpen }) => { + const [loading, setLoading] = useState(false); + + const handleCloseForm = () => { + setOpen(false); + }; + + return ( + + +
+ + + + بستن + + } + > + ثبت + + +
+ ); +}; +export default ChangePass; diff --git a/src/core/components/Profile/ProfileActions.jsx b/src/core/components/Profile/ProfileActions.jsx new file mode 100644 index 0000000..1bb99be --- /dev/null +++ b/src/core/components/Profile/ProfileActions.jsx @@ -0,0 +1,54 @@ +"use client"; + +import { Box, Divider, IconButton, Tooltip } from "@mui/material"; +import PowerSettingsNewIcon from "@mui/icons-material/PowerSettingsNew"; +import ModeEditIcon from "@mui/icons-material/ModeEdit"; +import VpnKeyIcon from "@mui/icons-material/VpnKey"; +import { useState } from "react"; +import Update from "@/core/components/Profile/Update"; +import ChangePass from "@/core/components/Profile/ChangePass"; +import { useAuth } from "@/lib/contexts/auth"; + +const ProfileActions = () => { + const { getUser } = useAuth(); + const [openUpdate, setOpenUpdate] = useState(false); + const [openChangePass, setOpenChangePass] = useState(false); + + const openUpdateProfile = () => { + getUser(); + setOpenUpdate(true); + }; + + return ( + <> + + + + + + + + + + + + + + + { + setOpenChangePass(true); + }} + > + + + + + + + + ); +}; +export default ProfileActions; diff --git a/src/core/components/Profile/ProfileInfo.jsx b/src/core/components/Profile/ProfileInfo.jsx new file mode 100644 index 0000000..6af5082 --- /dev/null +++ b/src/core/components/Profile/ProfileInfo.jsx @@ -0,0 +1,38 @@ +"use client"; + +import { useAuth } from "@/lib/contexts/auth"; +import { Avatar, Box, Chip, Divider, Stack, Typography } from "@mui/material"; +import moment from "jalali-moment"; + +const ProfileInfo = () => { + const { user } = useAuth(); + + return ( + <> + + + + + {`${user.first_name} ${user.last_name}`} + + .: {user.name} :. + + + + + آخرین ورود + + + + {moment(user.last_login).locale("fa").fromNow()} + + + + + + + + + ); +}; +export default ProfileInfo; diff --git a/src/core/components/Profile/Update/Form.jsx b/src/core/components/Profile/Update/Form.jsx new file mode 100644 index 0000000..69b1466 --- /dev/null +++ b/src/core/components/Profile/Update/Form.jsx @@ -0,0 +1,251 @@ +"use client"; + +import { + Autocomplete, + Avatar, + Backdrop, + Box, + Button, + Chip, + Divider, + FormControl, + FormHelperText, + Grid, + InputLabel, + OutlinedInput, + TextField, +} from "@mui/material"; +import StyledForm from "@/core/components/StyledForm"; +import useRequest from "@/lib/hooks/useRequest"; +import { Controller, useForm } from "react-hook-form"; +import { useAuth } from "@/lib/contexts/auth"; +import CloudUploadIcon from "@mui/icons-material/CloudUpload"; +import { styled } from "@mui/material/styles"; +import { useEffect, useState } from "react"; +import { yupResolver } from "@hookform/resolvers/yup"; +import { object, string } from "yup"; +import { UPDATE_USER_ROUTE } from "@/core/utils/routes"; + +const degreeItems = ["دیپلم", "کارشناسی", "کارشناسی ارشد", "دکترا"]; + +const VisuallyHiddenInput = styled("input")({ + clip: "rect(0 0 0 0)", + clipPath: "inset(50%)", + height: 1, + overflow: "hidden", + position: "absolute", + bottom: 0, + left: 0, + whiteSpace: "nowrap", + width: 1, +}); + +const validationSchema = object({ + first_name: string().required("اجباری"), + last_name: string().required("اجباری"), + degree: string().required("اجباری"), + major: string().required("اجباری"), + mobile: string().required("اجباری"), +}); + +const Form = ({ handleCloseForm, setLoading }) => { + const request = useRequest(); + const { user, getUser } = useAuth(); + const [uploadBackDrop, setUploadBackDrop] = useState(false); + const defaultValues = { + first_name: user.first_name, + last_name: user.last_name, + major: user.major, + degree: user.degree, + mobile: user.mobile, + avatar: null, + }; + + const { + control, + watch, + register, + setValue, + handleSubmit, + formState: { isSubmitting, errors }, + } = useForm({ defaultValues, resolver: yupResolver(validationSchema) }); + + useEffect(() => { + setLoading(isSubmitting); + }, [isSubmitting]); + + const onSubmit = async (data) => { + const formData = new FormData(); + formData.append("first_name", data.first_name); + formData.append("last_name", data.last_name); + formData.append("major", data.major); + formData.append("degree", data.degree); + formData.append("mobile", data.mobile); + if (data.avatar) { + formData.append("avatar", data.avatar); + } + + try { + await request(UPDATE_USER_ROUTE, "post", { data: formData }); + getUser(); + handleCloseForm(); + } catch (error) {} + }; + + return ( + <> + + + + + + + + + + + نام + + + {errors.first_name ? errors.first_name.message : null} + + + + + + نام خانوادگی + + + {errors.last_name ? errors.last_name.message : null} + + + + + + رشته تحصیلی + + {errors.major ? errors.major.message : null} + + + + ( + + { + onChange(newValue); + }} + options={degreeItems} + renderInput={(params) => ( + + )} + /> + {error ? error.message : null} + + )} + /> + + + + موبایل + + {errors.mobile ? errors.mobile.message : null} + + + + + + ); +}; +export default Form; diff --git a/src/core/components/Profile/Update/index.jsx b/src/core/components/Profile/Update/index.jsx new file mode 100644 index 0000000..d72b5a0 --- /dev/null +++ b/src/core/components/Profile/Update/index.jsx @@ -0,0 +1,44 @@ +"use client"; + +import { Button, Dialog, DialogActions, DialogContent, useMediaQuery } from "@mui/material"; +import { useTheme } from "@mui/material/styles"; +import Form from "./Form"; +import SaveIcon from "@mui/icons-material/Save"; +import { LoadingButton } from "@mui/lab"; +import { useState } from "react"; + +const Update = ({ open, setOpen }) => { + const theme = useTheme(); + const fullScreen = useMediaQuery(theme.breakpoints.down("sm")); + const [loading, setLoading] = useState(false); + + const handleCloseForm = () => { + setOpen(false); + }; + + return ( + + + + + + + } + > + ثبت + + + + ); +}; +export default Update; diff --git a/src/core/components/Profile/index.jsx b/src/core/components/Profile/index.jsx new file mode 100644 index 0000000..fd5cbf4 --- /dev/null +++ b/src/core/components/Profile/index.jsx @@ -0,0 +1,22 @@ +"use client"; + +import { Stack } from "@mui/material"; +import ProfileInfo from "./ProfileInfo"; +import ProfileActions from "./ProfileActions"; + +const Profile = () => { + return ( + + + + + ); +}; +export default Profile; diff --git a/src/core/components/StyledForm.jsx b/src/core/components/StyledForm.jsx index 4513129..accf0ab 100644 --- a/src/core/components/StyledForm.jsx +++ b/src/core/components/StyledForm.jsx @@ -1,5 +1,5 @@ import { styled } from "@mui/material"; -const StyledForm = styled('form')``; +const StyledForm = styled("form")``; export default StyledForm; diff --git a/src/core/components/Toasts/success.jsx b/src/core/components/Toasts/success.jsx index 36023c6..fc11759 100644 --- a/src/core/components/Toasts/success.jsx +++ b/src/core/components/Toasts/success.jsx @@ -16,7 +16,7 @@ export const successToast = (toastContainer) => - {"Your operation was successful"} + {"عملیات با موفقیت انجام شد"}
diff --git a/src/core/utils/cacheRtl.js b/src/core/utils/cacheRtl.js index 6cf5267..a646aa5 100644 --- a/src/core/utils/cacheRtl.js +++ b/src/core/utils/cacheRtl.js @@ -4,7 +4,7 @@ import { prefixer } from "stylis"; import stylisRTLPlugin from "stylis-plugin-rtl"; import { CacheProvider } from "@emotion/react"; -const isBrowser = typeof document !== 'undefined'; +const isBrowser = typeof document !== "undefined"; const createEmotionCache = () => { let insertionPoint; diff --git a/src/core/utils/errorResponse.js b/src/core/utils/errorResponse.js index 9eae51c..c71bfed 100644 --- a/src/core/utils/errorResponse.js +++ b/src/core/utils/errorResponse.js @@ -19,7 +19,7 @@ const errorServer = (response, notification, toastContainer) => { const errorClient = (response, notification, toastContainer, logout) => { switch (response.status) { case 401: - logout() + logout(); if (notification) errorUnauthorizedToast(toastContainer); break; case 422: diff --git a/src/core/utils/flattenArrayOfObjects.js b/src/core/utils/flattenArrayOfObjects.js index ec3cc23..e4d5051 100644 --- a/src/core/utils/flattenArrayOfObjects.js +++ b/src/core/utils/flattenArrayOfObjects.js @@ -7,4 +7,3 @@ export const flattenArrayOfObjects = (array, key) => { return acc; }, []); }; - diff --git a/src/core/utils/flattenObjectOfObjects.jsx b/src/core/utils/flattenObjectOfObjects.js similarity index 99% rename from src/core/utils/flattenObjectOfObjects.jsx rename to src/core/utils/flattenObjectOfObjects.js index 3fdac84..fb03576 100644 --- a/src/core/utils/flattenObjectOfObjects.jsx +++ b/src/core/utils/flattenObjectOfObjects.js @@ -9,4 +9,4 @@ export const flattenObjectOfObjects = (obj, res = {}) => { } } return res; -}; \ No newline at end of file +}; diff --git a/src/core/utils/getValueByPath.js b/src/core/utils/getValueByPath.js new file mode 100644 index 0000000..a31f76f --- /dev/null +++ b/src/core/utils/getValueByPath.js @@ -0,0 +1,14 @@ +export const getValueByPath = (obj, path) => { + const keys = path.split("."); + + let value = obj; + + for (const key of keys) { + if (value === undefined) { + return undefined; + } + value = value[key]; + } + + return value; +}; diff --git a/src/core/utils/headerMenu.js b/src/core/utils/headerMenu.js new file mode 100644 index 0000000..32438bb --- /dev/null +++ b/src/core/utils/headerMenu.js @@ -0,0 +1,80 @@ +export const headerMenu = [ + { + title: "تصادفات", + subMenu: [ + [ + { + title: "تصادفات روزانه", + href: "https://rms.witel.ir/v2/daily_accidents/create", + }, + ], + ], + }, + { + title: "گزارش های جامع", + subMenu: [ + [ + { + title: "گزارش محوری", + href: "https://rms.witel.ir/v2/axis_reports", + }, + { + title: "هوش تجاری (‌BI)", + href: "https://rms.witel.ir/v2/axis_reports", + }, + ], + ], + }, + { + title: "زیرساخت و ناوگان", + subMenu: [ + [ + { + title: "پراکندگی بر روی نقشه راهدارخانه ها", + href: "https://rms.witel.ir/v2/map?type=rahdar", + }, + { + title: "راهدارخانه ها", + href: "https://rms.witel.ir/v2/rahdari_points", + }, + ], + [ + { + title: "ممیزی ماشین آلات راهداری کشور", + href: "https://rms.witel.ir/cmms-audit", + }, + ], + ], + }, + { + title: "سامانه های راهداری", + subMenu: [ + [ + { + title: "تحقیق و توسعه", + href: "https://rms.witel.ir/RandD", + }, + { + title: "سامانه مدیریت یکپارچه زیرساخت های راه (PMS,BMS,SMS)", + href: "http://roadams.rmto.ir", + }, + { + title: "سامانه مدیریت ناوگان (FMS)", + href: "http://fms.141.ir", + }, + { + title: "سامانه جامع مدیریت سوانح و حوادث جاده ای", + href: "https://items.rmto.ir", + }, + { + title: "سامانه مدیریت نگهداری ماشین آلات (CMMS)", + href: "https://cmms.rmto.ir/Login.aspx?ReturnUrl=%2f", + }, + { + title: "درگاه کاتالوگ داده", + href: "https://roadams.rmto.ir:8080", + }, + ], + ], + }, +]; diff --git a/src/core/utils/pageMenu.js b/src/core/utils/pageMenu.js index 75f7828..1f9100c 100644 --- a/src/core/utils/pageMenu.js +++ b/src/core/utils/pageMenu.js @@ -1,4 +1,24 @@ -import { Security } from "@mui/icons-material"; +import SpaceDashboardIcon from "@mui/icons-material/SpaceDashboard"; +import GroupsIcon from "@mui/icons-material/Groups"; +import AccountTreeIcon from "@mui/icons-material/AccountTree"; +import FactCheckIcon from "@mui/icons-material/FactCheck"; +import FireTruckIcon from "@mui/icons-material/FireTruck"; +import RouteIcon from "@mui/icons-material/Route"; +import DoorbellIcon from "@mui/icons-material/Doorbell"; +import ElectricBoltIcon from "@mui/icons-material/ElectricBolt"; +import CottageIcon from "@mui/icons-material/Cottage"; +import GppMaybeIcon from "@mui/icons-material/GppMaybe"; +import GavelIcon from "@mui/icons-material/Gavel"; +import BallotIcon from "@mui/icons-material/Ballot"; +import AssistantIcon from "@mui/icons-material/Assistant"; +import AdminPanelSettingsIcon from "@mui/icons-material/AdminPanelSettings"; +import MapIcon from "@mui/icons-material/Map"; +import SpeedIcon from "@mui/icons-material/Speed"; +import EngineeringIcon from "@mui/icons-material/Engineering"; +import ReportIcon from "@mui/icons-material/Report"; +import AssignmentLateIcon from "@mui/icons-material/AssignmentLate"; +import LineAxisIcon from "@mui/icons-material/LineAxis"; +import ScienceIcon from '@mui/icons-material/Science'; export const pageMenu = [ { @@ -6,7 +26,7 @@ export const pageMenu = [ label: "پیشخوان", type: "page", route: "/dashboard", - icon: , + icon: , permissions: ["all"], }, { @@ -14,14 +34,14 @@ export const pageMenu = [ label: "مدیریت کاربران", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/user_management", - icon: , + icon: , permissions: ["full-user-management", "limited-user-management"], }, { id: "projectsManagment", label: "پروژه های راهداری", type: "menu", - icon: , + icon: , hasSubitems: true, Subitems: [ { @@ -29,7 +49,7 @@ export const pageMenu = [ label: "ثبت قرارداد و پروژه", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/rahdari_projects/finance", - icon: , + icon: , permissions: ["show-contract", "show-contract-province"], }, { @@ -37,7 +57,7 @@ export const pageMenu = [ label: "لیست پروژه ها", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/rahdari_projects/projects_list", - icon: , + icon: , permissions: ["all"], }, { @@ -45,7 +65,7 @@ export const pageMenu = [ label: "پروژه های پیشنهادی", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/rahdari_projects/proposal", - icon: , + icon: , permissions: ["show-proposal", "show-proposal-province"], }, { @@ -53,7 +73,7 @@ export const pageMenu = [ label: "درخواست نمایندگان", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/rahdari_projects/lawmakers", - icon: , + icon: , permissions: ["show-lawmaker", "show-lawmaker-province"], }, { @@ -61,7 +81,7 @@ export const pageMenu = [ label: "پراکندگی بر روی نقشه", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/map?type=rahdari_projects", - icon: , + icon: , permissions: ["all"], }, ], @@ -70,15 +90,17 @@ export const pageMenu = [ id: "roadItemManagment", label: "فعالیت های روزانه", type: "menu", - icon: , + icon: , hasSubitems: true, + badges: ["road_items.total"], Subitems: [ { id: "roadItemManagmentSupervisor", label: "ارزیابی", type: "menu", - icon: , + icon: , hasSubitems: true, + badges: ["road_items.supervise_cnt"], Subitems: [ { id: "roadItemManagmentSupervisorCartable", @@ -96,8 +118,9 @@ export const pageMenu = [ id: "roadItemManagmentOparation", label: "عملیات", type: "menu", - icon: , + icon: , hasSubitems: true, + badges: ["road_items.operation_cnt"], Subitems: [ { id: "roadItemManagmentOparationCreate", @@ -120,7 +143,7 @@ export const pageMenu = [ label: "پراکندگی بر روی نقشه", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/map?type=road_items", - icon: , + icon: , permissions: [ "show-road-item-supervise-cartable", "show-road-item-supervise-cartable-province", @@ -132,7 +155,7 @@ export const pageMenu = [ label: "گزارش ها", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_items/report", - icon: , + icon: , permissions: [ "show-road-item-supervise-cartable", "show-road-item-supervise-cartable-province", @@ -145,15 +168,17 @@ export const pageMenu = [ id: "roadPatrolManagment", label: "گشت راهداری و ترابری", type: "menu", - icon: , + icon: , hasSubitems: true, + badges: ["road_patrols.total"], Subitems: [ { id: "roadPatrolManagmentSupervisor", label: "ارزیابی", type: "menu", - icon: , + icon: , hasSubitems: true, + badges: ["road_patrols.supervise_cnt"], Subitems: [ { id: "roadPatrolManagmentSupervisorCartable", @@ -171,8 +196,9 @@ export const pageMenu = [ id: "roadPatrolManagmentOparation", label: "عملیات", type: "menu", - icon: , + icon: , hasSubitems: true, + badges: ["road_patrols.operation_cnt"], Subitems: [ { id: "roadPatrolManagmentOparationCreate", @@ -195,7 +221,7 @@ export const pageMenu = [ label: "پراکندگی بر روی نقشه", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/map?type=road_patrols", - icon: , + icon: , permissions: [ "add-road-patrol", "show-road-patrol-supervise-cartable", @@ -207,7 +233,7 @@ export const pageMenu = [ label: "گزارش ها", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_patrols/report", - icon: , + icon: , permissions: [ "add-road-patrol", "show-road-patrol-supervise-cartable", @@ -220,28 +246,35 @@ export const pageMenu = [ id: "inquiryPrivacyManagment", label: "استعلام حریم راه", type: "menu", - icon: , + icon: , hasSubitems: true, Subitems: [ { - id: "inquiryPrivacyManagmentFencing", - label: "احداث و بهره برداری دیوارکشی و مستحدثات", + id: "cityAdminZaminGov", + label: "استعلام حرائم پنجره واحد", type: "page", - route: "/dashboard/inquiry_privacy/fencing", + route: "/dashboard/inquiry-privacy/city-admin/zamin-gov", permissions: ["all"], }, { - id: "inquiryPrivacyManagmentRoad", - label: "احداث راه دسترسی اختصاصی", + id: "provinceAdminZaminGov", + label: "استعلام حرائم پنجره واحد", type: "page", - route: "/dashboard/inquiry_privacy/road", + route: "/dashboard/inquiry-privacy/province-admin/zamin-gov", permissions: ["all"], }, { - id: "inquiryPrivacyManagmentInfrastructure", - label: "احداث و بهره برداری تاسیسات زیربنایی", + id: "assistantZaminGov", + label: "استعلام حرائم پنجره واحد", type: "page", - route: "/dashboard/inquiry_privacy/infrastructure", + route: "/dashboard/inquiry-privacy/assistant/zamin-gov", + permissions: ["all"], + }, + { + id: "generalManagerZaminGov", + label: "استعلام حرائم پنجره واحد", + type: "page", + route: "/dashboard/inquiry-privacy/general-manager/zamin-gov", permissions: ["all"], }, ], @@ -250,14 +283,15 @@ export const pageMenu = [ id: "safetyAndPrivacyManagment", label: "نگهداری حریم راه", type: "menu", - icon: , + icon: , hasSubitems: true, + badges: ["safety_and_privacy.step_one", "safety_and_privacy.step_two"], Subitems: [ { id: "safetyAndPrivacyManagmentOparation", label: "عملیات", type: "menu", - icon: , + icon: , hasSubitems: true, Subitems: [ { @@ -285,7 +319,7 @@ export const pageMenu = [ label: "پراکندگی بر روی نقشه", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/map?type=safety_and_privacy", - icon: , + icon: , permissions: [ "show-safety-and-privacy-operator-cartable", "show-safety-and-privacy-operator-cartable-province", @@ -298,7 +332,7 @@ export const pageMenu = [ label: "گزارش ها", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/safety_and_privacy/report", - icon: , + icon: , permissions: [ "show-safety-and-privacy-operator-cartable", "show-safety-and-privacy-operator-cartable-province", @@ -312,15 +346,17 @@ export const pageMenu = [ id: "roadObservationsManagment", label: "واکنش سریع", type: "menu", - icon: , + icon: , hasSubitems: true, + badges: ["road_observations.total"], Subitems: [ { id: "roadObservationsManagmentSupervisor", label: "ارزیابی", type: "menu", - icon: , + icon: , hasSubitems: true, + badges: ["road_observations.supervise_cnt"], Subitems: [ { id: "roadObservationsManagmentSupervisorCartable", @@ -336,15 +372,16 @@ export const pageMenu = [ label: "رسیدگی به شکایات", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_observations", - icon: , + icon: , permissions: ["show-fast-react", "show-fast-react-province", "show-fast-react-edarate-shahri"], }, { id: "roadObservationsManagmentOparation", label: "عملیات", type: "menu", - icon: , + icon: , hasSubitems: true, + badges: ["road_observations.operation_cnt"], Subitems: [ { id: "roadObservationsManagmentOparationCartable", @@ -360,7 +397,7 @@ export const pageMenu = [ label: "پراکندگی بر روی نقشه", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/map?type=road_observations", - icon: , + icon: , permissions: ["all"], }, { @@ -368,7 +405,7 @@ export const pageMenu = [ label: "گزارش ها", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/road_observations/report/index", - icon: , + icon: , permissions: ["all"], }, ], @@ -377,7 +414,7 @@ export const pageMenu = [ id: "winterCampManagment", label: "قرارگاه زمستانی", type: "menu", - icon: , + icon: , hasSubitems: true, Subitems: [ { @@ -385,7 +422,7 @@ export const pageMenu = [ label: "محور های انسدادی", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/winter_camp", - icon: , + icon: , permissions: ["show-camp", "show-camp-province"], }, { @@ -393,7 +430,7 @@ export const pageMenu = [ label: "محور های حلقه اول", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/map?type=camp", - icon: , + icon: , permissions: ["show-camp", "show-camp-province"], }, { @@ -401,7 +438,7 @@ export const pageMenu = [ label: "گزارش ها", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/map?type=campNew", - icon: , + icon: , permissions: ["show-camp", "show-camp-province"], }, ], @@ -410,14 +447,14 @@ export const pageMenu = [ id: "receiptManagment", label: "خسارات وارده بر ابنیه فنی و تاسیسات راه", type: "menu", - icon: , + icon: , hasSubitems: true, Subitems: [ { id: "receiptManagmentOparation", label: "عملیات", type: "menu", - icon: , + icon: , hasSubitems: true, Subitems: [ { @@ -434,9 +471,17 @@ export const pageMenu = [ label: "گزارش ها", type: "page", route: process.env.NEXT_PUBLIC_API_URL + "/v2/receipt/report", - icon: , + icon: , permissions: ["all"], }, ], }, + { + id: "test", + label: "آزمایشات", + type: "page", + route: "/dashboard/test", + icon: , + permissions: ["all"], + }, ]; diff --git a/src/core/utils/routes.js b/src/core/utils/routes.js index d33fa7d..0e60709 100644 --- a/src/core/utils/routes.js +++ b/src/core/utils/routes.js @@ -1,8 +1,17 @@ const api = process.env.NEXT_PUBLIC_API_URL; -export const GET_USER_ROUTE = api + "/webapi/user/get-permission"; +export const GET_USER_ROUTE = api + "/api/v3/profile/info"; +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_INQUIRY_PRIVACY_FENCING_ROUTE = api + "/api/v3/harim/divarkeshi"; export const GET_PERMISSIONS_ROUTE = api + "/webapi/user/get-permission"; - -export const SET_INQUIRE_PRIVACY_FENCING = api + "/api/v3/harim/divarkeshi/store"; +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_PREV_STATE_OPINION = "/v3/api/fake-prev-state-opinion"; +export const SUBMIT_ROAD_SAFETY_FORM = "/v3/api/fake-submit"; +export const POST_TEST = api + "/api/v3/azmayeshes/store"; +export const GET_TESTS_LIST = api + "/api/v3/azmayesh_types"; +export const GET_AZMAYESH_LIST = api + "/api/v3/azmayeshes"; diff --git a/src/lib/contexts/DataTable.js b/src/lib/contexts/DataTable.js index 789df28..ff3439c 100644 --- a/src/lib/contexts/DataTable.js +++ b/src/lib/contexts/DataTable.js @@ -23,7 +23,7 @@ const DataTableProvider = ({ children, user_id, page_name, table_name, columns } const filterValues = flatColumns.reduce((acc, column) => { if (!column.enableColumnFilter) return acc; const storeFilter = settingStore?.[user_id]?.[page_name]?.[table_name]?.["filters"]?.find( - (filter) => filter.id === column.id, + (filter) => filter.id === column.id ); if (column.datatype === "array") { acc[column.id] = { @@ -100,7 +100,7 @@ const DataTableProvider = ({ children, user_id, page_name, table_name, columns } position: "bottom-left", draggable: true, autoClose: false, - }, + } ); } else { toast.update("keep_data", { diff --git a/src/lib/contexts/auth.js b/src/lib/contexts/auth.js index 074c8db..edc83fb 100644 --- a/src/lib/contexts/auth.js +++ b/src/lib/contexts/auth.js @@ -49,12 +49,12 @@ export const AuthProvider = ({ children }) => { clearUser(); changeAuthState(false); changeInitAuth(true); - } + }; const getUser = useCallback(async () => { try { const { data } = await axios.get(GET_USER_ROUTE, { withCredentials: true }); - changeUser(data); + changeUser(data.data); changeAuthState(true); changeInitAuth(true); } catch (error) { @@ -77,7 +77,7 @@ export const AuthProvider = ({ children }) => { isAuth: state.isAuth, initAuthState: state.initAuthState, getUser, - logout + logout, }} > {children} diff --git a/src/lib/contexts/tableSetting.js b/src/lib/contexts/tableSetting.js index 0484511..c73a08d 100644 --- a/src/lib/contexts/tableSetting.js +++ b/src/lib/contexts/tableSetting.js @@ -1,4 +1,5 @@ "use client"; + import { createContext, useCallback, useEffect, useState } from "react"; import LZString from "lz-string"; @@ -130,4 +131,4 @@ export const TableSettingProvider = ({ children }) => { {children} ); -}; \ No newline at end of file +}; diff --git a/src/lib/hooks/useCities.js b/src/lib/hooks/useCities.js new file mode 100644 index 0000000..e1af9aa --- /dev/null +++ b/src/lib/hooks/useCities.js @@ -0,0 +1,31 @@ +import { useState, useEffect } from "react"; +import axios from "axios"; +import { GET_CITY_LISTS } from "@/core/utils/routes"; +import useRequest from "@/lib/hooks/useRequest"; + +const useCities = () => { + const requestServer = useRequest(); + const [cities, setCities] = useState([]); + const [loadingCities, setLoadingCities] = useState(true); + const [errorCities, setErrorCities] = useState(null); + + useEffect(() => { + const fetchCities = async () => { + try { + const response = await requestServer(`${GET_CITY_LISTS}`); + setCities(response.data.data); + setLoadingCities(false); + } catch (e) { + console.error("Error fetching cities:", e); + setErrorCities(e); + setLoadingCities(false); + } + }; + + fetchCities(); + }, []); + + return { cities, loadingCities, errorCities }; +}; + +export default useCities; diff --git a/src/lib/hooks/usePrevStateopinion.js b/src/lib/hooks/usePrevStateopinion.js new file mode 100644 index 0000000..9104366 --- /dev/null +++ b/src/lib/hooks/usePrevStateopinion.js @@ -0,0 +1,31 @@ +import { useState, useEffect } from "react"; +import axios from "axios"; +import { GET_PREV_STATE_OPINION } from "@/core/utils/routes"; +import useRequest from "@/lib/hooks/useRequest"; + +const usePrevStateOpinion = () => { + const requestServer = useRequest(); + const [message, setMessage] = useState([]); + const [loadingMessage, setLoadingMessage] = useState(true); + const [errorMessage, setErrorMessage] = useState(null); + + useEffect(() => { + const fetchCities = async () => { + try { + const response = await requestServer(`${GET_PREV_STATE_OPINION}`); + setMessage(response.data.message); + setLoadingMessage(false); + } catch (e) { + console.error("Error fetching cities:", e); + setErrorMessage(e); + setLoadingMessage(false); + } + }; + + fetchCities(); + }, []); + + return { message, loadingMessage, errorMessage }; +}; + +export default usePrevStateOpinion; diff --git a/src/lib/hooks/useProvince.js b/src/lib/hooks/useProvince.js new file mode 100644 index 0000000..7a058f6 --- /dev/null +++ b/src/lib/hooks/useProvince.js @@ -0,0 +1,30 @@ +import {useEffect, useState} from "react"; +import {GET_PROVINCE_LISTS} from "@/core/utils/routes"; +import useRequest from "@/lib/hooks/useRequest"; + +const useProvinces = () => { + const requestServer = useRequest(); + const [provinces, setProvinces] = useState([]); + const [loadingProvinces, setLoadingProvinces] = useState(true); + const [errorProvinces, setErrorProvinces] = useState(null); + + 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 + } catch (e) { + console.error("Error fetching cities:", e); + setErrorProvinces(e); + setLoadingProvinces(false); + } + }; + + fetchCities(); // Call the fetch function + }, []); // Empty dependency array to ensure it only runs once + + return {provinces, loadingProvinces, errorProvinces}; +}; + +export default useProvinces; diff --git a/src/lib/hooks/useRequest.js b/src/lib/hooks/useRequest.js index 48a2080..eb30a18 100644 --- a/src/lib/hooks/useRequest.js +++ b/src/lib/hooks/useRequest.js @@ -16,7 +16,7 @@ const defaultOptions = { }; const useRequest = (initOptions) => { - const { logout } = useAuth() + const { logout } = useAuth(); const _options = Object.assign({}, defaultOptions, initOptions); @@ -38,7 +38,8 @@ const useRequest = (initOptions) => { errorResponse( error.response, mergedOptions.notification.show && mergedOptions.notification.failed, - "request_data", logout + "request_data", + logout ); } throw error; diff --git a/src/lib/hooks/useSidebarBadge.js b/src/lib/hooks/useSidebarBadge.js new file mode 100644 index 0000000..621ce55 --- /dev/null +++ b/src/lib/hooks/useSidebarBadge.js @@ -0,0 +1,18 @@ +import { GET_SIDEBAR_BADGE_ROUTE } from "@/core/utils/routes"; +import useSWR from "swr"; +import useRequest from "./useRequest"; + +export const useSidebarBadge = () => { + const request = useRequest(); + + const fetcher = async (url) => { + try { + const response = await request(url); + return response.data; + } catch (error) { + throw new Error(); + } + }; + + return useSWR(GET_SIDEBAR_BADGE_ROUTE, fetcher, { keepPreviousData: true }); +}; diff --git a/src/lib/hooks/useTest.js b/src/lib/hooks/useTest.js new file mode 100644 index 0000000..ea1a386 --- /dev/null +++ b/src/lib/hooks/useTest.js @@ -0,0 +1,30 @@ +import {useEffect, useState} from "react"; +import {GET_TESTS_LIST} from "@/core/utils/routes"; +import useRequest from "@/lib/hooks/useRequest"; + +const useTest = () => { + const requestServer = useRequest(); + const [tests, setTests] = useState([]); + const [loadingTests, setLoadingTests] = useState(true); + const [errorTests, setErrorTests] = useState(null); + + useEffect(() => { + const fetchTests = async () => { + try { + const response = await requestServer(`${GET_TESTS_LIST}`); + setTests(response.data.data); + setLoadingTests(false); + } catch (e) { + console.error("Error fetching tests types:", e); + setErrorTests(e); + setLoadingTests(false); + } + }; + + fetchTests(); + }, []); + + return {tests, loadingTests, errorTests}; +}; + +export default useTest;