Projekt

Obecné

Profil

Stáhnout (7.69 KB) Statistiky
| Větev: | Tag: | Revize:
1 f22a2126 Michal Schwob
import {
2
    VStack,
3
    Box,
4
    Text,
5
    HStack,
6
    ScrollView,
7
    Flex,
8
    Button,
9
    CloseIcon,
10
    IconButton,
11
    TextArea,
12
    useToast,
13
    KeyboardAvoidingView
14
} from "native-base";
15 cb25df10 Fantič
import { Note } from "../../types/note";
16
import NoteView from "./NoteView";
17 2135f53d Fantič
import { MessageIcon } from "../general/Icons";
18 56626a63 Fantič
import React, { useCallback, useState } from "react";
19 2135f53d Fantič
import { updateNote, deleteNote } from "../../stores/actions/notesThunks";
20
import { ConfirmDialog } from "../general/Dialogs";
21 b56c1e7d Fantič
import { AppDispatch, RootState } from "../../stores/store";
22
import { useDispatch, useSelector } from "react-redux";
23 f386a4fe Fantič
import { InfoToast } from "../toast/InfoToast";
24 b56c1e7d Fantič
import { UserRole } from "../../stores/reducers/userSlice";
25 cb25df10 Fantič
26 8b1106f4 Fantič
27
28 293f99f8 Fantič
const NotesListView = (props: { notes: Note[], navigation: any, handleCreateComment: any, requestPending: boolean, height: number }) => {
29 cb25df10 Fantič
    const notes = props.notes;
30 2135f53d Fantič
31 b56c1e7d Fantič
    // const userRole = useSelector((state: RootState) => state.user.role)
32
    const userId = useSelector((state: RootState) => state.user.userId)
33
    const userRole = useSelector((state: RootState) => state.user.role)
34
35
    console.log(userRole)
36
37 2135f53d Fantič
    const [newComment, setNewComment] = useState<string>("");
38
    const [replyingTo, setReplyingTo] = useState<{ messageId: string; userName: string } | null>(null);
39
40 f386a4fe Fantič
    const toast = useToast();
41
42 bc25708c Fantič
    const [renderedNotes, setRenderedNotes] = useState(6);
43
44 2135f53d Fantič
    const cancelRef = React.useRef(null);
45
46
    const dispatch = useDispatch<AppDispatch>();
47
48
    const [confirmDialog, setConfirmDialog] = React.useState<{
49
        headerText?: string;
50
        bodyText?: string;
51
        confirmText?: string;
52
        confirmColor?: string;
53
        cancelRef?: any;
54
        onClose?: () => void;
55
        onSubmit?: () => void;
56
    } | null>(null);
57
58 56626a63 Fantič
    const handleReply = useCallback((messageId: string, userName: string) => {
59
        setReplyingTo({ messageId, userName });
60
    }, [setReplyingTo]);
61 b5ac7218 Fantič
62 56626a63 Fantič
    const handleEdit = useCallback((note: Note) => {
63
        if (!props.requestPending) {
64 2135f53d Fantič
            dispatch(updateNote(note));
65 56626a63 Fantič
        }
66
    }, [dispatch, props.requestPending]);
67 b5ac7218 Fantič
68 56626a63 Fantič
    const handleDelete = useCallback((messageId: string) => {
69
        if (!props.requestPending) {
70
            dispatch(deleteNote({ noteId: messageId }));
71
        }
72
    }, [dispatch, props.requestPending]);
73 2135f53d Fantič
74 f386a4fe Fantič
75
76 8b1106f4 Fantič
    const handleScrollEnd = (event: any) => {
77 bc25708c Fantič
        const offsetY = event.nativeEvent.contentOffset.y;
78
        const contentHeight = event.nativeEvent.contentSize.height;
79
        const screenHeight = event.nativeEvent.layoutMeasurement.height;
80
81
        if (offsetY + screenHeight >= contentHeight - 20) {
82
            // Load more notes when the user is near the end of the list
83
            const nextBatchSize = 5; // Number of notes to render in the next batch
84
85 8b1106f4 Fantič
            if ((renderedNotes + nextBatchSize) > notes.length && (renderedNotes + nextBatchSize) != notes.length) {
86 f386a4fe Fantič
                toast.closeAll()
87
                toast.show({
88
                    render: ({
89
                        id
90
                    }) => {
91
                        return <InfoToast text={"All notes loaded..."} onClose={() => toast.close(id)} />;
92
                    },
93
                    duration: 3000
94
                });
95 bc25708c Fantič
                setRenderedNotes(notes.length);
96 f386a4fe Fantič
97 bc25708c Fantič
            }
98 8b1106f4 Fantič
            else if ((renderedNotes + nextBatchSize) != notes.length) {
99 f386a4fe Fantič
                toast.closeAll()
100
                toast.show({
101
                    render: ({
102
                        id
103
                    }) => {
104
                        return <InfoToast text={"Loading more notes..."} onClose={() => toast.close(id)} />;
105
                    },
106
                    duration: 3000
107
                });
108 bc25708c Fantič
                setRenderedNotes(renderedNotes + nextBatchSize);
109 f386a4fe Fantič
110 bc25708c Fantič
            }
111
        }
112
    };
113
114 cb25df10 Fantič
    return (
115 f22a2126 Michal Schwob
        <KeyboardAvoidingView
116
            h={ {lg: "auto"} }
117
            behavior={ "padding" }
118
            keyboardVerticalOffset={ 600 }
119
            mb={ 2 }
120
        >
121 9814562f Fantič
        <VStack >
122 293f99f8 Fantič
            <Box height={props.height - (replyingTo ? 40 : 0) ?? undefined} marginBottom={2}>
123 b5ac7218 Fantič
                {/* Notes */}
124 9814562f Fantič
                <ScrollView contentContainerStyle={{ flexGrow: 1 }} onScrollEndDrag={handleScrollEnd} paddingLeft={2.5} paddingRight={2.5}>
125 2135f53d Fantič
                    {
126
                        notes && notes.length > 0 ? (
127
                            <VStack>
128 bc25708c Fantič
                                {
129 8b1106f4 Fantič
                                    notes.slice(0, renderedNotes).map((note, index) => {
130 f386a4fe Fantič
131 b56c1e7d Fantič
                                        return <NoteView higlighted={replyingTo?.messageId == note.uuid} key={index} note={note}
132
                                            handleReply={
133
                                                handleReply
134
                                            }
135
136
                                            handleDelete={
137
                                                (note.username == userId || userRole == UserRole.Admin) ?
138
                                                    handleDelete
139
                                                    :
140
                                                    undefined
141
                                            }
142
143
                                            handleEdit={
144
                                                (note.username == userId || userRole == UserRole.Admin) ?
145
                                                    handleEdit
146
                                                    :
147
                                                    undefined
148
                                            } 
149
                                            setConfirmDialog={setConfirmDialog} navigation={props.navigation} />;
150 f386a4fe Fantič
151 8b1106f4 Fantič
                                    })
152 bc25708c Fantič
                                }
153 2135f53d Fantič
                            </VStack>
154
                        ) : (
155
                            <Text>There are no notes.</Text>
156
                        )
157
                    }
158
                </ScrollView>
159
            </Box>
160
161 b5ac7218 Fantič
            {/* Create comment */}
162 cb25df10 Fantič
            {
163 2135f53d Fantič
                props.handleCreateComment != null &&
164 b5ac7218 Fantič
                <VStack>
165
166
                    {/* Replying to */}
167
                    {replyingTo != null &&
168 f22a2126 Michal Schwob
                        <Flex direction="row" alignItems="center" justify="flex-end" height={10} backgroundColor={"secondary.50"}>
169 b5ac7218 Fantič
                            <Text>Replying to {replyingTo.userName}</Text>
170 f22a2126 Michal Schwob
                            <IconButton onPress={() => setReplyingTo(null)} size="sm" icon={<CloseIcon />} marginLeft={-1} marginRight={20} />
171 b5ac7218 Fantič
                        </Flex>
172
                    }
173 bc25708c Fantič
174 b5ac7218 Fantič
175
                    {/* Add comment */}
176 b56c1e7d Fantič
                    <HStack height={90} marginLeft={1.5} marginRight={1.5}>
177 b5ac7218 Fantič
                        <TextArea
178
                            flex={1}
179 b56c1e7d Fantič
                            placeholder={userRole == UserRole.Unauthorized || userRole == UserRole.User ? "Unathorized to add comment" : "Add comment"}
180
                            isDisabled={userRole == UserRole.Unauthorized || userRole == UserRole.User}
181 b5ac7218 Fantič
                            fontSize={14}
182
                            value={newComment}
183
                            onChangeText={setNewComment}
184
                            autoCompleteType={undefined}
185 b56c1e7d Fantič
186
187 b5ac7218 Fantič
                        />
188
                        <Flex marginLeft={2} marginBottom={8}>
189 b56c1e7d Fantič
                            <Button disabled={userRole == UserRole.Unauthorized || userRole == UserRole.User} onPress={() => props.handleCreateComment(newComment, replyingTo)} startIcon={<MessageIcon color="#FFF" />} />
190 b5ac7218 Fantič
                        </Flex>
191
                    </HStack>
192
                </VStack>
193 cb25df10 Fantič
            }
194 2135f53d Fantič
            <ConfirmDialog {...confirmDialog} isShown={confirmDialog != null} cancelRef={cancelRef} />
195 b5ac7218 Fantič
        </VStack >
196 f22a2126 Michal Schwob
        </KeyboardAvoidingView>
197 cb25df10 Fantič
    );
198
}
199
200
export default NotesListView