From 38b68875089e6adc834ee2205cc71523fa41c0e5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adrian=20Or=C5=82=C3=B3w?= <adrian.orlow@fishbrain.com>
Date: Tue, 17 Oct 2023 23:19:04 +0200
Subject: [PATCH] feat(map): improve usage of selectors and types in map module

---
 .../Map/MapViewer/utils/useOlMapConfig.ts     | 23 ++++++++++---------
 src/redux/map/map.selectors.ts                |  8 +++++--
 src/redux/map/map.types.ts                    |  8 ++-----
 src/types/fetchDataState.ts                   |  4 ++--
 src/utils/map/usePointToProjection.ts         |  8 +++----
 5 files changed, 26 insertions(+), 25 deletions(-)

diff --git a/src/components/Map/MapViewer/utils/useOlMapConfig.ts b/src/components/Map/MapViewer/utils/useOlMapConfig.ts
index bbb5384e..9ac87292 100644
--- a/src/components/Map/MapViewer/utils/useOlMapConfig.ts
+++ b/src/components/Map/MapViewer/utils/useOlMapConfig.ts
@@ -1,6 +1,6 @@
 /* eslint-disable no-magic-numbers */
 import { OPTIONS } from '@/constants/map';
-import { mapDataSelector } from '@/redux/map/map.selectors';
+import { mapDataPositionSelector, mapDataSizeSelector } from '@/redux/map/map.selectors';
 import { Point } from '@/types/map';
 import { usePointToProjection } from '@/utils/map/usePointToProjection';
 import { View } from 'ol';
@@ -16,26 +16,27 @@ interface UseOlMapConfigResult {
 }
 
 export const useOlMapConfig = (): UseOlMapConfigResult => {
-  const { data: mapData } = useSelector(mapDataSelector);
+  const mapPosition = useSelector(mapDataPositionSelector);
+  const mapSize = useSelector(mapDataSizeSelector);
   const pointToProjection = usePointToProjection();
 
   const center = useMemo(() => {
     const centerPoint: Point = {
-      x: mapData.position.x,
-      y: mapData.position.y,
+      x: mapPosition.x,
+      y: mapPosition.y,
     };
 
     return pointToProjection(centerPoint);
-  }, [mapData.position, pointToProjection]);
+  }, [mapPosition, pointToProjection]);
 
   const view = useMemo(
     () =>
       new View({
         center,
-        zoom: mapData.position.z,
+        zoom: mapPosition.z,
         showFullExtent: OPTIONS.showFullExtent,
       }),
-    [center, mapData.position],
+    [center, mapPosition],
   );
 
   const tileLayer = useMemo(
@@ -45,13 +46,13 @@ export const useOlMapConfig = (): UseOlMapConfigResult => {
         source: new XYZ({
           url: 'https://pdmap.uni.lu/map_images/9d4911bdeeea752f076e57a91d9b1f45/_nested0/{z}/{x}/{y}.PNG',
           // TODO: build url from data in redux
-          maxZoom: mapData.size.maxZoom,
-          minZoom: mapData.size.minZoom,
-          tileSize: mapData.size.tileSize,
+          maxZoom: mapSize.maxZoom,
+          minZoom: mapSize.minZoom,
+          tileSize: mapSize.tileSize,
           wrapX: OPTIONS.wrapXInTileLayer,
         }),
       }),
-    [mapData.size],
+    [mapSize],
   );
 
   return {
diff --git a/src/redux/map/map.selectors.ts b/src/redux/map/map.selectors.ts
index 9e559fd4..e5bbcfe7 100644
--- a/src/redux/map/map.selectors.ts
+++ b/src/redux/map/map.selectors.ts
@@ -1,4 +1,8 @@
-import { createSelector } from '@reduxjs/toolkit';
 import { rootSelector } from '@/redux/root/root.selectors';
+import { createSelector } from '@reduxjs/toolkit';
+
+export const mapDataSelector = createSelector(rootSelector, state => state.map.data);
+
+export const mapDataSizeSelector = createSelector(mapDataSelector, map => map.size);
 
-export const mapDataSelector = createSelector(rootSelector, state => state.map);
+export const mapDataPositionSelector = createSelector(mapDataSelector, map => map.position);
diff --git a/src/redux/map/map.types.ts b/src/redux/map/map.types.ts
index 245bd58a..95fafc9a 100644
--- a/src/redux/map/map.types.ts
+++ b/src/redux/map/map.types.ts
@@ -1,4 +1,4 @@
-import { Loading } from '@/types/loadingState';
+import { FetchDataState } from '@/types/fetchDataState';
 import { Point } from '@/types/map';
 
 export interface MapSize {
@@ -22,8 +22,4 @@ export type MapData = {
   };
 };
 
-export type MapState = {
-  data: MapData;
-  loading: Loading;
-  error: Error;
-};
+export type MapState = FetchDataState<MapData, MapData>;
diff --git a/src/types/fetchDataState.ts b/src/types/fetchDataState.ts
index 918bfd46..a218c966 100644
--- a/src/types/fetchDataState.ts
+++ b/src/types/fetchDataState.ts
@@ -1,7 +1,7 @@
 import { Loading } from './loadingState';
 
-export type FetchDataState<T> = {
-  data: T | undefined;
+export type FetchDataState<T, T2 = undefined> = {
+  data: T | T2;
   loading: Loading;
   error: Error;
 };
diff --git a/src/utils/map/usePointToProjection.ts b/src/utils/map/usePointToProjection.ts
index 60caae36..281a33bb 100644
--- a/src/utils/map/usePointToProjection.ts
+++ b/src/utils/map/usePointToProjection.ts
@@ -1,5 +1,5 @@
 import { LATLNG_FALLBACK } from '@/constants/map';
-import { mapDataSelector } from '@/redux/map/map.selectors';
+import { mapDataSizeSelector } from '@/redux/map/map.selectors';
 import { Point } from '@/types/map';
 import { Coordinate } from 'ol/coordinate';
 import { fromLonLat } from 'ol/proj';
@@ -12,17 +12,17 @@ type UsePointToProjectionResult = (point: Point) => Coordinate;
 type UsePointToProjection = () => UsePointToProjectionResult;
 
 export const usePointToProjection: UsePointToProjection = () => {
-  const map = useSelector(mapDataSelector);
+  const mapSize = useSelector(mapDataSizeSelector);
 
   const pointToProjection = useCallback(
     (point: Point): Coordinate => {
-      const [lng, lat] = pointToLatLng(point, map.data.size);
+      const [lng, lat] = pointToLatLng(point, mapSize);
       const projection = fromLonLat([lng, lat]);
       const isValid = !projection.some(v => Number.isNaN(v));
 
       return isValid ? projection : LATLNG_FALLBACK;
     },
-    [map.data.size],
+    [mapSize],
   );
 
   return pointToProjection;
-- 
GitLab