commit 8ff3394e05bb13e001c38cc3da63ce9319f004a2
Author: Fantič <58391275+FantaFantic@users.noreply.github.com>
Date:   Wed Oct 18 19:12:36 2023 +0200

    re #10819 ItemView next, previous item list switching

diff --git a/src/components/item/ItemTabBar.tsx b/src/components/item/ItemTabBar.tsx
index a8f7c18..6565eec 100644
--- a/src/components/item/ItemTabBar.tsx
+++ b/src/components/item/ItemTabBar.tsx
@@ -1,12 +1,17 @@
-import { HStack, CircleIcon, View, ScrollView, Button, Center, Heading, Pressable, Text, Box, Container, VStack, Icon, ArrowBackIcon, ChevronLeftIcon, ChevronRightIcon } from "native-base";
+import { HStack, CircleIcon, View, ScrollView, Button, Center, Heading, Pressable, Text, Box, Container, VStack, Icon, ArrowBackIcon, ChevronLeftIcon, ChevronRightIcon, useToast } from "native-base";
 import { CertaintyWithColors } from "../../stores/reducers/itemSlice";
 import { Certainty, Concordance } from "../../types/item";
 import LoadingBox from "../loading/LoadingBox";
+import { DrawerNavigationProp } from "@react-navigation/drawer";
+import { RootDrawerParamList } from "../../pages/Navigation";
+import { InfoToast } from "../toast/InfoToast";
 
 // custom render Tab
-const ItemTabBar = (props: { navigationState: { routes: any[] }, concordances: Concordance[], index: number, onIndexChange: any, onBackPressed: any }) => {
+const ItemTabBar = (props: { navigationState: { routes: any[] }, concordances: Concordance[], index: number, onIndexChange: any, onBackPressed: any, navigation: DrawerNavigationProp<RootDrawerParamList, "Item", undefined>, nextItem?: string | boolean, prevItem?:string | boolean }) => {
 
-    const { concordances, onIndexChange, index, onBackPressed } = props
+    const { concordances, onIndexChange, index, onBackPressed, nextItem, prevItem } = props
+
+    const toast = useToast();
 
     if (concordances && concordances.length > 0) {
         return (
@@ -25,11 +30,41 @@ const ItemTabBar = (props: { navigationState: { routes: any[] }, concordances: C
                         </HStack>
                         <HStack marginRight={0}>
                             <Button variant="ghost" size="lg"
-                                onPress={() => onIndexChange(index - 1)}
+                                onPress={() => {
+                                    if(prevItem){
+                                        console.log(prevItem)
+                                        props.navigation.navigate("Item", { itemId: prevItem.toString() })
+                                    }
+                                    else{
+                                        toast.show({
+                                            render: ({
+                                                id
+                                            }) => {
+                                                return <InfoToast text={"No previous item..."} onClose={() => toast.close(id)} />;
+                                            },
+                                            duration: 3000
+                                        });
+                                    }
+                                }}
                                 leftIcon={<ChevronLeftIcon size="lg" />}>
                             </Button>
                             <Button variant="ghost" size="lg"
-                                onPress={() => onIndexChange(index + 1)}
+                                onPress={() => {
+                                    
+                                    if(nextItem){
+                                        props.navigation.navigate("Item", { itemId: nextItem.toString() })
+                                    }
+                                    else{
+                                        toast.show({
+                                            render: ({
+                                                id
+                                            }) => {
+                                                return <InfoToast text={"No next item..."} onClose={() => toast.close(id)} />;
+                                            },
+                                            duration: 3000
+                                        });
+                                    }
+                                }}
                                 leftIcon={<ChevronRightIcon size="lg" />}>
                             </Button>
                         </HStack>
@@ -46,10 +81,10 @@ const ItemTabBar = (props: { navigationState: { routes: any[] }, concordances: C
                                                 <CircleIcon
                                                     marginLeft="5"
                                                     size="2"
-                                                    color={CertaintyWithColors[concordances[i].cert ?? Certainty.Unknown].color}
+                                                    color={CertaintyWithColors[concordances[i]?.cert ?? Certainty.Unknown].color}
                                                 />
                                                 <Text marginLeft="5%">
-                                                    {i == index ? <Text bold>{concordances[i].id}</Text> : concordances[i].id}
+                                                    {i == index ? <Text bold>{concordances[i]?.id}</Text> : concordances[i]?.id}
 
                                                 </Text>
                                             </HStack>
@@ -64,10 +99,10 @@ const ItemTabBar = (props: { navigationState: { routes: any[] }, concordances: C
                                                 <CircleIcon
                                                     marginLeft="42%"
                                                     size="2"
-                                                    color={CertaintyWithColors[concordances[0].cert ?? Certainty.Unknown].color}
+                                                    color={CertaintyWithColors[concordances[0]?.cert ?? Certainty.Unknown].color}
                                                 />
                                                 <Text marginLeft="2%">
-                                                    <Text bold>{concordances[0].id}</Text>
+                                                    <Text bold>{concordances[0]?.id}</Text>
                                                 </Text>
                                             </HStack>
                                         </Pressable>
diff --git a/src/components/item/ItemView.tsx b/src/components/item/ItemView.tsx
index ae2b220..a1d2181 100644
--- a/src/components/item/ItemView.tsx
+++ b/src/components/item/ItemView.tsx
@@ -12,13 +12,15 @@ import { useDispatch, useSelector } from "react-redux"
 import { getItemNotes } from "../../stores/actions/itemThunks"
 
 import { Dimensions } from "react-native";
+import { DrawerNavigationProp } from "@react-navigation/drawer"
+import { RootDrawerParamList } from "../../pages/Navigation"
 
 interface ItemDetailProps {
     item: Item,
     itemLoading: boolean,
     notes: Note[],
     notesLoading: boolean,
-    navigation: any
+    navigation: DrawerNavigationProp<RootDrawerParamList, "Item", undefined>
 }
 
 const ItemDetail = (props: { item: Item, itemLoading: boolean }) => {
@@ -26,8 +28,6 @@ const ItemDetail = (props: { item: Item, itemLoading: boolean }) => {
 
     const [selectedImage, setSelectedImage] = useState<number>(0);
 
-    console.log("rerender")
-
     return (<>
         {
             item && props.itemLoading ?
@@ -137,7 +137,7 @@ const ItemDetail = (props: { item: Item, itemLoading: boolean }) => {
 
 
 
-const ItemNotes = (props: { item: Item, notes: Note[], notesLoading: boolean, navigation: any }) => {
+const ItemNotes = (props: { item: Item, notes: Note[], notesLoading: boolean, navigation: DrawerNavigationProp<RootDrawerParamList, "Item", undefined> }) => {
 
     const [showRelatedComments, setShowRelatedComments] = useState(true);
 
@@ -152,8 +152,8 @@ const ItemNotes = (props: { item: Item, notes: Note[], notesLoading: boolean, na
             dispatch(getItemNotes({ item: props.item, relatedComments: showRelatedComments }));
         }
     }, [triggerRefresh])
-
-    const toggleRelatedComments = () => {
+    
+    const toggleRelatedComments = useCallback(() => {
         if (!props.notesLoading) {
 
             let value = !showRelatedComments;
@@ -161,7 +161,8 @@ const ItemNotes = (props: { item: Item, notes: Note[], notesLoading: boolean, na
             setShowRelatedComments(value);
             dispatch(getItemNotes({ item: props.item, relatedComments: value }));
         }
-    }
+      }, [showRelatedComments]);
+
 
     const handleCreateItemComment = useCallback(
         (newComment: string, replyingTo: { messageId: string; userName: string } | null) => {
diff --git a/src/pages/ItemViewPage.tsx b/src/pages/ItemViewPage.tsx
index ebf47ad..c9931cb 100644
--- a/src/pages/ItemViewPage.tsx
+++ b/src/pages/ItemViewPage.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect } from "react"
+import React, { useCallback, useEffect } from "react"
 import { useDispatch, useSelector } from "react-redux"
 import { AppDispatch, RootState } from "../stores/store"
 import { getItem, getItemNotes, setConcordances } from "../stores/actions/itemThunks"
@@ -15,11 +15,11 @@ import { useToast } from "native-base"
 import { ErrorToast } from "../components/toast/ErrorToast"
 
 
-const ItemViewPage = ({route, navigation}: DrawerScreenProps<RootDrawerParamList, 'Item'>) => {
+const ItemViewPage = ({ route, navigation }: DrawerScreenProps<RootDrawerParamList, 'Item'>) => {
 
   const layout = useWindowDimensions();
 
-  const [routes, setRoutes] = React.useState<{key: string, title: string}[]>([
+  const [routes, setRoutes] = React.useState<{ key: string, title: string }[]>([
     // initial tab
     { key: 'loading', title: 'Loading item...' },
   ]);
@@ -36,18 +36,19 @@ const ItemViewPage = ({route, navigation}: DrawerScreenProps<RootDrawerParamList
   const lastError = useSelector((state: RootState) => state.itemViewState.lastError)
   const toast = useToast();
 
+
   useEffect(() => {
-      if (lastError) {
-          toast.closeAll()
-          toast.show({
-              render: ({
-                  id
-              }) => {
-                  return <ErrorToast headerText={"Error"} text={lastError} onClose={() => toast.close(id)} />;
-              },
-              duration: 3000
-          });
-      }
+    if (lastError) {
+      toast.closeAll()
+      toast.show({
+        render: ({
+          id
+        }) => {
+          return <ErrorToast headerText={"Error"} text={lastError} onClose={() => toast.close(id)} />;
+        },
+        duration: 3000
+      });
+    }
   }, [lastError])
 
   // initial: load main item
@@ -89,20 +90,21 @@ const ItemViewPage = ({route, navigation}: DrawerScreenProps<RootDrawerParamList
       }
       // set item notes if item is loaded
       if (item && item.id) {
-        dispatch(getItemNotes({item: item, relatedComments: true}));
+        dispatch(getItemNotes({ item: item, relatedComments: true }));
       }
     }
   }, [item]);
 
-  const handleIndexChanged = (newIndex: number) => {
-    if(newIndex >= 0 && newIndex < concordances.length && index != newIndex){
+
+  const handleIndexChanged = useCallback((newIndex: number) => {
+    if (newIndex >= 0 && newIndex < concordances.length && index != newIndex) {
       console.log("index changed");
       setIndex(newIndex);
       if (concordances && concordances.length > 0) {
         dispatch(getItem(concordances[newIndex].id ?? ""));
       }
     }
-  }
+  }, [concordances, index]);
 
   const onBackPressed = () => {
     log.debug("back pressed")
@@ -111,7 +113,7 @@ const ItemViewPage = ({route, navigation}: DrawerScreenProps<RootDrawerParamList
 
   return (
     !concordances || concordances.length < 1 ?
-      <LoadingBox text={`Loading item ${route.params.itemId}...`}/>
+      <LoadingBox text={`Loading item ${route.params.itemId}...`} />
       :
       <TabView
         renderTabBar={() => ItemTabBar({
@@ -122,10 +124,13 @@ const ItemViewPage = ({route, navigation}: DrawerScreenProps<RootDrawerParamList
           index: index,
           onIndexChange: handleIndexChanged,
           onBackPressed: onBackPressed,
+          navigation: navigation,
+          prevItem: item.prevItem,
+          nextItem: item.nextItem,
         })}
 
         navigationState={{ index, routes }}
-        renderScene={() => <ItemView item={item} notes={notes} itemLoading={itemLoading} notesLoading={notesLoading} navigation={navigation}/>}
+        renderScene={() => <ItemView item={item} notes={notes} itemLoading={itemLoading} notesLoading={notesLoading} navigation={navigation} />}
 
         initialLayout={{ width: layout.width }}
         onIndexChange={handleIndexChanged}
diff --git a/src/stores/actions/itemThunks.ts b/src/stores/actions/itemThunks.ts
index 7a41e57..6361577 100644
--- a/src/stores/actions/itemThunks.ts
+++ b/src/stores/actions/itemThunks.ts
@@ -42,6 +42,8 @@ export const getItem = createAsyncThunk(
                     workName: response.data.object[0]?.caption ?? undefined,
                     inventoryItem: response.data.text ?? undefined,
                     searchSubjects: response.data.search_subject ?? undefined,
+                    prevItem: response.data.prevItem ?? undefined,
+                    nextItem: response.data.nextItem ?? undefined,
                     authorName,
                     images,
                     institution,
@@ -61,6 +63,8 @@ export const getItem = createAsyncThunk(
                         [{ id: itemId, cert: response.data?.object[1]?.cert ?? Certainty.Unknown }],
                     authorDisplayName: response.data.object[0]?.name?.[0]?.getty_data?.display_name ?? undefined,
                     workName: response.data.object[0]?.caption ?? undefined,
+                    prevItem: response.data.prevItem ?? undefined,
+                    nextItem: response.data.nextItem ?? undefined,
                     inventoryItem: response.data.text ?? undefined,
                     searchSubjects: response.data.search_subject ?? undefined,
                 }
diff --git a/src/stores/reducers/itemSlice.ts b/src/stores/reducers/itemSlice.ts
index 9d5c80e..a3500fb 100644
--- a/src/stores/reducers/itemSlice.ts
+++ b/src/stores/reducers/itemSlice.ts
@@ -39,6 +39,8 @@ export const itemSlice = createSlice({
                 concordances : action.payload.concordances,
                 searchSubjects : action.payload.searchSubjects,
                 inventoryItem : action.payload.inventoryItem,
+                prevItem: action.payload.prevItem,
+                nextItem: action.payload.nextItem,
                 fullView : action.payload.fullView,
             }
 
diff --git a/src/types/item.ts b/src/types/item.ts
index 98f0a62..8cc2a0c 100644
--- a/src/types/item.ts
+++ b/src/types/item.ts
@@ -25,6 +25,9 @@ export type  Item = {
     repository?: string
     provenance?: string
     description?: string
+
+    prevItem?: string | boolean
+    nextItem?: string | boolean
 }
 
 export type ItemViewState = {
