Projekt

Obecné

Profil

Stáhnout (8.02 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 {
5
  Box,
6
  Button,
7
  ChevronDownIcon,
8
  ChevronUpIcon,
9
  Flex,
10
  HStack,
11
  MinusIcon,
12
  Popover,
13
  Switch,
14
  Text,
15
  VStack,
16
  useToast,
17
  KeyboardAvoidingView
18
} from "native-base"
19
import { SortOptions } from "../types/general"
20
import { Note } from "../types/note"
21
import NotesListView from "../components/notes/NotesListView"
22
import { useDispatch, useSelector } from "react-redux"
23
import { AppDispatch, RootState } from "../stores/store"
24
import LoadingBox from "../components/loading/LoadingBox"
25
import { createNote, getAllNotes } from "../stores/actions/notesThunks"
26
import { RootStackParamList } from "./Navigation"
27
import { ErrorToast } from "../components/toast/ErrorToast"
28
import { InfoToast } from "../components/toast/InfoToast"
29

    
30
import {Dimensions, Platform} from "react-native";
31

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

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

    
36
  const dispatch = useDispatch<AppDispatch>();
37

    
38
  const [isSortOpen, setIsSortOpen] = useState(false);
39

    
40
  const [myCommentsCheck, setMyCommentsCheck] = useState(false);
41
  const [generalCommentsCheck, setGeneralCommentsCheck] = useState(true);
42

    
43
  const lastError = useSelector((state: RootState) => state.noteViewState.lastError)
44
  const toast = useToast();
45

    
46
  useEffect(() => {
47
    if (lastError) {
48
      toast.closeAll()
49
      toast.show({
50
        render: ({
51
          id
52
        }) => {
53
          return <ErrorToast headerText={"Error"} text={lastError} onClose={() => toast.close(id)} />;
54
        },
55
        duration: 3000
56
      });
57
    }
58
  }, [lastError])
59

    
60
  const [sortSettings, setSortSettings] = useState({
61
    items: SortOptions.None,
62
    date: SortOptions.None
63
  });
64

    
65
  const handleSortChanged = useCallback((key: "items" | "date", sortSettings: any) => {
66
    let currentState = sortSettings[key];
67
    let otherKey = "items"
68

    
69
    if (key == "items") {
70
      otherKey = "date"
71
    }
72

    
73
    if (currentState == SortOptions.None) {
74
      setSortSettings({
75
        ...sortSettings,
76
        [key]: SortOptions.Asc,
77
        [otherKey]: SortOptions.None
78
      })
79
    }
80
    else if (currentState == SortOptions.Asc) {
81
      setSortSettings({
82
        ...sortSettings,
83
        [key]: SortOptions.Desc,
84
        [otherKey]: SortOptions.None
85
      })
86
    }
87
    else {
88
      setSortSettings({
89
        ...sortSettings,
90
        [key]: SortOptions.None,
91
        [otherKey]: SortOptions.None
92
      })
93
    }
94
  }, [setSortSettings]);
95

    
96
  const getSortIcon = (sortOption: SortOptions, size: string, color?: string) => {
97
    switch (sortOption) {
98
      case SortOptions.Asc:
99
        return <ChevronUpIcon size={size} color={color} />;
100
      case SortOptions.Desc:
101
        return <ChevronDownIcon size={size} color={color} />;
102
      default:
103
        return <MinusIcon size={size} color={color} />;
104
    }
105
  };
106

    
107
  // trigger refresh on triggerRefresh increment
108
  useEffect(() => {
109
    log.debug("NotesViewPage", "useEffect", "getNotes");
110
    getNotes();
111
  }, [triggerRefresh])
112

    
113
  // general comments check changed
114
  useEffect(() => {
115
    if (!notesLoading) {
116
      log.debug("NotesViewPage", "useEffect", "getNotes");
117
      getNotes();
118
    }
119
  }, [generalCommentsCheck, myCommentsCheck])
120

    
121

    
122
  const getNotes = useCallback(() => {
123
    dispatch(getAllNotes({
124
      myComments: myCommentsCheck,
125
      generalComments: generalCommentsCheck,
126
      sortOptions: sortSettings
127
    }));
128
  }, [myCommentsCheck, generalCommentsCheck, sortSettings]);
129

    
130

    
131
  const handleCreateComment = useCallback((newComment: string, replyingTo: { messageId: string; userName: string } | null) => {
132
    console.log(newComment, replyingTo)
133

    
134
    if (!requestPending) {
135
      // creating new comment
136
      toast.show({
137
        render: ({
138
          id
139
        }) => {
140
          return <InfoToast text={"Adding note"} onClose={() => toast.close(id)} />;
141
        },
142
        duration: 2000
143
      });
144
      if (replyingTo != null) {
145
        dispatch(createNote({
146
          newNote: { note: newComment, reply_to: replyingTo.messageId } as Note
147
        }))
148
      }
149
      else {
150
        dispatch(createNote({
151
          newNote: { note: newComment } as Note
152
        }))
153
      }
154
    }
155
  }, [dispatch, createNote]);
156

    
157

    
158

    
159
  return (
160

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

    
219

    
220
          </VStack>
221
        </Box>
222
  );
223
}
224

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