commit 160b70733d8eb91b375af45d8a03fa7091c3f85a
Author: Fantič <58391275+FantaFantic@users.noreply.github.com>
Date:   Thu Nov 9 19:49:08 2023 +0100

    re #10844: PlanViewPage: GetItemInventories, GetPlanItems

diff --git a/src/api/planservice.ts b/src/api/planservice.ts
index 7f8fd4f..3ef2780 100644
--- a/src/api/planservice.ts
+++ b/src/api/planservice.ts
@@ -13,13 +13,40 @@ export const getPlanListRequest = async () => {
     )
 }
 
-export const getPlanItemsRequest = async (page: number, pageSize: number, room: number, place?: number) => {
-    let url = `search_v2?activeTab=0&tabbed=false&cursor=0&page=${page}&items=${pageSize}&room=${room}`
 
-    if(place){
-        url += `&place=${place}`
+
+
+/*
+
+
+// inventories
+@activeTab: index of selected inventory: result: Inventories (starting from 0)
+
+// pagination
+@page: page number (starting from 1) -> current page is returned as result
+@items: page size
+@cursor: (page - 1) * pageSize ? 
+
+
+// location
+@room: id of room in which we are looking for items
+@place: id of place inside a room in which we are looking for items
+*/
+export const getPlanItemsRequest = async (params: {activeTab: number, page: number, room: number, items: number, place?: number, inventory?: string}) => {
+
+
+    let url = `search_v2?activeTab=${params.activeTab}&page=${params.page}&tabbed=true&room=${params.room}&cursor=${(params.page - 1)*params.items}&items=${params.items}`
+
+    if(params.place){
+        url += `&place=${params.place}`
     }
 
+    if(params.inventory){
+        url += `&inventory=${params.inventory}`
+    }
+
+    console.log(url)
+
     return await axiosInstance.get(
         url
     )
diff --git a/src/components/plan/PlanView.tsx b/src/components/plan/PlanView.tsx
new file mode 100644
index 0000000..5184017
--- /dev/null
+++ b/src/components/plan/PlanView.tsx
@@ -0,0 +1,14 @@
+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 7e90046..9e3eff3 100644
--- a/src/pages/PlanViewPage.tsx
+++ b/src/pages/PlanViewPage.tsx
@@ -6,27 +6,31 @@ import LoadingBox from "../components/loading/LoadingBox"
 import { log } from "../logging/logger"
 import { DrawerScreenProps } from "@react-navigation/drawer"
 import { RootDrawerParamList } from "./Navigation"
-import { Box, CloseIcon, Select, useToast, Button, Flex } from "native-base"
+import { Box, CloseIcon, Select, useToast, Button, Flex, Text } from "native-base"
 import { ErrorToast } from "../components/toast/ErrorToast"
 import { Floor, Place, Room } from "../types/plan"
-import { getFloorList } from "../stores/actions/planThunks"
+import { getFloorList, getPlanInventories, getPlanItems } from "../stores/actions/planThunks"
 import { login } from "../stores/actions/userThunks"
+import { getPlanItemsRequest } from "../api/planservice"
+import ItemPreview from "../components/listView/ItemPreview"
+import { parseArtists, parseImage } from "../components/listView/ListViewInventoryGroup"
+import PlanView from "../components/plan/PlanView"
+import { BASE_API_URL } from "../api/constants"
 
 const PlanViewPage = ({ route, navigation }: DrawerScreenProps<RootDrawerParamList, 'Plan'>) => {
 
   const layout = useWindowDimensions();
 
-    // Route: set selected room / place from 
-    useEffect(() => {
-        console.log("dispatching get floor list")
-        // dispatch(login({username: "Viktorie", password: "Golem123."}))
-        dispatch(getFloorList())
-    }, [])
-
+  // Route: set selected room / place from 
+  useEffect(() => {
+    console.log("dispatching get floor list")
+    // dispatch(login({username: "Viktorie", password: "Golem123."}))
+    dispatch(getFloorList())
+  }, [])
 
-  let page = 1
-  let pageSize = 20
-  let room = 0
+  const pageSize = 20
+  const currentPage = 0
+  const totalPages = 100
 
   const DEFAULT_FLOOR = "first_floor"
 
@@ -36,7 +40,7 @@ const PlanViewPage = ({ route, navigation }: DrawerScreenProps<RootDrawerParamLi
 
   const dispatch = useDispatch<AppDispatch>();
 
-  const { floorListLoading, floorList, itemListLoading, itemList, lastError } = useSelector((state: RootState) => state.planViewState)
+  const { floorListLoading, floorList, itemListLoading, itemList, itemInventories, itemInventoriesLoading, totalItemsCount, lastError } = useSelector((state: RootState) => state.planViewState)
 
   const toast = useToast();
 
@@ -45,20 +49,31 @@ const PlanViewPage = ({ route, navigation }: DrawerScreenProps<RootDrawerParamLi
       if (route.params && route.params.roomId) {
 
         selectRoom(route.params.roomId)
-  
+
         if (route.params.placeId) {
           selectPlace(route.params.placeId)
         }
-  
-        // todo dispatch get items
-        // getPlanItems(page, pageSize, room)
+
+        if (!itemListLoading) {
+          searchSubmit(currentPage, route.params.roomId, route.params.placeId)
+        }
+
       }
-      else{
+      else {
         selectFloor(DEFAULT_FLOOR)
       }
     }
   }, [floorList, route.params.roomId, route.params.placeId])
 
+  useEffect(() => {
+    if (floorList && selectedRoom) {
+      if (!itemInventoriesLoading) {
+        dispatch(getPlanInventories({ room: selectedRoom.id, place: selectedPlace?.id }))
+      }
+    }
+  }, [selectedPlace, selectedRoom])
+
+
   useEffect(() => {
     if (lastError) {
       toast.closeAll()
@@ -74,9 +89,12 @@ const PlanViewPage = ({ route, navigation }: DrawerScreenProps<RootDrawerParamLi
   }, [lastError])
 
 
-  const searchSubmit = () => {
+  const searchSubmit = (pageNumber: number, roomId: number, placeId?: number) => {
     log.debug("PlanView", "searchSubmit")
 
+    console.log("searching " + roomId + ", " + placeId)
+
+    dispatch(getPlanItems({ page: pageNumber, items: pageSize, room: roomId, place: placeId, activeTab: 0 }))
   }
 
   const selectFloor = (floorId: string) => {
@@ -232,7 +250,15 @@ const PlanViewPage = ({ route, navigation }: DrawerScreenProps<RootDrawerParamLi
                 Reset
               </Button>
               <Button
-                onPress={() => searchSubmit()}
+                onPress={() => {
+                  if (selectedRoom && !selectedPlace) {
+                    searchSubmit(currentPage, selectedRoom.id)
+                  }
+                  else if (selectedRoom && selectedPlace) {
+                    searchSubmit(currentPage, selectedRoom.id, selectedPlace.id)
+                  }
+
+                }}
                 colorScheme="primary"
                 background={"primary.100"}
                 variant="solid"
@@ -248,20 +274,43 @@ const PlanViewPage = ({ route, navigation }: DrawerScreenProps<RootDrawerParamLi
 
 
       {/* Plan */}
+      {/* temporary prototype */}
 
+      {selectedFloor && !floorListLoading &&
+        <PlanView imageUrl={BASE_API_URL + "/downloads/" + selectedFloor.id} />
+      }
 
       {/* Item List */}
+      <>
+        {itemInventoriesLoading ?
+          <LoadingBox text="Loading available inventories..." />
+          :
+          <>
+            <Text>TODO view inventories in SearchItemPreview way</Text>
+            {itemInventories.map((inventory) => {
+              <Text>{inventory.label}</Text>
+            })}
+          </>
+
+        }
+        {/* 
+        {itemList.map((item, index) => {
+          return (
+            <Box>
+              <ItemPreview
+                // @ts-ignore
+                caption={item.object[0].caption}
+                title={item.text}
+                name={parseArtists(item)}
+                image={parseImage(item)}
+                itemId={item.xml_id}
+                inventoryLabel={item.inventory.label}
+                navigation={navigation}
+              />
+            </Box> */}
+      </>
+
 
-      {/* <ItemPreview
-          // @ts-ignore
-          caption={item.object[0].caption}
-          title={item.text}
-          name={parseArtists(item)}
-          image={parseImage(item)}
-          itemId={item.xml_id}
-          inventoryLabel={props.inventoryLabel}
-          navigation={props.navigation}
-      /> */}
     </Box >
 
 
diff --git a/src/stores/actions/planThunks.ts b/src/stores/actions/planThunks.ts
index 5a50caa..b5cd13a 100644
--- a/src/stores/actions/planThunks.ts
+++ b/src/stores/actions/planThunks.ts
@@ -1,8 +1,10 @@
 import { createAsyncThunk } from "@reduxjs/toolkit"
 import { SortOptions } from "../../types/general";
 import { Note } from "../../types/note";
-import { getPlanAllRequest } from "../../api/planservice";
-import { Floor, Room } from "../../types/plan";
+import { getPlanAllRequest, getPlanItemsRequest } from "../../api/planservice";
+import { Floor, InventoryTab, Room } from "../../types/plan";
+import { ItemPreviewType } from "../../types/listViewTypes";
+import { StringLiteralType } from "typescript";
 
 export const getFloorList = createAsyncThunk(
     "plan/getFloorList",
@@ -33,7 +35,7 @@ export const getFloorList = createAsyncThunk(
                     let floorList = []
 
                     for (let key in floorsDict) {
-                        let floor : Floor = floorsDict[key]
+                        let floor: Floor = floorsDict[key]
                         floorList.push(floor)
                     }
 
@@ -45,6 +47,78 @@ export const getFloorList = createAsyncThunk(
                 return Promise.reject(err.response.data)
             }
 
+        } catch (err: any) {
+            console.log(err);
+            return Promise.reject(err.response.data)
+        }
+    }
+)
+
+
+export const getPlanInventories = createAsyncThunk(
+    "plan/getPlanInventories",
+    async (params: { room: number, place?: number }) => {
+        try {
+            try {
+                const response = await getPlanItemsRequest({ activeTab: 0, page: 1, room: params.room, items: 1, place: params.place })
+                if (response.status === 200) {
+
+                    let inventories: InventoryTab[] = []
+
+                    for(let i = 0; i < response.data.pagination.inventories; i++){
+                        let inventory = response.data.pagination.inventories[i]
+                        
+                        inventories.push({
+                            tab: i,
+                            label: inventory.label,
+                            key: inventory.name
+                        })
+                    }
+
+                    let allInventoriesRecords = response.data.pagination.records
+
+                    console.log(inventories)
+                    console.log(allInventoriesRecords)
+
+                    return {
+                        inventories: inventories,
+                        allInventoriesRecords : allInventoriesRecords
+                    }
+                } else {
+                    return Promise.reject(response.data ? response.data : "Get plan items request failed")
+                }
+            } catch (err: any) {
+                return Promise.reject(err.response.data)
+            }
+
+        } catch (err: any) {
+            console.log(err);
+            return Promise.reject(err.response.data)
+        }
+    })
+
+export const getPlanItems = createAsyncThunk(
+    "plan/getPlanItems",
+    async (params: { activeTab: number, page: number, room: number, items: number, place?: number, inventory?: string }) => {
+        try {
+            try {
+                const response = await getPlanItemsRequest({ activeTab: params.activeTab, page: params.page, room: params.room, items: params.items, place: params.place, inventory: params.inventory })
+                if (response.status === 200) {
+
+                    let items: ItemPreviewType[] = response.data.data
+                    let totalItemsCountByInventory: number = response.data.pagination.records
+
+                    return {
+                        items: items,
+                        totalItemsCount: totalItemsCountByInventory,
+                    }
+                } else {
+                    return Promise.reject(response.data ? response.data : "Get plan items 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 ee9f6b2..001abdf 100644
--- a/src/stores/reducers/planSlice.ts
+++ b/src/stores/reducers/planSlice.ts
@@ -1,12 +1,11 @@
 import { PayloadAction, createSlice } from "@reduxjs/toolkit"
 import { PlanViewState } from "../../types/plan";
-import { getFloorList } from "../actions/planThunks";
+import { getFloorList, getPlanInventories, getPlanItems } from "../actions/planThunks";
 
 const initialState: PlanViewState = {
     lastError: "",
 
 
-
     // TODO backend -> retrieve list of floors, not static -> not implemented at the time of coding
     floorList: [
         { label: "Ground floor", id: "ground_floor", roomList: [] },
@@ -15,8 +14,9 @@ const initialState: PlanViewState = {
     ],
     floorListLoading: false,
 
-    itemList: [],
+    itemInventories: [],
 
+    itemList: [],
 }
 
 export const planSlice = createSlice({
@@ -25,6 +25,7 @@ export const planSlice = createSlice({
     reducers: {},
     extraReducers: (builder) => {
 
+        // getFloorList
         builder.addCase(getFloorList.fulfilled, (state, action) => {
 
             state.floorList = action.payload
@@ -37,6 +38,34 @@ export const planSlice = createSlice({
             state.floorListLoading = false;
             state.lastError = action.error.message
         })
+
+        // getPlanItems
+        builder.addCase(getPlanItems.fulfilled, (state, action) => {
+            state.itemList = action.payload.items
+            state.itemListLoading = false;
+        })
+        builder.addCase(getPlanItems.pending, (state, action) => {
+            state.itemListLoading = true;
+        })
+        builder.addCase(getPlanItems.rejected, (state, action) => {
+            state.itemListLoading = false;
+            state.lastError = action.error.message
+        })
+
+        
+        // getPlanInventories
+        builder.addCase(getPlanInventories.fulfilled, (state, action) => {
+            state.itemInventories = action.payload.inventories
+            state.totalItemsCount = action.payload.allInventoriesRecords
+            state.itemInventoriesLoading = false;
+        })
+        builder.addCase(getPlanInventories.pending, (state, action) => {
+            state.itemInventoriesLoading = true;
+        })
+        builder.addCase(getPlanInventories.rejected, (state, action) => {
+            state.itemInventoriesLoading = false;
+            state.lastError = action.error.message
+        })
     }
 })
 
diff --git a/src/types/plan.ts b/src/types/plan.ts
index 21612c5..a518fa9 100644
--- a/src/types/plan.ts
+++ b/src/types/plan.ts
@@ -1,3 +1,4 @@
+import { ItemPreviewType } from "./listViewTypes"
 
 
 export type Floor = {
@@ -8,7 +9,7 @@ export type Floor = {
 }
 
 export type Room = {
-    id : number
+    id: number
 
     kx: number
     ky: number
@@ -20,7 +21,7 @@ export type Room = {
     in_plan: true
     svg_path: string
     room_list: boolean
-    
+
     places: Place[]
 
     number_x: number
@@ -33,16 +34,26 @@ export type Place = {
 }
 
 
+export type InventoryTab = { tab: number, key: string, label: string }
+
+
 export type PlanViewState = {
-    planLoading?: boolean
-    plan?: any
 
+    // floorList
     floorListLoading?: boolean
     floorList: Floor[]
 
-    
-    itemListLoading?: boolean
-    itemList: { label: string, id: string }[]
+
+    // items
+    itemInventories: InventoryTab[],
+    itemInventoriesLoading?: boolean,
+
+    itemListLoading?: boolean,
+    itemList: ItemPreviewType[]
+    totalItemsCount?: number
+
+    // plan
+    // @TODO
 
     lastError?: string
 }
\ No newline at end of file
