fix: Fix edit entities on the map
				
					
				
			This commit is contained in:
		| @@ -22,6 +22,28 @@ interface ApiSight { | ||||
|   longitude: number; | ||||
| } | ||||
|  | ||||
| // Допуск для сравнения координат, чтобы избежать ошибок с точностью чисел. | ||||
| const COORDINATE_PRECISION_TOLERANCE = 1e-9; | ||||
|  | ||||
| // Вспомогательная функция, обновленная для сравнения с допуском. | ||||
| const arePathsEqual = ( | ||||
|   path1: [number, number][], | ||||
|   path2: [number, number][] | ||||
| ): boolean => { | ||||
|   if (path1.length !== path2.length) { | ||||
|     return false; | ||||
|   } | ||||
|   for (let i = 0; i < path1.length; i++) { | ||||
|     if ( | ||||
|       Math.abs(path1[i][0] - path2[i][0]) > COORDINATE_PRECISION_TOLERANCE || | ||||
|       Math.abs(path1[i][1] - path2[i][1]) > COORDINATE_PRECISION_TOLERANCE | ||||
|     ) { | ||||
|       return false; | ||||
|     } | ||||
|   } | ||||
|   return true; | ||||
| }; | ||||
|  | ||||
| class MapStore { | ||||
|   constructor() { | ||||
|     makeAutoObservable(this); | ||||
| @@ -33,25 +55,19 @@ class MapStore { | ||||
|  | ||||
|   getRoutes = async () => { | ||||
|     const routes = await languageInstance("ru").get("/route"); | ||||
|  | ||||
|     const routedIds = routes.data.map((route: any) => route.id); | ||||
|  | ||||
|     const mappedRoutes: ApiRoute[] = []; | ||||
|     for (const routeId of routedIds) { | ||||
|       const responseSoloRoute = await languageInstance("ru").get( | ||||
|         `/route/${routeId}` | ||||
|       ); | ||||
|       const route = responseSoloRoute.data; | ||||
|  | ||||
|       const mappedRoute = { | ||||
|       mappedRoutes.push({ | ||||
|         id: route.id, | ||||
|         route_number: route.route_number, | ||||
|         path: route.path, | ||||
|       }; | ||||
|  | ||||
|       mappedRoutes.push(mappedRoute); | ||||
|       }); | ||||
|     } | ||||
|  | ||||
|     this.routes = mappedRoutes.sort((a, b) => | ||||
|       a.route_number.localeCompare(b.route_number) | ||||
|     ); | ||||
| @@ -59,27 +75,23 @@ class MapStore { | ||||
|  | ||||
|   getStations = async () => { | ||||
|     const stations = await languageInstance("ru").get("/station"); | ||||
|     const mappedStations = stations.data.map((station: any) => ({ | ||||
|     this.stations = stations.data.map((station: any) => ({ | ||||
|       id: station.id, | ||||
|       name: station.name, | ||||
|       latitude: station.latitude, | ||||
|       longitude: station.longitude, | ||||
|     })); | ||||
|  | ||||
|     this.stations = mappedStations; | ||||
|   }; | ||||
|  | ||||
|   getSights = async () => { | ||||
|     const sights = await languageInstance("ru").get("/sight"); | ||||
|     const mappedSights = sights.data.map((sight: any) => ({ | ||||
|     this.sights = sights.data.map((sight: any) => ({ | ||||
|       id: sight.id, | ||||
|       name: sight.name, | ||||
|       description: sight.description, | ||||
|       latitude: sight.latitude, | ||||
|       longitude: sight.longitude, | ||||
|     })); | ||||
|  | ||||
|     this.sights = mappedSights; | ||||
|   }; | ||||
|  | ||||
|   deleteRecourse = async (recourse: string, id: number) => { | ||||
| @@ -94,31 +106,98 @@ class MapStore { | ||||
|   }; | ||||
|  | ||||
|   handleSave = async (json: string) => { | ||||
|     const sights: any[] = []; | ||||
|     const routes: any[] = []; | ||||
|     const stations: any[] = []; | ||||
|     const newSights: any[] = []; | ||||
|     const newRoutes: any[] = []; | ||||
|     const newStations: any[] = []; | ||||
|     const updatedSights: any[] = []; | ||||
|     const updatedRoutes: any[] = []; | ||||
|     const updatedStations: any[] = []; | ||||
|  | ||||
|     const parsedJSON = JSON.parse(json); | ||||
|     console.log("Данные для сохранения (GeoJSON):", parsedJSON); | ||||
|  | ||||
|     console.log(parsedJSON); | ||||
|     parsedJSON.features.forEach((feature: any) => { | ||||
|     for (const feature of parsedJSON.features) { | ||||
|       const { geometry, properties, id } = feature; | ||||
|       const idCanBeSplited = id.split("-"); | ||||
|       const idParts = String(id).split("-"); | ||||
|  | ||||
|       if (!(idCanBeSplited.length > 1)) { | ||||
|       if (idParts.length > 1) { | ||||
|         const featureType = idParts[0]; | ||||
|         const numericId = parseInt(idParts[1], 10); | ||||
|         if (isNaN(numericId)) continue; | ||||
|  | ||||
|         if (featureType === "station") { | ||||
|           const originalStation = this.stations.find((s) => s.id === numericId); | ||||
|           if (!originalStation) continue; | ||||
|  | ||||
|           const currentStation = { | ||||
|             name: properties.name || "", | ||||
|             latitude: geometry.coordinates[1], | ||||
|             longitude: geometry.coordinates[0], | ||||
|           }; | ||||
|  | ||||
|           // ИЗМЕНЕНИЕ: Сравнение координат с допуском | ||||
|           if ( | ||||
|             originalStation.name !== currentStation.name || | ||||
|             Math.abs(originalStation.latitude - currentStation.latitude) > | ||||
|               COORDINATE_PRECISION_TOLERANCE || | ||||
|             Math.abs(originalStation.longitude - currentStation.longitude) > | ||||
|               COORDINATE_PRECISION_TOLERANCE | ||||
|           ) { | ||||
|             updatedStations.push({ id: numericId, ...currentStation }); | ||||
|           } | ||||
|         } else if (featureType === "route") { | ||||
|           const originalRoute = this.routes.find((r) => r.id === numericId); | ||||
|           if (!originalRoute) continue; | ||||
|  | ||||
|           const currentRoute = { | ||||
|             route_number: properties.name || "", | ||||
|             path: geometry.coordinates, | ||||
|           }; | ||||
|  | ||||
|           // ИЗМЕНЕНИЕ: Используется новая функция arePathsEqual с допуском | ||||
|           if ( | ||||
|             originalRoute.route_number !== currentRoute.route_number || | ||||
|             !arePathsEqual(originalRoute.path, currentRoute.path) | ||||
|           ) { | ||||
|             updatedRoutes.push({ id: numericId, ...currentRoute }); | ||||
|           } | ||||
|         } else if (featureType === "sight") { | ||||
|           const originalSight = this.sights.find((s) => s.id === numericId); | ||||
|           if (!originalSight) continue; | ||||
|  | ||||
|           const currentSight = { | ||||
|             name: properties.name || "", | ||||
|             description: properties.description || "", | ||||
|             latitude: geometry.coordinates[1], | ||||
|             longitude: geometry.coordinates[0], | ||||
|           }; | ||||
|  | ||||
|           // ИЗМЕНЕНИЕ: Сравнение координат с допуском | ||||
|           if ( | ||||
|             originalSight.name !== currentSight.name || | ||||
|             originalSight.description !== currentSight.description || | ||||
|             Math.abs(originalSight.latitude - currentSight.latitude) > | ||||
|               COORDINATE_PRECISION_TOLERANCE || | ||||
|             Math.abs(originalSight.longitude - currentSight.longitude) > | ||||
|               COORDINATE_PRECISION_TOLERANCE | ||||
|           ) { | ||||
|             updatedSights.push({ id: numericId, ...currentSight }); | ||||
|           } | ||||
|         } | ||||
|       } else { | ||||
|         if (properties.featureType === "station") { | ||||
|           stations.push({ | ||||
|           newStations.push({ | ||||
|             name: properties.name || "", | ||||
|             latitude: geometry.coordinates[1], | ||||
|             longitude: geometry.coordinates[0], | ||||
|           }); | ||||
|         } else if (properties.featureType === "route") { | ||||
|           routes.push({ | ||||
|           newRoutes.push({ | ||||
|             route_number: properties.name || "", | ||||
|             path: geometry.coordinates, | ||||
|           }); | ||||
|         } else if (properties.featureType === "sight") { | ||||
|           sights.push({ | ||||
|           newSights.push({ | ||||
|             name: properties.name || "", | ||||
|             description: properties.description || "", | ||||
|             latitude: geometry.coordinates[1], | ||||
| @@ -126,16 +205,54 @@ class MapStore { | ||||
|           }); | ||||
|         } | ||||
|       } | ||||
|     }); | ||||
|     } | ||||
|  | ||||
|     for (const station of stations) { | ||||
|       await languageInstance("ru").post("/station", station); | ||||
|     const requests: Promise<any>[] = []; | ||||
|  | ||||
|     console.log( | ||||
|       `К созданию: ${newStations.length} станций, ${newRoutes.length} маршрутов, ${newSights.length} достопримечательностей.` | ||||
|     ); | ||||
|     console.log( | ||||
|       `К обновлению: ${updatedStations.length} станций, ${updatedRoutes.length} маршрутов, ${updatedSights.length} достопримечательностей.` | ||||
|     ); | ||||
|  | ||||
|     newStations.forEach((data) => | ||||
|       requests.push(languageInstance("ru").post("/station", data)) | ||||
|     ); | ||||
|     newRoutes.forEach((data) => | ||||
|       requests.push(languageInstance("ru").post("/route", data)) | ||||
|     ); | ||||
|     newSights.forEach((data) => | ||||
|       requests.push(languageInstance("ru").post("/sight", data)) | ||||
|     ); | ||||
|  | ||||
|     updatedStations.forEach(({ id, ...data }) => | ||||
|       requests.push(languageInstance("ru").patch(`/station/${id}`, data)) | ||||
|     ); | ||||
|     updatedRoutes.forEach(({ id, ...data }) => | ||||
|       requests.push(languageInstance("ru").patch(`/route/${id}`, data)) | ||||
|     ); | ||||
|     updatedSights.forEach(({ id, ...data }) => | ||||
|       requests.push(languageInstance("ru").patch(`/sight/${id}`, data)) | ||||
|     ); | ||||
|  | ||||
|     if (requests.length === 0) { | ||||
|       console.log("Нет изменений для сохранения."); | ||||
|       return; | ||||
|     } | ||||
|     for (const route of routes) { | ||||
|       await languageInstance("ru").post("/route", route); | ||||
|     } | ||||
|     for (const sight of sights) { | ||||
|       await languageInstance("ru").post("/sight", sight); | ||||
|  | ||||
|     try { | ||||
|       await Promise.all(requests); | ||||
|       console.log("Все изменения успешно сохранены!"); | ||||
|  | ||||
|       await Promise.all([ | ||||
|         this.getRoutes(), | ||||
|         this.getStations(), | ||||
|         this.getSights(), | ||||
|       ]); | ||||
|     } catch (error) { | ||||
|       console.error("Ошибка при сохранении данных:", error); | ||||
|       throw error; | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user