components/modals/JourneyModal.tsx   A
last analyzed

Complexity

Total Complexity 15
Complexity/F 3

Size

Lines of Code 307
Function Count 5

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 15
eloc 253
mnd 10
bc 10
fnc 5
dl 0
loc 307
rs 10
bpm 2
cpm 3
noi 0
c 0
b 0
f 0

3 Functions

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