commit aac857cf2d52e271630363fc6a9167af0149fba9
Author: Fantič <58391275+FantaFantic@users.noreply.github.com>
Date:   Sat Nov 11 12:47:05 2023 +0100

    re #10871: PlanViewPage: CastlePlanView init : get map image

diff --git a/package.json b/package.json
index 0d70ffc..6ba200a 100644
--- a/package.json
+++ b/package.json
@@ -26,6 +26,7 @@
     "react-native-deck-swiper": "^1.1.7",
     "react-native-gesture-handler": "~2.12.0",
     "react-native-logs": "^5.0.1",
+    "react-native-maps": "^1.8.0",
     "react-native-multiple-select": "^0.5.12",
     "react-native-reanimated": "~3.3.0",
     "react-native-safe-area-context": "4.6.3",
@@ -43,6 +44,7 @@
     "@tsconfig/react-native": "^2.0.3",
     "@types/jest": "^29.5.0",
     "@types/react": "~18.2.14",
+    "@types/react-native-maps": "^0.24.2",
     "@types/react-test-renderer": "^18.0.0",
     "typescript": "^5.1.3"
   },
diff --git a/src/api/planservice.ts b/src/api/planservice.ts
index be89983..7067c6a 100644
--- a/src/api/planservice.ts
+++ b/src/api/planservice.ts
@@ -13,12 +13,11 @@ export const getPlanListRequest = async () => {
     )
 }
 
-
-
+export const getPlanFloorImageRequest = async (floorId: string) => {
+    return await axiosInstance.get(`/downloads/${floorId}`);
+}
 
 /*
-
-
 // inventories
 @activeTab: index of selected inventory: result: Inventories (starting from 0)
 
diff --git a/src/components/plan/CastlePlanView.tsx b/src/components/plan/CastlePlanView.tsx
new file mode 100644
index 0000000..7105ee0
--- /dev/null
+++ b/src/components/plan/CastlePlanView.tsx
@@ -0,0 +1,33 @@
+import { VStack, Box, Text, HStack, ScrollView, Flex, Button, CloseIcon, IconButton, TextArea, useToast } from "native-base";
+import { Note } from "../../types/note";
+import React, { useCallback, useState } from "react";
+import { Floor, Room } from "../../types/plan";
+
+import MapView, { Marker } from 'react-native-maps';
+import Svg, { Image, SvgXml } from 'react-native-svg';
+import SvgImage from "react-native-svg/lib/typescript/elements/Image";
+
+const CastlePlanView = (props: { mapImage : string, selectedRoom?: Room }) => {
+
+    const { mapImage, selectedRoom } = props
+
+    console.log(mapImage.substring(0,500))
+
+    return (
+        <Box h={300}>
+            {/* Display the background image */}
+            <SvgXml
+                xml={mapImage}
+            />
+
+            {/* Display the MapView on top of the background image */}
+            <MapView
+                style={{ flex: 1 }}
+            // Add other map-related props as needed
+            >
+            </MapView>
+        </Box>
+    );
+}
+
+export default CastlePlanView
\ No newline at end of file
diff --git a/src/components/plan/PlanView.tsx b/src/components/plan/PlanView.tsx
deleted file mode 100644
index 5184017..0000000
--- a/src/components/plan/PlanView.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import { VStack, Box, Text, HStack, ScrollView, Flex, Button, CloseIcon, IconButton, TextArea, useToast, Image } from "native-base";
-import { Note } from "../../types/note";
-import React, { useCallback, useState } from "react";
-
-
-
-
-const PlanView = (props: { imageUrl: string }) => {
-    return (
-        <Image size={250} alt="image" source={{ uri: props.imageUrl }} />
-    );
-}
-
-export default PlanView
\ No newline at end of file
diff --git a/src/pages/PlanViewPage.tsx b/src/pages/PlanViewPage.tsx
index a28507f..8de024f 100644
--- a/src/pages/PlanViewPage.tsx
+++ b/src/pages/PlanViewPage.tsx
@@ -8,15 +8,16 @@ import { RootDrawerParamList } from "./Navigation"
 import { Box, CloseIcon, Select, useToast, Button, Flex, Text, Center, VStack, ScrollView } from "native-base"
 import { ErrorToast } from "../components/toast/ErrorToast"
 import { Floor, Place, Room } from "../types/plan"
-import { getFloorList, getPlanInventories, getPlanItems } from "../stores/actions/planThunks"
+import { getFloorList, getPlanFloorImage, getPlanInventories, getPlanItems } from "../stores/actions/planThunks"
 import { login } from "../stores/actions/userThunks"
 import { getPlanItemsRequest } from "../api/planservice"
 import ItemPreview from "../components/listView/ItemPreview"
-import PlanView from "../components/plan/PlanView"
+import PlanView from "../components/plan/CastlePlanView"
 import { BASE_API_URL } from "../api/constants"
 import ListView from "../components/listView/ListView"
 import SearchForm from "../components/search/SearchForm"
 import { loadItemsByInventory } from "../stores/actions/listViewThunks"
+import CastlePlanView from "../components/plan/CastlePlanView"
 
 const PlanViewPage = ({ route, navigation }: DrawerScreenProps<RootDrawerParamList, 'Plan'>) => {
 
@@ -46,6 +47,9 @@ const PlanViewPage = ({ route, navigation }: DrawerScreenProps<RootDrawerParamLi
   const dataLoading = useSelector((state: RootState) => state.planViewState.itemListLoading)
   const pagination = useSelector((state: RootState) => state.planViewState.itemListPagination)
 
+  const floorMapImage = useSelector((state: RootState) => state.planViewState.mapImage)
+  const floorMapImageLoading = useSelector((state: RootState) => state.planViewState.mapImageLoading)
+
   const toast = useToast();
 
   useEffect(() => {
@@ -62,7 +66,6 @@ const PlanViewPage = ({ route, navigation }: DrawerScreenProps<RootDrawerParamLi
         // if (!itemListLoading) {
         //   searchSubmit(currentPage, route.params.roomId, route.params.placeId)
         // }
-
       }
       else {
         selectFloor(DEFAULT_FLOOR)
@@ -78,6 +81,13 @@ const PlanViewPage = ({ route, navigation }: DrawerScreenProps<RootDrawerParamLi
     }
   }, [selectedPlace, selectedRoom])
 
+  useEffect(() => {
+    if (selectedFloor) {
+      console.log("Dispatching getFloorImage " + selectedFloor.id)
+      dispatch(getPlanFloorImage(selectedFloor.id))
+    }
+  }, [selectedFloor])
+
 
   useEffect(() => {
     if (lastError) {
@@ -283,9 +293,13 @@ const PlanViewPage = ({ route, navigation }: DrawerScreenProps<RootDrawerParamLi
           {/* Plan */}
           {/* temporary prototype */}
 
-          {/* {selectedFloor && !floorListLoading &&
-            <PlanView imageUrl={BASE_API_URL + "/downloads/" + selectedFloor.id} />
-          } */}
+          {selectedFloor && !floorListLoading && (
+            floorMapImageLoading ?
+              <LoadingBox text="Loading castle plan" />
+              :
+              floorMapImage && <CastlePlanView mapImage={floorMapImage} selectedRoom={selectedRoom} />
+          )
+          }
 
           {/* Item List */}
           <>
diff --git a/src/stores/actions/planThunks.ts b/src/stores/actions/planThunks.ts
index 0e73fbb..8ec0e2e 100644
--- a/src/stores/actions/planThunks.ts
+++ b/src/stores/actions/planThunks.ts
@@ -1,7 +1,7 @@
 import { createAsyncThunk } from "@reduxjs/toolkit"
 import { SortOptions } from "../../types/general";
 import { Note } from "../../types/note";
-import { getPlanAllRequest, getPlanItemsRequest } from "../../api/planservice";
+import { getPlanAllRequest, getPlanFloorImageRequest, getPlanItemsRequest } from "../../api/planservice";
 import { Floor, Room } from "../../types/plan";
 import { ItemPreviewType } from "../../types/listViewTypes";
 import { StringLiteralType } from "typescript";
@@ -64,9 +64,6 @@ export const getPlanInventories = createAsyncThunk(
                 const response = await getPlanItemsRequest({ cursor: 0, room: params.room, items: 1, place: params.place })
                 if (response.status === 200) {
 
-                    console.log("response")
-                    console.log(response.data.pagination.inventories)
-
                     const inventories: Inventory[] = response.data.pagination.inventories
                     const allInventoriesRecords = response.data.pagination.records
 
@@ -113,6 +110,29 @@ export const getPlanItems = createAsyncThunk(
                 return Promise.reject(err.response.data)
             }
 
+        } catch (err: any) {
+            console.log(err);
+            return Promise.reject(err.response.data)
+        }
+    }
+)
+
+export const getPlanFloorImage = createAsyncThunk(
+    "plan/getPlanFloorImage",
+    async (floorId: string) => {
+        try {
+            try {
+                const response = await getPlanFloorImageRequest(floorId)
+
+                if (response.status === 200) {
+                    return response.data
+                } else {
+                    return Promise.reject(response.data ? response.data : "Get plan floor image request failed")
+                }
+            } catch (err: any) {
+                return Promise.reject(err.response.data)
+            }
+
         } catch (err: any) {
             console.log(err);
             return Promise.reject(err.response.data)
diff --git a/src/stores/reducers/planSlice.ts b/src/stores/reducers/planSlice.ts
index 7804cc1..ff096ae 100644
--- a/src/stores/reducers/planSlice.ts
+++ b/src/stores/reducers/planSlice.ts
@@ -1,6 +1,6 @@
 import { PayloadAction, createSlice } from "@reduxjs/toolkit"
 import { PlanViewState } from "../../types/plan";
-import { getFloorList, getPlanInventories, getPlanItems } from "../actions/planThunks";
+import { getFloorList, getPlanFloorImage, getPlanInventories, getPlanItems } from "../actions/planThunks";
 
 const initialState: PlanViewState = {
     lastError: "",
@@ -96,6 +96,19 @@ export const planSlice = createSlice({
             state.itemInventoriesLoading = false;
             state.lastError = action.error.message
         })
+
+        // getPlanFloorImage
+        builder.addCase(getPlanFloorImage.fulfilled, (state, action) => {
+            state.mapImage = action.payload
+            state.mapImageLoading = false
+        })
+        builder.addCase(getPlanFloorImage.pending, (state, action) => {
+            state.mapImageLoading = true
+        })
+        builder.addCase(getPlanFloorImage.rejected, (state, action) => {
+            state.mapImageLoading = false;
+            state.lastError = action.error.message
+        })
     }
 })
 
diff --git a/src/types/plan.ts b/src/types/plan.ts
index 21f884c..3044782 100644
--- a/src/types/plan.ts
+++ b/src/types/plan.ts
@@ -51,8 +51,8 @@ export type PlanViewState = {
     itemList: Record<string, ItemPreviewType[]>
 
     // plan
-    // @TODO
-
+    mapImage?: string
+    mapImageLoading?: boolean
 
     // last error
     lastError?: string
