components/Map.tsx   A
last analyzed

Complexity

Total Complexity 11
Complexity/F 2.2

Size

Lines of Code 302
Function Count 5

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 11
eloc 219
mnd 6
bc 6
fnc 5
dl 0
loc 302
rs 10
bpm 1.2
cpm 2.2
noi 0
c 0
b 0
f 0

2 Functions

Rating   Name   Duplication   Size   Complexity  
A Map.tsx ➔ markerIcon 0 6 2
D Map.tsx ➔ Map 0 217 9
1
import { useState, useEffect, useRef } from 'react';
2
import { ScrollView, Image, Text, View, StyleSheet, StatusBar, Button, Pressable, InteractionManagerStatic, TouchableHighlightBase } from 'react-native';
3
import MapView, { Marker, Circle, Polygon } from 'react-native-maps';
4
import * as Location from 'expo-location';
5
import React from 'react';
6
import mapModel from '../models/map';
7
import scooterModel from '../models/scooter';
8
import Icon from 'react-native-vector-icons/Octicons';
9
import ScooterModal from './modals/ScooterModal';
10
import NavBar from './drawer/NavBar';
11
import ZoneModal from './modals/ZoneModal';
12
import { showMessage, hideMessage } from "react-native-flash-message";
13
import QrScanner from './modals/QrScanner';
14
import JourneyModal from './modals/JourneyModal';
15
16
const marker = require('../assets/scooter_white.png');
17
const selectedMarker = require('../assets/scooter_blue.png');
18
19
function markerIcon(index, selected) {
20
    if (index === selected) {
21
        return selectedMarker;
22
    }
23
    return marker;
24
};
25
26
27
export default function Map({navigation, API_KEY, position, setPosition, token}): any {
28
    const [locationMarker, setLocationMarker] = useState(null);
29
    const [currentCity, setCurrentCity] = useState(null);
30
    const [zones, setZones] = useState([]);
31
    const [scooters, setScooters] = useState([]);
32
    const [currentScooter, setCurrentScooter] = useState(null);
33
    const [modalVisible, setModalVisible] = useState(false);
34
    const [zoneModalVisible, setZoneModalVisible] = useState(false);
35
    const [currentZone, setCurrentZone] = useState(null);
36
    const [cameraVisible, setCameraVisible] = useState(false);
37
    const [journeyModal, setJourneyModal] = useState(false);
38
    const [toggleTimer, setToggleTimer] = useState(false);
39
    const [markerSelected, setMarkerSelected] = useState(null);
40
    
41
    const mapRef = useRef(null);    
42
    /**
43
     * Set user position
44
     */
45
    useEffect(() => {
46
        async function setUpMap(): Promise<void> {
47
            const { status } = await Location.requestForegroundPermissionsAsync();
48
49
            if (status !== 'granted') {
50
                showMessage({
51
                    message: 'Permission to access location was denied',
52
                    type: 'danger',
53
                    position: 'center'
54
                });
55
                return;
56
            }
57
58
            const currentLocation = await Location.getCurrentPositionAsync({});
59
60
            const userCoordinates = {
61
                //latlang hardcoded for testing
62
                latitude: await currentLocation.coords.latitude,
63
                longitude: await currentLocation.coords.longitude
64
                // latitude: 56.674283063446495,
65
                // longitude: 12.857826360096537
66
            };
67
68
            
69
            
70
            setPosition(userCoordinates);
71
            
72
            // mapModel.getClosestCity(position);
73
74
            setLocationMarker(<Marker
75
                coordinate={{
76
                    //latlang hardcoded for testing
77
                    latitude: currentLocation.coords.latitude,
78
                    longitude: currentLocation.coords.longitude
79
                    // latitude: 56.161013580817986,
80
                    // longitude: 15.587742977884904
81
                }}
82
                title="My location"
83
                pinColor="blue"
84
                flat={false}
85
            />);
86
87
88
            // Get closest city to user location
89
            const city = await mapModel.getClosestCity(userCoordinates);
90
            
91
            
92
            // Set city that is closest to user
93
            setCurrentCity(city);
94
            
95
            
96
            /**
97
             * Set zones on map
98
             */
99
            const zones = mapModel.getZones(city);
100
            setZones(zones);
101
        };
102
103
104
        setUpMap();
105
106
    }, []);
107
108
    /**
109
     * Get scooters for current city,
110
     * Updated every 5 seconds
111
     */
112
    useEffect(() => {
113
        const interval = setInterval(() => {
114
115
            // Get scooters
116
            async function getScooters() {
117
                // const city = await mapModel.getClosestCity(position);
118
                
119
                const result = await scooterModel.getScooters(currentCity); 
120
                
121
                if (result) {
122
                    const scooters = result['cityScooters'];
123
                    
124
                    const sortedScooters = scooterModel.sortAvailableScooters(scooters);
125
                    setScooters(sortedScooters);
126
                };
127
128
            };
129
130
      
131
            getScooters();
132
133
        }, 2000);
134
        return () => clearInterval(interval);
135
      });
136
    
137
    /**
138
     * Update user position
139
     */
140
    useEffect(() => {
141
        const interval = setInterval(() => {
142
143
            // Get scooters
144
            async function updateUserPosition() {
145
                const currentLocation = await Location.getCurrentPositionAsync({});
146
                const userCoordinates = {
147
                    //latlang hardcoded for testing
148
                    latitude: await currentLocation.coords.latitude,
149
                    longitude: await currentLocation.coords.longitude
150
                    // latitude: 56.674283063446495,
151
                    // longitude: 12.857826360096537
152
                };
153
                
154
                setPosition(userCoordinates);
155
            };
156
157
            updateUserPosition();
158
159
        }, 2000);
160
        return () => clearInterval(interval);
161
      });
162
163
164
165
    return (
166
        <View style={styles.container}>
167
            
168
            {journeyModal ?
169
                <View
170
                style={{
171
                    width: '100%',
172
                    height: 50,
173
                    backgroundColor: 'white',
174
                    zIndex: 1
175
                }}
176
                />
177
                    :
178
                <View></View>
179
            }
180
181
            <MapView
182
                ref={mapRef}
183
                style={styles.map}
184
                initialRegion={{
185
                    latitude: position.latitude? position.latitude : 56.161013580817986,
186
                    longitude: position.longitude? position.longitude : 15.587742977884904,
187
                    latitudeDelta: 0.03,
188
                    longitudeDelta: 0.03,
189
                }}
190
            >
191
                {locationMarker}
192
193
                {scooters.map((s, index) => 
194
                    <Marker
195
                        coordinate={s['coordinates']}
196
                        icon={markerIcon(index, markerSelected)}
197
                        tappable={true}
198
                        key={index}
199
                        onPress={() => {
200
                            setCurrentScooter(s);                                                        
201
                            setModalVisible(true);
202
                            setMarkerSelected(index);                            
203
                        }}
204
                        >
205
                    </Marker>
206
                )}
207
                {zones.map((z, index) => (                    
208
                    <Polygon 
209
                        coordinates={z['coordinates']}
210
                        strokeColor={z['zoneColor']}
211
                        strokeWidth={3}
212
                        fillColor={z['zoneColor']}
213
                        key={index}
214
                        tappable={true}
215
                        onPress={() => {
216
                            setCurrentZone(z)
217
                            setZoneModalVisible(true)                            
218
                        }}
219
                    />
220
                ))}
221
            </MapView>
222
223
            <ScooterModal navigation={navigation} scooter={currentScooter} modalVisible={modalVisible} currentCity={currentCity} setModalVisible={setModalVisible} setJourneyModal={setJourneyModal} setToggleTimer={setToggleTimer} position={position} setCurrentScooter={setCurrentScooter}/> 
224
225
            <ZoneModal navigation={navigation} zone={currentZone} zoneModalVisible={zoneModalVisible} setZoneModalVisible={setZoneModalVisible} currentCity={currentCity}/>
226
            
227
 
228
            <JourneyModal navigation={navigation} scooter={currentScooter} journeyModal={journeyModal} setJourneyModal={setJourneyModal} toggleTimer={toggleTimer} setToggleTimer={setToggleTimer}/>
229
230
            <Pressable onPress={() => {setCameraVisible(true)}} style={styles.googleLogin}>
231
                    <Icon 
232
                        name='screen-full' 
233
                        size={15} 
234
                        color='white'
235
                    />
236
                    <Text style={styles.googleText}>Scan to unlock</Text>
237
            </Pressable>
238
            
239
            <NavBar navigation={navigation} mapRef={mapRef} position={position}/>
240
            <QrScanner navigation={navigation} cameraVisible={cameraVisible} setCameraVisible={setCameraVisible} scooter={currentScooter} setModalVisible={setModalVisible} currentCity={currentCity} setCurrentScooter={setCurrentScooter}/>
241
        </View>
242
        
243
    )
244
}
245
246
const styles = StyleSheet.create({
247
    container: {
248
        height: '100%',
249
        alignItems: "center",
250
        width: '100%'
251
    },
252
253
    map: {
254
        position: 'absolute',
255
        top: 0,
256
        left: 0,
257
        bottom: 0,
258
        right: 0,
259
    },
260
261
    drawer: {
262
        position: 'absolute',
263
        width: 50,
264
        height: 50, 
265
        left: 50,
266
        backgroundColor: 'white',
267
        marginTop: 50,
268
        borderRadius: 25,
269
        justifyContent: 'center',
270
        alignItems: 'center'
271
    },
272
    
273
    shadowProp: {
274
        elevation: 5,
275
        shadowColor: 'black'
276
    },
277
278
    googleLogin: {
279
        backgroundColor: '#1A1A1A',
280
        width: '65%',
281
        height: 45,
282
        borderRadius: 25,
283
        display: 'flex',
284
        flexDirection: 'row',
285
        justifyContent: 'center',
286
        alignItems: 'center',
287
        marginBottom: 30
288
    },
289
290
    googleText: {
291
        color: 'white',
292
        fontWeight: 'bold',
293
        fontSize: 18,
294
        marginLeft: 10
295
    },
296
297
    googleIcon: {
298
        height: 20,
299
        width: 20
300
    }
301
});
302
303