diff --git a/src/components/dashboard/roadMissions/operator/Actions/Create/Form/Area/Routing/AlarmText.jsx b/src/components/dashboard/roadMissions/operator/Actions/Create/Form/Area/Routing/AlarmText.jsx
new file mode 100644
index 0000000..0a3be1b
--- /dev/null
+++ b/src/components/dashboard/roadMissions/operator/Actions/Create/Form/Area/Routing/AlarmText.jsx
@@ -0,0 +1,28 @@
+import { Box, Typography } from "@mui/material";
+
+const AlarmText = ({ isSource }) => {
+ if (isSource) return null;
+ return (
+
+
+ با کلیک بر روی مارکر موقعیت را انتخاب کنید
+
+
+ );
+};
+
+export default AlarmText;
diff --git a/src/components/dashboard/roadMissions/operator/Actions/Create/Form/Area/Routing/DataBox.jsx b/src/components/dashboard/roadMissions/operator/Actions/Create/Form/Area/Routing/DataBox.jsx
index 5269a52..c19cb6f 100644
--- a/src/components/dashboard/roadMissions/operator/Actions/Create/Form/Area/Routing/DataBox.jsx
+++ b/src/components/dashboard/roadMissions/operator/Actions/Create/Form/Area/Routing/DataBox.jsx
@@ -27,9 +27,11 @@ const DataBox = ({ isSource, isDest, sourcePosition, destPosition, editingTarget
readOnly
value={sourcePosition ? `${sourcePosition.lat.toFixed(6)}, ${sourcePosition.lng.toFixed(6)}` : ""}
/>
-
+ {isSource && isDest && (
+
+ )}
{isDest && (
diff --git a/src/components/dashboard/roadMissions/operator/Actions/Create/Form/Area/Routing/ShowRoute.jsx b/src/components/dashboard/roadMissions/operator/Actions/Create/Form/Area/Routing/ShowRoute.jsx
new file mode 100644
index 0000000..8cc7e90
--- /dev/null
+++ b/src/components/dashboard/roadMissions/operator/Actions/Create/Form/Area/Routing/ShowRoute.jsx
@@ -0,0 +1,46 @@
+import { useEffect, useRef } from "react";
+import { Marker, Polyline, useMap } from "react-leaflet";
+import L from "leaflet";
+import polyline from "@mapbox/polyline";
+import SourceIcon from "@/assets/images/source-icon.svg";
+import DestIcon from "@/assets/images/destination-icon.svg";
+
+const ShowRoute = ({ area }) => {
+ const map = useMap();
+ 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 sourceIcon = createCustomIcon(defaultIconSize, SourceIcon.src);
+ const destIcon = createCustomIcon(defaultIconSize, DestIcon.src);
+
+ if (!area) return null;
+ const coords = polyline.decode(area, 6);
+
+ if (coords.length === 0) return null;
+
+ const sourcePosition = coords[0];
+ const destPosition = coords[coords.length - 1];
+ useEffect(() => {
+ if (coords.length > 0) {
+ map.flyToBounds(coords, { padding: [50, 50], duration: 1.5 });
+ }
+ }, [area]);
+
+ return (
+ <>
+
+
+
+ >
+ );
+};
+
+export default ShowRoute;
diff --git a/src/components/dashboard/roadMissions/operator/Actions/Create/Form/Area/Routing/index.jsx b/src/components/dashboard/roadMissions/operator/Actions/Create/Form/Area/Routing/index.jsx
index 4f1e47a..06e7c9b 100644
--- a/src/components/dashboard/roadMissions/operator/Actions/Create/Form/Area/Routing/index.jsx
+++ b/src/components/dashboard/roadMissions/operator/Actions/Create/Form/Area/Routing/index.jsx
@@ -5,12 +5,14 @@ import SourceIcon from "@/assets/images/source-icon.svg";
import PrevSourceIcon from "@/assets/images/prev-source-icon.svg";
import PrevDestIcon from "@/assets/images/prev-destination-icon.svg";
import DestIcon from "@/assets/images/destination-icon.svg";
-import { useRef, useState } from "react";
+import { useEffect, useRef, useState } from "react";
import DataBox from "./DataBox";
+import AlarmText from "./AlarmText";
-const Routing = () => {
+const Routing = ({ setArea, setLocations, locations, area }) => {
const mapPrevSourceMarker = useRef();
const mapPrevDestMarker = useRef();
+ const mapRef = useRef(null);
const defaultIconSize = [35, 35];
const [isSource, setIsSource] = useState(false);
const [sourcePosition, setSourcePosition] = useState(null);
@@ -45,33 +47,48 @@ const Routing = () => {
const map = useMapEvents({
move(e) {
- if (isMovingSource) {
- mapPrevSourceMarker.current.setLatLng(e.target.getCenter());
- }
- if (isMovingDest && mapPrevDestMarker.current) {
- mapPrevDestMarker.current.setLatLng(e.target.getCenter());
- }
+ if (isMovingSource) mapPrevSourceMarker.current.setLatLng(e.target.getCenter());
+ if (isMovingDest && mapPrevDestMarker.current) mapPrevDestMarker.current.setLatLng(e.target.getCenter());
},
movestart() {
- if (isMovingSource) {
- mapPrevSourceMarker.current.setIcon(createCustomIcon([45, 45], PrevSourceIcon.src));
- }
- if (isMovingDest && mapPrevDestMarker.current) {
+ if (isMovingSource) mapPrevSourceMarker.current.setIcon(createCustomIcon([45, 45], PrevSourceIcon.src));
+ if (isMovingDest && mapPrevDestMarker.current)
mapPrevDestMarker.current.setIcon(createCustomIcon([45, 45], PrevDestIcon.src));
- }
},
moveend() {
- if (isMovingSource) {
+ if (isMovingSource)
mapPrevSourceMarker.current.setIcon(createCustomIcon(defaultIconSize, PrevSourceIcon.src));
- }
- if (isMovingDest && mapPrevDestMarker.current) {
+ if (isMovingDest && mapPrevDestMarker.current)
mapPrevDestMarker.current.setIcon(createCustomIcon(defaultIconSize, PrevDestIcon.src));
- }
},
});
+ useEffect(() => {
+ mapRef.current = map;
+ }, [map]);
+
+ useEffect(() => {
+ if (locations.length < 2) return;
+ const restoredSource = { lat: locations[0].lat, lng: locations[0].lon };
+ const restoredDest = { lat: locations[1].lat, lng: locations[1].lon };
+ setSourcePosition(restoredSource);
+ setDestPosition(restoredDest);
+ setIsSource(true);
+ setIsDest(true);
+ if (area) {
+ const decoded = polyline.decode(area, 6);
+ setRouteCoords(decoded);
+ setSelectedRoute({ index: "main", coords: decoded });
+ setTimeout(() => {
+ mapRef.current?.flyToBounds(decoded, { padding: [50, 50], duration: 1.5 });
+ }, 100);
+ } else {
+ fetchRoute(restoredSource, restoredDest);
+ }
+ }, []);
+
const fetchRoute = async (source, dest) => {
- const locations = [
+ const locs = [
{ lat: source.lat, lon: source.lng },
{ lat: dest.lat, lon: dest.lng },
];
@@ -79,16 +96,17 @@ const Routing = () => {
const response = await fetch("https://jouya.141.ir/api/router/drive", {
method: "POST",
headers: { "Content-Type": "application/json" },
- body: JSON.stringify({ locations }),
+ body: JSON.stringify({ locations: locs }),
});
const data = await response.json();
-
const shape = data.trip.legs[0].shape;
+ setLocations(locs);
+ setArea(shape);
const decoded = polyline.decode(shape, 6);
setRouteCoords(decoded);
setSelectedRoute({ index: "main", coords: decoded });
- if (data.alternates && data.alternates.length > 0) {
+ if (data.alternates?.length > 0) {
const decodedAlternates = data.alternates.map((alt) => polyline.decode(alt.trip.legs[0].shape, 6));
setAlternateCoords(decodedAlternates);
} else {
@@ -103,7 +121,6 @@ const Routing = () => {
const handleMarkerClick = async () => {
if (!isSource || editingTarget === "source") {
const clickedPosition = mapPrevSourceMarker.current.getLatLng();
- console.log("Source:", clickedPosition.lat, clickedPosition.lng);
setSourcePosition(clickedPosition);
setIsSource(true);
setEditingTarget(null);
@@ -144,8 +161,9 @@ const Routing = () => {
const handleSelectRoute = (index, coords) => {
setSelectedRoute({ index, coords });
+ const encoded = polyline.encode(coords, 6);
+ setArea(encoded);
map.flyToBounds(coords, { padding: [50, 50], duration: 0.3 });
- console.log("Selected route:", index, coords);
};
return (
@@ -159,6 +177,7 @@ const Routing = () => {
onEditSource={handleEditSource}
onEditDest={handleEditDest}
/>
+
import("@/core/components/MapLayer"), {
});
const Area = ({ allData, setAllData, handlePrev, setTabState }) => {
- const [bound, setBound] = useState(allData.bound);
+ const [area, setArea] = useState(allData.area);
+ const [locations, setLocations] = useState(allData.locations);
const handleNext = useCallback(() => {
- setAllData({ bound: bound });
+ setAllData({ area: area });
+ setAllData({ locations: locations });
setTabState((s) => s + 1);
- }, [bound]);
+ }, [area]);
return (
<>
@@ -22,7 +24,7 @@ const Area = ({ allData, setAllData, handlePrev, setTabState }) => {
-
+
@@ -31,8 +33,8 @@ const Area = ({ allData, setAllData, handlePrev, setTabState }) => {
-