commit 2135f53d27abf91d44f6cdb387f204fbb534d9e7
Author: Fantič <58391275+FantaFantic@users.noreply.github.com>
Date:   Thu May 25 22:00:53 2023 +0200

    re #10678: ItemNotes refactor NoteListView

diff --git a/src/components/item/ItemView.tsx b/src/components/item/ItemView.tsx
index b740686..40096b2 100644
--- a/src/components/item/ItemView.tsx
+++ b/src/components/item/ItemView.tsx
@@ -6,9 +6,9 @@ import LoadingBox from "../loading/LoadingBox"
 import NotesListView from "../notes/NotesListView"
 import { IMAGE_URL } from "../../api/constants"
 import { log } from "../../logging/logger"
-import { getAllNotes } from "../../stores/actions/notesThunks"
-import { AppDispatch } from "../../stores/store"
-import { useDispatch } from "react-redux"
+import { createNote, getAllNotes } from "../../stores/actions/notesThunks"
+import { AppDispatch, RootState } from "../../stores/store"
+import { useDispatch, useSelector } from "react-redux"
 import { getItemNotes } from "../../stores/actions/itemThunks"
 
 interface ItemDetailProps {
@@ -24,93 +24,94 @@ const ItemDetail = (props: { item: Item, itemLoading: boolean }) => {
 
     return (<>
         {
-
             item && props.itemLoading ?
                 (<LoadingBox text="Item loading..." />)
                 :
                 (
-                    <VStack>
-                        <HStack marginTop="5%">
-                            <VStack width="75%">
-                                <Text>
-                                    {item.authorDisplayName ? item.authorDisplayName : item.authorName}
-                                </Text>
-                                <Heading size="sm">
-                                    {item.workName}
-                                </Heading>
-
-                            </VStack>
-                            <Box width="25%">
-                                <Button variant="outline" size="md">
-                                    {item.concordances[0].id}
-                                </Button>
-                            </Box>
-                        </HStack>
-                        <Card shadow="1" marginTop="5%">
-                            {item.inventoryItem &&
-                                <VStack>
-                                    <Text italic>
-                                        <Text color="light.500">Inventory item: </Text>
-                                        {item.inventoryItem}
-                                    </Text>
-                                    <Text italic marginTop="2.5%">
-                                        {item.searchSubjects.map((subject, index) => (
-                                            index < item.searchSubjects.length - 1 ? (subject + ", ") : (subject)
-                                        ))}
+                    <ScrollView flex="1">
+                        <VStack>
+                            <HStack marginTop="5%">
+                                <VStack width="75%">
+                                    <Text>
+                                        {item.authorDisplayName ? item.authorDisplayName : item.authorName}
                                     </Text>
-                                </VStack>}
-                        </Card>
-                        {item.fullView && item.imageUrl && (
-                            <Center background="primary.100" marginTop="5%">
-                                <Text>Resembling object</Text>
-                                <Image size={250} alt="image" source={{ uri: IMAGE_URL + "/" + item.imageUrl }} />
-                            </Center>)}
-                        {item.fullView && (
-                            <Card shadow="1" marginTop="5%" marginBottom="5%">
-                                {item.authorName &&
-                                    <HStack>
-                                        <Text italic marginTop="2.5%">
-                                            <Text color="light.500">Author name: </Text>
-                                            {item.authorName}
-                                        </Text>
-                                    </HStack>}
-                                {item.title &&
-                                    <HStack>
-                                        <Text italic marginTop="2.5%">
-                                            <Text color="light.500">Title: </Text>
-                                            {item.title}
+                                    <Heading size="sm">
+                                        {item.workName}
+                                    </Heading>
+
+                                </VStack>
+                                <Box width="25%">
+                                    <Button variant="outline" size="md">
+                                        {item.concordances[0].id}
+                                    </Button>
+                                </Box>
+                            </HStack>
+                            <Card shadow="1" marginTop="5%">
+                                {item.inventoryItem &&
+                                    <VStack>
+                                        <Text italic>
+                                            <Text color="light.500">Inventory item: </Text>
+                                            {item.inventoryItem}
                                         </Text>
-                                    </HStack>}
-                                {item.institution &&
-                                    <HStack>
                                         <Text italic marginTop="2.5%">
-                                            <Text color="light.500">Institution: </Text>
-                                            {item.institution.name}, Inv. No. {item.institution.inventoryNumber}, {item.institution.city} {"(" + item.institution.country + ")"}
+                                            {item.searchSubjects.map((subject, index) => (
+                                                index < item.searchSubjects.length - 1 ? (subject + ", ") : (subject)
+                                            ))}
                                         </Text>
-                                    </HStack>}
-                                {item.repository &&
-                                    <HStack>
-                                        <Text italic marginTop="2.5%">
-                                            <Text color="light.500">Repository: </Text>
-                                            {item.repository}
-                                        </Text>
-                                    </HStack>}
-                                {item.provenance &&
-                                    <HStack>
-                                        <Text italic marginTop="2.5%">
-                                            <Text color="light.500">Provenance: </Text>
-                                            {item.provenance}
-                                        </Text>
-                                    </HStack>}
-                                {item.description &&
-                                    <HStack>
-                                        <Text italic marginTop="2.5%">
-                                            <Text color="light.500">Description: </Text>
-                                            {item.description}
-                                        </Text>
-                                    </HStack>}
-                            </Card>)}
-                    </VStack>
+                                    </VStack>}
+                            </Card>
+                            {item.fullView && item.imageUrl && (
+                                <Center background="primary.100" marginTop="5%">
+                                    <Text>Resembling object</Text>
+                                    <Image size={250} alt="image" source={{ uri: IMAGE_URL + "/" + item.imageUrl }} />
+                                </Center>)}
+                            {item.fullView && (
+                                <Card shadow="1" marginTop="5%" marginBottom="5%">
+                                    {item.authorName &&
+                                        <HStack>
+                                            <Text italic marginTop="2.5%">
+                                                <Text color="light.500">Author name: </Text>
+                                                {item.authorName}
+                                            </Text>
+                                        </HStack>}
+                                    {item.title &&
+                                        <HStack>
+                                            <Text italic marginTop="2.5%">
+                                                <Text color="light.500">Title: </Text>
+                                                {item.title}
+                                            </Text>
+                                        </HStack>}
+                                    {item.institution &&
+                                        <HStack>
+                                            <Text italic marginTop="2.5%">
+                                                <Text color="light.500">Institution: </Text>
+                                                {item.institution.name}, Inv. No. {item.institution.inventoryNumber}, {item.institution.city} {"(" + item.institution.country + ")"}
+                                            </Text>
+                                        </HStack>}
+                                    {item.repository &&
+                                        <HStack>
+                                            <Text italic marginTop="2.5%">
+                                                <Text color="light.500">Repository: </Text>
+                                                {item.repository}
+                                            </Text>
+                                        </HStack>}
+                                    {item.provenance &&
+                                        <HStack>
+                                            <Text italic marginTop="2.5%">
+                                                <Text color="light.500">Provenance: </Text>
+                                                {item.provenance}
+                                            </Text>
+                                        </HStack>}
+                                    {item.description &&
+                                        <HStack>
+                                            <Text italic marginTop="2.5%">
+                                                <Text color="light.500">Description: </Text>
+                                                {item.description}
+                                            </Text>
+                                        </HStack>}
+                                </Card>)}
+                        </VStack>
+                    </ScrollView>
                 )
         }</>
     );
@@ -122,6 +123,8 @@ const ItemNotes = (props: { item: Item, notes: Note[], notesLoading: boolean, na
 
     const [showRelatedComments, setShowRelatedComments] = useState(true);
 
+    const { requestPending } = useSelector((state: RootState) => state.noteViewState)
+
     const dispatch = useDispatch<AppDispatch>();
 
     const toggleRelatedComments = () => {
@@ -134,17 +137,35 @@ const ItemNotes = (props: { item: Item, notes: Note[], notesLoading: boolean, na
         }
     }
 
+    const handleCreateItemComment = (newComment: string, replyingTo: { messageId: string; userName: string } | null) => {
+        if (!requestPending) {
+            // creating new comment
+            if (replyingTo != null) {
+                dispatch(createNote({
+                    newNote: { note: newComment, reply_to: replyingTo.messageId } as Note
+                }))
+            }
+            else {
+                dispatch(createNote({
+                    newNote: { note: newComment, items: [props.item.id] } as Note
+                }))
+            }
+        }
+    }
+
     return (
 
         props.notesLoading ?
             (<LoadingBox text="Notes loading..." />)
             :
-            (<VStack>
+            (<VStack height="90%">
                 <Flex direction="row" alignItems="center" justify="flex-end">
                     <Text fontSize={"12"}>Show related comments</Text>
                     <Switch value={showRelatedComments} onChange={toggleRelatedComments} size="md" />
                 </Flex>
-                <NotesListView notes={props.notes} handleDelete={() => console.log("TODO handle delete")} handleEdit={() => console.log("TODO handle edit")} handleReply={() => console.log("TODO handle reply")} setConfirmDialog={() => { }} navigation={props.navigation} />
+                <Box height="120%">
+                    <NotesListView requestPending={requestPending} notes={props.notes} navigation={props.navigation} handleCreateComment={handleCreateItemComment} />
+                </Box>
             </VStack>)
     );
 }
@@ -168,15 +189,15 @@ const ItemView = (props: ItemDetailProps) => {
 
     return (
         <Box display="flex" flex={1} flexDirection="column" justifyContent="space-between">
-            <ScrollView flex="1">
-                <Box width="92%" marginLeft="5%">
-                    {itemShown ? (
-                        <ItemDetail itemLoading={itemLoading} item={props.item} />
-                    ) : (
-                        <ItemNotes item={props.item} notesLoading={props.notesLoading} notes={props.notes} navigation={props.navigation} />
-                    )}
-                </Box>
-            </ScrollView>
+
+            <Box width="92%" marginLeft="5%" height="92%">
+                {itemShown ? (
+                    <ItemDetail itemLoading={itemLoading} item={props.item} />
+                ) : (
+                    <ItemNotes item={props.item} notesLoading={props.notesLoading} notes={props.notes} navigation={props.navigation} />
+                )}
+            </Box>
+
 
 
             {/* item notes switch tab */}
diff --git a/src/components/notes/NotesListView.tsx b/src/components/notes/NotesListView.tsx
index 4ca98f7..f74e355 100644
--- a/src/components/notes/NotesListView.tsx
+++ b/src/components/notes/NotesListView.tsx
@@ -1,23 +1,87 @@
-import { Center, VStack, Box, Text, HStack, ScrollView } from "native-base";
+import { VStack, Box, Text, HStack, ScrollView, Flex, Button, CloseIcon, IconButton, TextArea } from "native-base";
 import { Note } from "../../types/note";
 import NoteView from "./NoteView";
+import { MessageIcon } from "../general/Icons";
+import React, { useState } from "react";
+import { updateNote, deleteNote } from "../../stores/actions/notesThunks";
+import { ConfirmDialog } from "../general/Dialogs";
+import { AppDispatch } from "../../stores/store";
+import { useDispatch } from "react-redux";
 
-const NotesListView = (props: { notes: Note[], handleReply : any, handleDelete : any, handleEdit : any, setConfirmDialog: any, navigation: any}) => {
+const NotesListView = (props: { notes: Note[], navigation: any, handleCreateComment: any, requestPending: boolean }) => {
     const notes = props.notes;
+
+    const [newComment, setNewComment] = useState<string>("");
+    const [replyingTo, setReplyingTo] = useState<{ messageId: string; userName: string } | null>(null);
+
+    const cancelRef = React.useRef(null);
+
+    const dispatch = useDispatch<AppDispatch>();
+
+    const [confirmDialog, setConfirmDialog] = React.useState<{
+        headerText?: string;
+        bodyText?: string;
+        confirmText?: string;
+        confirmColor?: string;
+        cancelRef?: any;
+        onClose?: () => void;
+        onSubmit?: () => void;
+    } | null>(null);
+
+    const handleReply = (messageId: string, userName: string) => {
+        setReplyingTo({ messageId, userName })
+    }
+
+    const handleEdit = (note: Note) => {
+        if (!props.requestPending)
+            dispatch(updateNote(note));
+    }
+
+    const handleDelete = (messageId: string) => {
+        if (!props.requestPending)
+            dispatch(deleteNote({ noteId: messageId }))
+    }
+
     return (
-        <ScrollView>
+        <VStack>
+            <Box h={props.handleCreateComment == null ? "88%" : (replyingTo != null ? "65%" : "70%")}>
+                <ScrollView contentContainerStyle={{ flexGrow: 1 }}>
+                    {
+                        notes && notes.length > 0 ? (
+                            <VStack>
+                                {notes.map((note, index) => (
+                                    <NoteView key={index} note={note} handleReply={handleReply} handleDelete={handleDelete} handleEdit={handleEdit} setConfirmDialog={setConfirmDialog} navigation={props.navigation} />
+                                ))}
+                            </VStack>
+                        ) : (
+                            <Text>There are no notes.</Text>
+                        )
+                    }
+                </ScrollView>
+            </Box>
+            {
+                props.handleCreateComment != null && replyingTo != null &&
+                <Flex direction="row" alignItems="center" justify="flex-end" h="5%" marginRight="10%">
+                    <Text>Replying to {replyingTo.userName}</Text>
+                    <IconButton onPress={() => setReplyingTo(null)} size="sm" icon={<CloseIcon />} marginLeft="-1%">
+                    </IconButton>
+                </Flex>
+            }
+
             {
-                notes && notes.length > 0 ? (
+                props.handleCreateComment != null &&
+                <HStack h={replyingTo != null ? "20%" : "15%"} marginTop={replyingTo != null ? "0%" : "6%"}>
+                    <TextArea placeholder="Add comment" width="90%" fontSize={14} value={newComment} onChangeText={setNewComment} autoCompleteType={undefined} ></TextArea>
                     <VStack>
-                        {notes.map((note, index) => (
-                            <NoteView key={index} note={note} handleReply={props.handleReply} handleDelete={props.handleDelete} handleEdit={props.handleEdit} setConfirmDialog={props.setConfirmDialog} navigation={props.navigation}/>
-                        ))}
+                        <Box h={replyingTo != null ? "30%" : "45%"}></Box>
+                        <Box marginLeft="2">
+                            <Button onPress={() => props.handleCreateComment(newComment , replyingTo)} startIcon={<MessageIcon color="#FFF" />}></Button>
+                        </Box>
                     </VStack>
-                ) : (
-                    <Text>There are no notes.</Text>
-                )
+                </HStack>
             }
-        </ScrollView>
+            <ConfirmDialog {...confirmDialog} isShown={confirmDialog != null} cancelRef={cancelRef} />
+        </VStack>
     );
 }
 
diff --git a/src/pages/NotesViewPage.tsx b/src/pages/NotesViewPage.tsx
index 56308e6..89c7ad3 100644
--- a/src/pages/NotesViewPage.tsx
+++ b/src/pages/NotesViewPage.tsx
@@ -1,46 +1,26 @@
 import React, { useEffect, useState } from "react"
 import { log } from "../logging/logger"
 import { DrawerScreenProps } from "@react-navigation/drawer"
-import { Box, Button, ChevronDownIcon, ChevronUpIcon, CloseIcon, Flex, HStack, Icon, IconButton, MinusIcon, Popover, Pressable, ScrollView, Switch, Text, TextArea, VStack } from "native-base"
+import { Box, Button, ChevronDownIcon, ChevronUpIcon, Flex, HStack, MinusIcon, Popover, Switch, Text, VStack } from "native-base"
 import { SortOptions } from "../types/general"
 import { Note } from "../types/note"
 import NotesListView from "../components/notes/NotesListView"
-import { G, Path } from "react-native-svg"
-import { MessageIcon } from "../components/general/Icons"
-import { ConfirmDialog } from "../components/general/Dialogs"
 import { useDispatch, useSelector } from "react-redux"
 import { AppDispatch, RootState } from "../stores/store"
 import LoadingBox from "../components/loading/LoadingBox"
-import { createNote, deleteNote, getAllNotes, updateNote } from "../stores/actions/notesThunks"
-import { login } from "../stores/actions/userThunks"
+import { createNote, getAllNotes } from "../stores/actions/notesThunks"
 import { RootDrawerParamList } from "./Navigation"
-const NotesViewPage = ({ route, navigation }: DrawerScreenProps<RootDrawerParamList, 'Notes'>) => {
+const NotesViewPage = ({ navigation }: DrawerScreenProps<RootDrawerParamList, 'Notes'>) => {
 
   const { notes, notesLoading, requestPending, triggerRefresh } = useSelector((state: RootState) => state.noteViewState)
-  
+
   const dispatch = useDispatch<AppDispatch>();
 
   const [isSortOpen, setIsSortOpen] = useState(false);
-  
-  const [newComment, setNewComment] = useState<string>("");
 
   const [myCommentsCheck, setMyCommentsCheck] = useState(false);
   const [generalCommentsCheck, setGeneralCommentsCheck] = useState(true);
 
-  const [replyingTo, setReplyingTo] = useState<{ messageId: string; userName: string } | null>(null);
-
-  const cancelRef = React.useRef(null);
-
-  const [confirmDialog, setConfirmDialog] = React.useState<{
-    headerText?: string;
-    bodyText?: string;
-    confirmText?: string;
-    confirmColor?: string;
-    cancelRef?: any;
-    onClose?: () => void;
-    onSubmit?: () => void;
-  } | null>(null);
-
   const [sortSettings, setSortSettings] = useState({
     items: SortOptions.None,
     date: SortOptions.None
@@ -83,14 +63,11 @@ const NotesViewPage = ({ route, navigation }: DrawerScreenProps<RootDrawerParamL
   useEffect(() => {
     log.debug("NotesViewPage", "useEffect", "getNotes");
     getNotes();
-    
-    setNewComment("");
-    setReplyingTo(null);
   }, [triggerRefresh])
 
   // general comments check changed
   useEffect(() => {
-    if(!notesLoading){
+    if (!notesLoading) {
       log.debug("NotesViewPage", "useEffect", "getNotes");
       getNotes();
     }
@@ -105,36 +82,26 @@ const NotesViewPage = ({ route, navigation }: DrawerScreenProps<RootDrawerParamL
     }));
   }
 
-  const handleReply = (messageId: string, userName: string) => {
-    setReplyingTo({ messageId, userName })
-  }
-
-  const handleEdit = (note : Note) => {
-    if(!requestPending)
-      dispatch(updateNote(note));
-  }
+  const handleCreateComment = (newComment : string, replyingTo : { messageId: string; userName: string } | null) => {
 
-  const handleDelete = (messageId: string) => {
-    if(!requestPending)
-      dispatch(deleteNote({noteId: messageId}))
-  }
+    console.log(newComment, replyingTo)
 
-  const handleCreateComment = () => {
-    if(!requestPending){
+    if (!requestPending) {
       // creating new comment
-      if(replyingTo != null){
-        dispatch(createNote( {
-          newNote: {note: newComment, reply_to: replyingTo.messageId} as Note
+      if (replyingTo != null) {
+        dispatch(createNote({
+          newNote: { note: newComment, reply_to: replyingTo.messageId } as Note
         }))
       }
-      else{
+      else {
         dispatch(createNote({
-          newNote: {note: newComment} as Note
+          newNote: { note: newComment } as Note
         }))
       }
-    } 
+    }
   }
 
+
   return (
     <Box width="92%" marginLeft="5%">
       <VStack>
@@ -177,39 +144,21 @@ const NotesViewPage = ({ route, navigation }: DrawerScreenProps<RootDrawerParamL
           <VStack width="70%" space="0">
             <Flex direction="row" alignItems="center" justify="flex-end">
               <Text>My comments</Text>
-              <Switch isChecked={myCommentsCheck} onValueChange={() => {if(!notesLoading) setMyCommentsCheck(!myCommentsCheck)}} size="md" />
+              <Switch isChecked={myCommentsCheck} onValueChange={() => { if (!notesLoading) setMyCommentsCheck(!myCommentsCheck) }} size="md" />
             </Flex>
             <Flex direction="row" alignItems="center" justify="flex-end" marginTop="-7.5%">
               <Text>General comments</Text>
-              <Switch isChecked={generalCommentsCheck} onValueChange={() => {if(!notesLoading) setGeneralCommentsCheck(!generalCommentsCheck)}} size="md" />
+              <Switch isChecked={generalCommentsCheck} onValueChange={() => { if (!notesLoading) setGeneralCommentsCheck(!generalCommentsCheck) }} size="md" />
             </Flex>
           </VStack>
         </HStack>
-        <Box h={replyingTo != null ? "62.5%" : "67.5%"}>
-          {
-            notesLoading ? (<LoadingBox text="Loading notes"/>)
-              :
-              (<NotesListView notes={notes} handleReply={handleReply} handleDelete={handleDelete} handleEdit={handleEdit} setConfirmDialog={setConfirmDialog} navigation={navigation} />)
-          }
-        </Box>
-        {replyingTo != null &&
-          <Flex direction="row" alignItems="center" justify="flex-end" h="5%" marginRight="10%">
-            <Text>Replying to {replyingTo.userName}</Text>
-            <IconButton onPress={() => setReplyingTo(null)} size="sm" icon={<CloseIcon />} marginLeft="-1%">
-            </IconButton>
-          </Flex>
+        {
+          notesLoading ? (<LoadingBox text="Loading notes" />)
+            :
+            (<NotesListView notes={notes} navigation={navigation} handleCreateComment={handleCreateComment} requestPending={requestPending} />)
         }
-        <HStack h={replyingTo != null ? "20%" : "15%"} marginTop={replyingTo != null ? "0%" : "5%"}>
-          <TextArea placeholder="Add comment" width="90%" fontSize={14} value={newComment} onChangeText={setNewComment} autoCompleteType={undefined} ></TextArea>
-          <VStack>
-            <Box h={replyingTo != null ? "30%" : "45%"}></Box>
-            <Box marginLeft="2">
-              <Button onPress={handleCreateComment} startIcon={<MessageIcon color="#FFF" /> }></Button>
-            </Box>
-          </VStack>
-        </HStack>
+
       </VStack>
-      <ConfirmDialog {...confirmDialog} isShown={confirmDialog != null} cancelRef={cancelRef} />
     </Box>
   );
 }
diff --git a/src/stores/actions/notesThunks.ts b/src/stores/actions/notesThunks.ts
index 8122a36..d0dc094 100644
--- a/src/stores/actions/notesThunks.ts
+++ b/src/stores/actions/notesThunks.ts
@@ -32,7 +32,7 @@ export const createNote = createAsyncThunk(
     "notes/createNote",
     async ({ newNote }: { newNote: Note}) => {
         try {
-
+            console.log(newNote.note);
             const response = await createNoteRequest(newNote);
             console.log(response);
             if (response.status === 201) {
