Passed
Push — dev ( c5bc2a...3c211c )
by Kasper
01:09 queued 12s
created

JourneyModal.tsx ➔ JourneyModal   F

Complexity

Conditions 15

Size

Total Lines 195
Code Lines 161

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 161
dl 0
loc 195
rs 2.0999
c 0
b 0
f 0
cc 15

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like JourneyModal.tsx ➔ JourneyModal often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
import React from "react";
2
import { useState, useEffect, useRef } from 'react';
3
import { View, Text, TextInput, Button, Pressable, StyleSheet, Image, StatusBar, Modal } from "react-native";
4
import GestureRecognizer from 'react-native-swipe-gestures';
5
import scooterModel from "../../models/scooter";
6
import { showMessage, hideMessage } from "react-native-flash-message";
7
import Icon from 'react-native-vector-icons/Octicons';
8
import { Stopwatch, Timer } from 'react-native-stopwatch-timer';
9
import MapView, { Marker, Circle, Polygon } from 'react-native-maps';
10
11
12
export default function JourneyModal({navigation, scooter, journeyModal, setJourneyModal, toggleTimer, setToggleTimer}) {
13
    const [scooterName, setScooterName] = useState(null);
14
    const [scooterNumber, setScooterNumber] = useState(null);
15
    const [battery, setBattery] = useState(null);
16
    const [scooterPosition, setScooterPosition] = useState(null);
17
    const [scooterId, setScooterId] = useState(null);
18
    const markerRef = useRef(null);
19
    const [distance, setDistance] = useState(null);
20
    const [batteryPercentage, setBatteryPercentage] = useState(null);
21
    const [currentScooter, setCurrentScooter] = useState(null);
22
23
    const batteryImages = {
24
        '100': require('../../assets/battery_100.png'),
25
        '75': require('../../assets/battery_75.png'),
26
        '50': require('../../assets/battery_50.png'),
27
        '25': require('../../assets/battery_25.png')
28
    }
29
30
    function getBattery(batteryPercentage) {
31
        if (batteryPercentage >= 75) {
32
            return '100'
33
        } else if (batteryPercentage >= 50) {
34
            return '75'
35
        } else if (batteryPercentage >= 25) {
36
            return '50'
37
        } else {
38
            return '25'
39
        }
40
    };
41
42
    async function getScooterInfo(): Promise<void> {            
43
        if (scooter) {            
44
            const title = scooter['name'].split('#');
45
            setScooterName(title[0]);
46
            setScooterNumber(title[1]);
47
            setBattery(getBattery(scooter['battery']));
48
            setScooterId(scooter['_id']);
49
            
50
            const getScooter = await scooterModel.getSpecificScooter(scooter['_id']);
51
            
52
            setCurrentScooter(getScooter);
53
            
54
            setScooterPosition(getScooter['scooter']['coordinates']);
55
            setBatteryPercentage(getScooter['scooter']['battery'].toFixed(1));                        
56
            setDistance(getScooter['scooter']['trip']['distance'].toFixed(2));
57
58
            
59
            
60
            
61
        }
62
    }
63
64
    useEffect(() => {
65
        const interval = setInterval(() => {
66
67
            journeyModal ? getScooterInfo() : null;
68
69
            if (markerRef.current) {
70
                markerRef.current.animateMarkerToCoordinate(scooterPosition, 100);
71
            };
72
            
73
            
74
        }, 100);
75
        return () => clearInterval(interval);
76
      });
77
78
79
    async function stopJourney() {
80
        const result = await scooterModel.stopScooter(scooterId);
81
82
        if (Object.prototype.hasOwnProperty.call(result, 'errors')) {
83
            showMessage({
84
                message: result['errors']['title'],
85
                type: 'danger',
86
                position: 'bottom'
87
            })
88
89
            return;
90
        };
91
92
        showMessage({
93
            message: result['message'],
94
            type: 'success',
95
            position: 'bottom'
96
        });
97
98
        setJourneyModal(!journeyModal)
99
    };
100
101
    function getFormattedTime(time) {
102
        const currentTime = time;
103
        return currentTime;
104
    };
105
106
    return (
107
        <GestureRecognizer
108
            style={{flex: 1}}
109
        >
110
        <Modal
111
        animationType="slide"
112
        transparent={true}
113
        visible={journeyModal}
114
        onRequestClose={() => {
115
        }}
116
117
        >
118
            <View style={styles.modalContainer}></View>
119
            
120
            <MapView
121
                // ref={mapRef}
122
                style={styles.map}
123
                region={{
124
                    latitude: scooterPosition? scooterPosition['latitude'] : 56.161013580817986,
125
                    longitude: scooterPosition? scooterPosition['longitude'] : 15.587742977884904,
126
                    latitudeDelta: 0.001,
127
                    longitudeDelta: 0.001,
128
                }}
129
                userInterfaceStyle={'dark'}
130
            >
131
                {scooterPosition ? 
132
                    <Marker
133
                        ref={markerRef}                        
134
                        coordinate={scooterPosition}
135
                        icon={require('../../assets/scooter_green.png')}
136
                        tappable={true}
137
                        onPress={() => {                           
138
                        }}
139
                        >
140
                    </Marker> 
141
                    : 
142
                    <View></View>
143
                }
144
145
            </MapView>
146
147
            <View style={[styles.modalMessage, styles.shadowProp]}>
148
149
                <View style={styles.titleContainer}>
150
                    <Image style={styles.scooterImage} source={require('../../assets/scooter_large_white.png')}></Image>
151
152
                    <View style={styles.textContainer}>
153
                        <Text style={styles.scooterTitle}> {scooterName} {scooterNumber}</Text>
154
155
156
                        <View style={styles.travelInfoContainer}>
157
                            <View style={styles.travelInfo}>
158
                                <Icon 
159
                                    name='location' 
160
                                    size={30} 
161
                                    color='black'
162
                                />
163
164
                                <Text>{distance} km</Text>
165
                            </View>
166
   
167
168
169
                            <View style={styles.travelInfo}>
170
                                <Icon 
171
                                    name='clock' 
172
                                    size={30} 
173
                                    color='black'
174
                                />
175
                                <Stopwatch start={toggleTimer}
176
                                    options={styles.timer}
177
                                    getTime={(time) => {                                        
178
                                        getFormattedTime(time);
179
                                    }} 
180
                                />
181
182
                            </View>
183
                        
184
                            <View style={styles.travelInfo}>
185
                                <Image style={styles.battery} source={batteryImages[`${battery}`]}></Image>
186
187
                                <Text>{batteryPercentage}%</Text>
188
                            </View>
189
                    </View>
190
191
                    </View>
192
193
                </View>
194
 
195
                <Pressable style={styles.tourButton} onPress={() => {
196
                    stopJourney();
197
                    setToggleTimer(false);
198
                }}>
199
                    <Text style={{color: 'black'}}>Finish the ride</Text>
200
                </Pressable>
201
                
202
            </View>
203
        </Modal>
204
    </GestureRecognizer>
205
    )
206
}
207
208
const styles = StyleSheet.create({
209
    modalContainer: {
210
        backgroundColor: 'rgba(80, 80, 80, 0.6)',
211
        width: '100%',
212
        height: '100%',
213
        flex: 1,
214
    },
215
216
    map: {
217
        position: 'absolute',
218
        top: 0,
219
        left: 0,
220
        bottom: 0,
221
        right: 0,
222
        height: '65%',
223
    },
224
225
226
    titleContainer: {
227
        flexDirection: 'row',
228
        alignItems: 'center',
229
        marginBottom: 10,
230
        marginTop: 30
231
    },
232
233
    swipeButton: {
234
        width: '25%',
235
        height: 5,
236
        backgroundColor: 'lightgrey',
237
        borderRadius: 25
238
    },
239
240
    textContainer: {
241
        width: '60%',
242
        marginBottom: 10,
243
        alignItems: 'center',
244
    },
245
246
    modalMessage: {
247
        backgroundColor: 'cornflowerblue',
248
        width: '100%',
249
        height: '35%',
250
        justifyContent: 'space-around',
251
        alignItems: 'center',
252
        paddingTop: 10,
253
    },
254
255
    scooterTitle: {
256
        fontWeight: 'bold',
257
        marginBottom: 10,
258
        fontSize: 26,
259
        color: 'white'
260
    },
261
    
262
    battery: {
263
        marginLeft: 5,
264
        marginBottom: 15
265
    },
266
267
    scooterImage: {
268
        margin: 10
269
    },
270
271
    tourButton: {
272
        backgroundColor: 'white',
273
        width: '80%',
274
        height: 50,
275
        borderRadius: 10,
276
        justifyContent: 'center',
277
        alignItems: 'center',
278
    },
279
280
    timer: {
281
        backgroundColor: 'white',
282
    },
283
284
    travelInfoContainer: {
285
        flexDirection: 'row',
286
        backgroundColor: 'white',
287
        justifyContent: 'space-evenly',
288
        width: '100%',
289
        padding: 10,
290
        borderRadius: 25
291
    },
292
293
    travelInfo: {
294
        flexDirection: 'column',
295
        justifyContent: 'space-around',
296
        alignItems: 'center',
297
        height: 75
298
    },
299
300
    shadowProp: {
301
        elevation: 5,
302
        shadowColor: 'black'
303
      },
304
305
306
})