diff --git a/.env.local.example b/.env.local.example
index c93a078..fa80b33 100644
--- a/.env.local.example
+++ b/.env.local.example
@@ -1,2 +1,3 @@
NEXT_PUBLIC_VERSION="0.2.0"
-NEXT_PUBLIC_API_URL="https://rms.witel.ir"
\ No newline at end of file
+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 7bec569..36ec3d1 100644
--- a/package.json
+++ b/package.json
@@ -28,6 +28,8 @@
"next": "^14.2.3",
"react": "^18",
"react-dom": "^18",
+ "react-hook-form": "^7.52.1",
+ "react-leaflet": "^4.2.1",
"react-toastify": "^10.0.5",
"sass": "^1.75.0",
"stylis": "^4.3.1",
diff --git a/public/global.scss b/public/global.scss
index 764379f..7b73e7e 100644
--- a/public/global.scss
+++ b/public/global.scss
@@ -1,8 +1,10 @@
@import "fontiran";
+@import "leaflet/dist/leaflet.css";
@import "react-toastify/dist/ReactToastify.css";
.filter-toast {
- box-shadow: rgba(50, 50, 93, 0.25) 0px 13px 27px -5px,
- rgba(0, 0, 0, 0.3) 0px 8px 16px -8px;
- background-color: #d0dfe8;
-}
\ No newline at end of file
+ box-shadow:
+ rgba(50, 50, 93, 0.25) 0px 13px 27px -5px,
+ rgba(0, 0, 0, 0.3) 0px 8px 16px -8px;
+ background-color: #d0dfe8;
+}
diff --git a/public/images/locationMarker.png b/public/images/locationMarker.png
new file mode 100644
index 0000000..5e19b95
Binary files /dev/null and b/public/images/locationMarker.png differ
diff --git a/src/components/dashboard/inquiryPrivacyFencing/Create/Form/LocationOnMap/index.jsx b/src/components/dashboard/inquiryPrivacyFencing/Create/Form/LocationOnMap/index.jsx
new file mode 100644
index 0000000..be24704
--- /dev/null
+++ b/src/components/dashboard/inquiryPrivacyFencing/Create/Form/LocationOnMap/index.jsx
@@ -0,0 +1,23 @@
+import MapLoading from "@/core/components/MapLayer/Loading";
+import MarkerLocation from "@/core/components/MapLayer/MarkerLocation";
+import { Paper, Stack } from "@mui/material";
+import { useFormikContext } from "formik";
+import dynamic from "next/dynamic";
+
+const MapLayer = dynamic(() => import("@/core/components/MapLayer"), {
+ loading: () => ,
+ ssr: false,
+});
+
+const LocationOnMap = ({ setValue }) => {
+ return (
+
+
+
+
+
+
+
+ )
+}
+export default LocationOnMap
\ No newline at end of file
diff --git a/src/components/dashboard/inquiryPrivacyFencing/Create/Form/index.jsx b/src/components/dashboard/inquiryPrivacyFencing/Create/Form/index.jsx
new file mode 100644
index 0000000..9fff4da
--- /dev/null
+++ b/src/components/dashboard/inquiryPrivacyFencing/Create/Form/index.jsx
@@ -0,0 +1,570 @@
+import LtrTextField from "@/core/components/LtrTextField";
+import StyledForm from "@/core/components/StyledForm";
+import { SET_INQUIRE_PRIVACY_FENCING } from "@/core/utils/routes";
+import useRequest from "@/lib/hooks/useRequest";
+import { Autocomplete, Box, Button, Chip, 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";
+import { Controller, useForm } from "react-hook-form";
+import LocationOnMap from "./LocationOnMap";
+
+const CreateForm = ({ handleClose, mutate }) => {
+ const { control, watch, register, handleSubmit, setValue } = useForm({
+ defaultValues: {
+ dabirkhaneh_number: '',
+ nameh_date: moment(),
+ nameh_date_fa: '',
+ marjae_pasokh: '',
+ motaghazi_is_legal_id: null,
+ motaghazi_is_legal: '',
+ motaghazi_type_id: '',
+ motaghazi_type: null,
+ motaghazi_firstname: '',
+ motaghazi_lastname: '',
+ national_id: '',
+ shenase_melli: '',
+ tel_number: '',
+ mobile_number: '',
+ address: '',
+ edare_kol_id: null,
+ edare_kol: '',
+ edare_shahri_id: null,
+ edare_shahri: '',
+ rah_type_id: null,
+ rah_type: '',
+ name_mehvar_id: '',
+ name_mehvar_fa: null,
+ mizan_harim: null,
+ arze_navar: null,
+ samt_id: null,
+ samt: '',
+ kilometr: '',
+ lat: '',
+ lon: '',
+ zone: null,
+ karbari_type_id: null,
+ karbari_type: '',
+ tarh_title: '',
+ masahat_zirbana: '',
+ ehdasat_type_id: [],
+ ehdasat_type: '',
+ divarkeshi_distance: '',
+ mostahadesat_distance: '',
+ mahale_ejra_id: null,
+ mahale_ejra: '',
+ traffic_id: null,
+ traffic: '',
+ vaziat_eghtesadi_id: null,
+ vaziat_eghtesadi: '',
+ has_access_id: null,
+ has_access: '',
+ shomare_estelam_harim: '',
+ max_month: '',
+ max_day: '',
+ shomare_tahaodname: '',
+ shomare_daftarkhaneh: '',
+ description: '',
+ ronevesht: '',
+ }
+ });
+ const request = useRequest()
+
+ 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_id)
+ 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(SET_INQUIRE_PRIVACY_FENCING, 'post', { data: formData })
+ handleClose()
+ mutate()
+ } catch (error) {
+
+ }
+ };
+
+ return (
+
+
+
+
+
+
+
+
+ (
+ onChange(moment(newValue))}
+ label="تاریخ نامه درخواست *"
+ slotProps={{
+ textField: { fullWidth: true, size: "small", autoComplete: 'off' },
+ }}
+ />
+ )}
+ />
+
+
+
+
+
+ (
+ {
+ onChange(newValue)
+ }}
+ options={["حقوقی", "حقیقی"]}
+ renderInput={(params) => }
+ />
+ )}
+ />
+
+
+
+
+ (
+ {
+ onChange(newValue)
+ }}
+ options={["دولتی", "خصوصی"]}
+ renderInput={(params) => }
+ />
+ )}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (
+ {
+ onChange(newValue)
+ }}
+ options={["تهران"]}
+ renderInput={(params) => (
+
+ )}
+ />
+ )}
+ />
+
+
+ (
+ {
+ onChange(newValue)
+ }}
+ options={["تهران"]}
+ renderInput={(params) => }
+ />
+ )}
+ />
+
+
+ (
+ {
+ onChange(newValue)
+ }}
+ options={["آزاد راه", "بزرگراه", 'راه فرعی درجه 3']}
+ renderInput={(params) => }
+ />
+ )}
+ />
+
+
+ (
+ {
+ onChange(newValue)
+ }}
+ options={["سایر"]}
+ renderInput={(params) => }
+ />
+ )}
+ />
+
+
+
+
+
+
+
+ (
+ {
+ onChange(newValue)
+ }}
+ options={["چپ", "راست"]}
+ renderInput={(params) => }
+ />
+ )}
+ />
+
+
+ (
+ {
+ onChange(newValue)
+ }}
+ options={["12.5", "17.5"]}
+ renderInput={(params) => }
+ />
+ )}
+ />
+
+
+
+
+ (
+ {
+ onChange(newValue)
+ }}
+ options={["15", "30"]}
+ renderInput={(params) => }
+ />
+ )}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (
+ {
+ onChange(newValue)
+ }}
+ options={["38", "39"]}
+ renderInput={(params) => }
+ />
+ )}
+ />
+
+
+
+ (
+ {
+ onChange(newValue)
+ }}
+ options={["اتاقک نگهبانی", "دولتی"]}
+ renderInput={(params) => }
+ />
+ )}
+ />
+
+
+
+
+
+
+ مترمربع,
+ }} />
+
+
+ (
+ {
+ onChange(newValue)
+ }}
+ renderTags={(value, getTagProps) =>
+ value.map((option, index) => {
+ const { key, ...tagProps } = getTagProps({ index });
+ return (
+
+ );
+ })
+ }
+ options={["تعمیرات", "احداث بنا"]}
+ renderInput={(params) => }
+ />
+ )}
+ />
+
+
+ متر,
+ }} />
+
+
+ متر,
+ }} />
+
+
+ (
+ {
+ onChange(newValue)
+ }}
+ options={["داخل حریم"]}
+ renderInput={(params) => }
+ />
+ )}
+ />
+
+
+ (
+ {
+ onChange(newValue)
+ }}
+ options={["سبک (ضریب ۱)"]}
+ renderInput={(params) => }
+ />
+ )}
+ />
+
+
+ (
+ {
+ onChange(newValue)
+ }}
+ options={["تست"]}
+ renderInput={(params) => }
+ />
+ )}
+ />
+
+
+ (
+ {
+ onChange(newValue)
+ }}
+ options={["بله", "خیر"]}
+ renderInput={(params) => }
+ />
+ )}
+ />
+
+
+
+
+
+
+ حداکثر مدت زمان شروع عملیات: *
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+export default CreateForm;
diff --git a/src/components/dashboard/inquiryPrivacyFencing/Create/index.jsx b/src/components/dashboard/inquiryPrivacyFencing/Create/index.jsx
new file mode 100644
index 0000000..9010277
--- /dev/null
+++ b/src/components/dashboard/inquiryPrivacyFencing/Create/index.jsx
@@ -0,0 +1,32 @@
+"use client";
+import DialogTransition from "@/core/components/DialogTransition";
+import { Close } from "@mui/icons-material";
+import { Dialog, DialogTitle, IconButton } from "@mui/material";
+import CreateForm from "./Form";
+
+const InquiryPrivacyFencingCreate = ({ open, handleClose, mutate }) => {
+
+ return (
+ <>
+
+ >
+ );
+};
+export default InquiryPrivacyFencingCreate;
diff --git a/src/core/components/DialogTransition.jsx b/src/core/components/DialogTransition.jsx
new file mode 100644
index 0000000..f289140
--- /dev/null
+++ b/src/core/components/DialogTransition.jsx
@@ -0,0 +1,8 @@
+import { Slide } from "@mui/material";
+import React from "react";
+
+const DialogTransition = React.forwardRef(function Transition(props, ref) {
+ return ;
+});
+
+export default DialogTransition
\ No newline at end of file
diff --git a/src/core/components/MapLayer/Loading/index.jsx b/src/core/components/MapLayer/Loading/index.jsx
new file mode 100644
index 0000000..5d42012
--- /dev/null
+++ b/src/core/components/MapLayer/Loading/index.jsx
@@ -0,0 +1,17 @@
+import { Box, LinearProgress, Stack } from "@mui/material";
+
+function MapLoading() {
+ return (
+
+
+
+
+
+ );
+}
+
+export default MapLoading;
\ No newline at end of file
diff --git a/src/core/components/MapLayer/MarkerLocation/index.jsx b/src/core/components/MapLayer/MarkerLocation/index.jsx
new file mode 100644
index 0000000..a75d191
--- /dev/null
+++ b/src/core/components/MapLayer/MarkerLocation/index.jsx
@@ -0,0 +1,32 @@
+import { useRef } from "react";
+import { Marker, useMapEvents } from "react-leaflet";
+
+const prefix = process.env.NODE_ENV === "production" ? "/v3" : "";
+
+const locationMarker = L.icon({
+ iconUrl: prefix + "/images/locationMarker.png",
+ iconSize: [50, 50],
+ iconAnchor: [25, 50],
+});
+
+const MarkerLocation = ({ setValue }) => {
+ const location = useRef();
+ const map = useMapEvents({
+ move: (e) => {
+ const latlon = e.target.getCenter()
+ location.current?.setLatLng(latlon);
+ setValue('lat', latlon.lat)
+ setValue('lon', latlon.lng)
+ },
+ zoom: (e) => {
+ const latlon = e.target.getCenter()
+ location.current?.setLatLng(latlon);
+ setValue('lat', latlon.lat)
+ setValue('lon', latlon.lng)
+ },
+ });
+ return (
+
+ )
+}
+export default MarkerLocation
\ No newline at end of file
diff --git a/src/core/components/MapLayer/index.jsx b/src/core/components/MapLayer/index.jsx
new file mode 100644
index 0000000..52209da
--- /dev/null
+++ b/src/core/components/MapLayer/index.jsx
@@ -0,0 +1,43 @@
+"use client";
+import { MapContainer, TileLayer, useMap } from "react-leaflet";
+
+export const IRAN_CENTER = L.latLng(32.4279, 53.6880);
+
+const MapOptions = ({ options }) => {
+ const map = useMap();
+ if (!options) return;
+
+ if (options.mapDrag) {
+ map.dragging.enable();
+ map.scrollWheelZoom.enable();
+ map.touchZoom.enable();
+ map.doubleClickZoom.enable();
+ } else {
+ map.dragging.disable();
+ map.scrollWheelZoom.disable();
+ map.touchZoom.disable();
+ map.doubleClickZoom.disable();
+ }
+};
+
+function MapLayer({ children, style, otherLayers, options }) {
+ return (
+ <>
+
+
+
+ {children}
+
+ {otherLayers}
+ >
+ );
+}
+
+export default MapLayer;
\ No newline at end of file
diff --git a/src/core/components/StyledForm.jsx b/src/core/components/StyledForm.jsx
new file mode 100644
index 0000000..4513129
--- /dev/null
+++ b/src/core/components/StyledForm.jsx
@@ -0,0 +1,5 @@
+import { styled } from "@mui/material";
+
+const StyledForm = styled('form')``;
+
+export default StyledForm;
diff --git a/src/core/utils/routes.js b/src/core/utils/routes.js
index 62273df..7c0f4dc 100644
--- a/src/core/utils/routes.js
+++ b/src/core/utils/routes.js
@@ -1,6 +1,10 @@
const api = process.env.NEXT_PUBLIC_API_URL;
+export const GET_CSRF = api + "/csrf";
+
export const GET_USER_ROUTE = api + "/webapi/user/get-permission";
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";
diff --git a/src/lib/hooks/useRequest.js b/src/lib/hooks/useRequest.js
index 2e35512..8805a56 100644
--- a/src/lib/hooks/useRequest.js
+++ b/src/lib/hooks/useRequest.js
@@ -1,7 +1,18 @@
import { errorResponse } from "@/core/utils/errorResponse";
+import { GET_CSRF } from "@/core/utils/routes";
import { successRequest } from "@/core/utils/successRequest";
import axios from "axios";
+const getCsrfToken = async () => {
+ try {
+ const response = await axios.get(GET_CSRF);
+ return response.data.data;
+ } catch (error) {
+ console.error("Error fetching CSRF token:", error);
+ throw error;
+ }
+};
+
const defaultOptions = {
data: {},
requestOptions: {
@@ -15,13 +26,27 @@ const defaultOptions = {
};
const useRequest = (initOptions) => {
+ const instance = axios.create();
+ instance.interceptors.request.use(
+ async function (config) {
+ if (config.method !== 'get') {
+ const csrfToken = await getCsrfToken();
+ config.headers['X-CSRF-TOKEN'] = csrfToken;
+ }
+ return config;
+ },
+ function (error) {
+ return Promise.reject(error);
+ }
+ );
+
const _options = Object.assign({}, defaultOptions, initOptions);
return async (url = "", method = "get", options) => {
const mergedOptions = Object.assign({}, _options, options);
try {
- const response = await axios({
+ const response = await instance({
url,
method,
data: method === "get" ? null : mergedOptions.data,