Projekt

Obecné

Profil

Stáhnout (7.69 KB) Statistiky
| Větev: | Tag: | Revize:
1
import React, { useCallback, useEffect, useState } from "react"
2
import { log } from "../logging/logger"
3
import { DrawerScreenProps } from "@react-navigation/drawer"
4
import { Box, Button, ChevronDownIcon, ChevronUpIcon, Flex, HStack, MinusIcon, Popover, Switch, Text, VStack, useToast } from "native-base"
5
import { SortOptions } from "../types/general"
6
import { Note } from "../types/note"
7
import NotesListView from "../components/notes/NotesListView"
8
import { useDispatch, useSelector } from "react-redux"
9
import { AppDispatch, RootState } from "../stores/store"
10
import LoadingBox from "../components/loading/LoadingBox"
11
import { createNote, getAllNotes } from "../stores/actions/notesThunks"
12
import { RootStackParamList } from "./Navigation"
13
import { ErrorToast } from "../components/toast/ErrorToast"
14
import { InfoToast } from "../components/toast/InfoToast"
15

    
16
import { Dimensions } from "react-native";
17

    
18
const NotesViewPage = ({ navigation }: DrawerScreenProps<RootStackParamList, 'Notes'>) => {
19

    
20
  const { notes, notesLoading, requestPending, triggerRefresh } = useSelector((state: RootState) => state.noteViewState);
21

    
22
  const dispatch = useDispatch<AppDispatch>();
23

    
24
  const [isSortOpen, setIsSortOpen] = useState(false);
25

    
26
  const [myCommentsCheck, setMyCommentsCheck] = useState(false);
27
  const [generalCommentsCheck, setGeneralCommentsCheck] = useState(true);
28

    
29
  const lastError = useSelector((state: RootState) => state.noteViewState.lastError)
30
  const toast = useToast();
31

    
32
  useEffect(() => {
33
    if (lastError) {
34
      toast.closeAll()
35
      toast.show({
36
        render: ({
37
          id
38
        }) => {
39
          return <ErrorToast headerText={"Error"} text={lastError} onClose={() => toast.close(id)} />;
40
        },
41
        duration: 3000
42
      });
43
    }
44
  }, [lastError])
45

    
46
  const [sortSettings, setSortSettings] = useState({
47
    items: SortOptions.None,
48
    date: SortOptions.None
49
  });
50

    
51
  const handleSortChanged = useCallback((key: "items" | "date", sortSettings: any) => {
52
    let currentState = sortSettings[key];
53
    let otherKey = "items"
54

    
55
    if (key == "items") {
56
      otherKey = "date"
57
    }
58

    
59
    if (currentState == SortOptions.None) {
60
      setSortSettings({
61
        ...sortSettings,
62
        [key]: SortOptions.Asc,
63
        [otherKey]: SortOptions.None
64
      })
65
    }
66
    else if (currentState == SortOptions.Asc) {
67
      setSortSettings({
68
        ...sortSettings,
69
        [key]: SortOptions.Desc,
70
        [otherKey]: SortOptions.None
71
      })
72
    }
73
    else {
74
      setSortSettings({
75
        ...sortSettings,
76
        [key]: SortOptions.None,
77
        [otherKey]: SortOptions.None
78
      })
79
    }
80
  }, [setSortSettings]);
81

    
82
  const getSortIcon = (sortOption: SortOptions, size: string, color?: string) => {
83
    switch (sortOption) {
84
      case SortOptions.Asc:
85
        return <ChevronUpIcon size={size} color={color} />;
86
      case SortOptions.Desc:
87
        return <ChevronDownIcon size={size} color={color} />;
88
      default:
89
        return <MinusIcon size={size} color={color} />;
90
    }
91
  };
92

    
93
  // trigger refresh on triggerRefresh increment
94
  useEffect(() => {
95
    log.debug("NotesViewPage", "useEffect", "getNotes");
96
    getNotes();
97
  }, [triggerRefresh])
98

    
99
  // general comments check changed
100
  useEffect(() => {
101
    if (!notesLoading) {
102
      log.debug("NotesViewPage", "useEffect", "getNotes");
103
      getNotes();
104
    }
105
  }, [generalCommentsCheck, myCommentsCheck])
106

    
107

    
108
  const getNotes = useCallback(() => {
109
    dispatch(getAllNotes({
110
      myComments: myCommentsCheck,
111
      generalComments: generalCommentsCheck,
112
      sortOptions: sortSettings
113
    }));
114
  }, [myCommentsCheck, generalCommentsCheck, sortSettings]);
115

    
116

    
117
  const handleCreateComment = useCallback((newComment: string, replyingTo: { messageId: string; userName: string } | null) => {
118
    console.log(newComment, replyingTo)
119

    
120
    if (!requestPending) {
121
      // creating new comment
122
      toast.show({
123
        render: ({
124
          id
125
        }) => {
126
          return <InfoToast text={"Adding note"} onClose={() => toast.close(id)} />;
127
        },
128
        duration: 2000
129
      });
130
      if (replyingTo != null) {
131
        dispatch(createNote({
132
          newNote: { note: newComment, reply_to: replyingTo.messageId } as Note
133
        }))
134
      }
135
      else {
136
        dispatch(createNote({
137
          newNote: { note: newComment } as Note
138
        }))
139
      }
140
    }
141
  }, [dispatch, createNote]);
142

    
143

    
144

    
145
  return (
146
    <Box>
147
      <VStack>
148
        <Flex direction="row" align="flex-start" justifyContent="space-between" marginTop={1} marginLeft={2.5} marginRight={2.5}>
149
          <Text fontWeight="semibold" mt={3} ml={2} fontSize="md" color="#4D4D4D">General comments</Text>
150
          <Switch isChecked={generalCommentsCheck} onValueChange={() => { if (!notesLoading) setGeneralCommentsCheck(!generalCommentsCheck) }} size="lg" marginRight={2} />
151
        </Flex>
152
        <Flex direction="row" align="flex-start" justifyContent="space-between" marginTop={-1} marginLeft={2.5} marginRight={2.5}>
153
          <Text fontWeight="semibold" mt={3} ml={2} fontSize="md" color="#4D4D4D">My comments</Text>
154
          <Switch padding={0} isChecked={myCommentsCheck} onValueChange={() => { if (!notesLoading) setMyCommentsCheck(!myCommentsCheck) }} size="lg" marginRight={2} />
155
        </Flex>
156
        <Popover // @ts-ignore
157
          trigger={triggerProps => {
158
            return <Button marginLeft={4} marginBottom={2} width={150} backgroundColor="#F4DFAB" {...triggerProps} onPress={() => setIsSortOpen(true)}
159
              borderRadius={7}
160
              rightIcon={(sortSettings.date != SortOptions.None || sortSettings.items != SortOptions.None) ? (getSortIcon(sortSettings.date != SortOptions.None ? sortSettings.date : sortSettings.items, "xs", "#654B07")) : undefined}
161
            >
162
              <Text fontSize={14} color="#654B07">
163
                Sort {(sortSettings.date != SortOptions.None || sortSettings.items != SortOptions.None) ? (sortSettings.date != SortOptions.None ? "by date" : "by items") : ""}
164
              </Text>
165
            </Button>;
166
          }} isOpen={isSortOpen} onClose={() => setIsSortOpen(!isSortOpen)}>
167
          <Popover.Content w="48">
168
            <Popover.Arrow />
169
            <Popover.CloseButton onPress={() => setIsSortOpen(false)} />
170
            <Popover.Header><Text fontSize={"md"} color="#654B07">Sort Options</Text></Popover.Header>
171
            <Popover.Body>
172
              <VStack>
173
                <Button size="md" variant="outline" onPress={() => handleSortChanged("items", sortSettings)}
174
                  rightIcon={getSortIcon(sortSettings.items, "sm", "#654B07")}
175
                >
176
                  Items</Button>
177
                <Button size="md" variant="outline" marginTop={"5%"} onPress={() => handleSortChanged("date", sortSettings)}
178
                  rightIcon={getSortIcon(sortSettings.date, "sm", "#654B07")}>
179
                  Date</Button>
180
              </VStack>
181
            </Popover.Body>
182
            <Popover.Footer justifyContent="flex-end">
183
              <Button.Group space={2}>
184
                <Button colorScheme="coolGray" variant="ghost" onPress={() => setIsSortOpen(false)}>
185
                  Cancel
186
                </Button>
187
                <Button backgroundColor={"#F4DFAB"} onPress={() => { setIsSortOpen(false); getNotes() }}>
188
                  <Text color="#654B07">
189
                    Save
190
                  </Text>
191
                </Button>
192
              </Button.Group>
193
            </Popover.Footer>
194
          </Popover.Content>
195
        </Popover>
196
        {
197
          notesLoading ? (
198
            <LoadingBox text="Loading notes" />
199
          )
200
            :
201
            (<NotesListView height={Dimensions.get('window').height - 307} notes={notes} navigation={navigation} handleCreateComment={handleCreateComment} requestPending={requestPending} />)
202
        }
203

    
204

    
205
      </VStack>
206
    </Box>
207
  );
208
}
209

    
210
export default NotesViewPage;
(6-6/8)