-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
324 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,291 @@ | ||
import React, { useEffect, useState } from 'react'; | ||
import { StyleSheet, Text, ScrollView, View, TouchableOpacity, RefreshControl, Dimensions } from 'react-native'; | ||
import { MaterialIcons } from '@expo/vector-icons'; | ||
import { useRoute } from '@react-navigation/native'; | ||
import MapView, { Marker, Polyline } from 'react-native-maps'; | ||
|
||
import { gql, useLazyQuery } from '@apollo/client'; | ||
|
||
import { getAsyncStorageData } from '../../common/common'; | ||
|
||
const styles = StyleSheet.create({ | ||
container: { | ||
flex: 1, | ||
backgroundColor: 'white', | ||
}, | ||
viewContainer: { | ||
marginVertical: 65, | ||
marginHorizontal: 30, | ||
}, | ||
noDataContainer: { | ||
backgroundColor: 'gainsboro', | ||
padding: 20, | ||
borderRadius: 5, | ||
}, | ||
loadingContainer: { | ||
backgroundColor: 'moccasin', | ||
padding: 20, | ||
borderRadius: 5, | ||
}, | ||
errorContainer: { | ||
backgroundColor: 'tomato', | ||
padding: 20, | ||
borderRadius: 5, | ||
}, | ||
mapContainer: { | ||
flex: 1, | ||
justifyContent: 'center', | ||
alignItems: 'center', | ||
}, | ||
map: { | ||
width: Dimensions.get('window').width, | ||
height: Dimensions.get('window').height, | ||
}, | ||
}); | ||
|
||
const GET_BUS_SERVICE_BY_BUS_SERVICE_NO = gql` | ||
query busServiceByBusServiceNo($busServiceNo: String!) { | ||
busServiceByBusServiceNo(busServiceNo: $busServiceNo) { | ||
serviceNo | ||
operator | ||
direction | ||
category | ||
originCode | ||
originBusStop { | ||
busStopCode | ||
roadName | ||
description | ||
latitude | ||
longitude | ||
} | ||
destinationCode | ||
destinationBusStop { | ||
busStopCode | ||
roadName | ||
description | ||
latitude | ||
longitude | ||
} | ||
amPeakFreq | ||
amOffpeakFreq | ||
pmPeakFreq | ||
pmOffpeakFreq | ||
loopDesc | ||
} | ||
} | ||
`; | ||
|
||
const singaporeLatitude = 1.3521; | ||
const singaporeLongitude = 103.8198; | ||
|
||
function BusMapView(props: any): JSX.Element { | ||
const route = useRoute(); | ||
|
||
const [theme, setTheme] = useState('light'); | ||
|
||
const [region, setRegion] = useState({ | ||
latitude: singaporeLatitude, | ||
longitude: singaporeLongitude, | ||
latitudeDelta: 0.05, | ||
longitudeDelta: 0.05, | ||
}); | ||
|
||
const [responseData, setResponseData] = useState<any>(null); | ||
|
||
const [refreshing, setRefreshing] = useState(false); | ||
|
||
const [getBusServiceByBusServiceNo, { loading, error, data, client }] = useLazyQuery( | ||
GET_BUS_SERVICE_BY_BUS_SERVICE_NO, | ||
); | ||
|
||
console.log('loading = ', loading); | ||
console.log('error = ', error); | ||
console.log('data = ', data); | ||
|
||
useEffect(() => { | ||
getThemeData(); | ||
props.navigation.addListener('focus', () => { | ||
getThemeData(); | ||
}); | ||
}, []); | ||
|
||
useEffect(() => { | ||
if (route.params) { | ||
const busServiceNo = (route.params as any).busServiceNo; | ||
getBusServiceByBusServiceNo({ | ||
variables: { busServiceNo: busServiceNo }, | ||
}); | ||
} | ||
}, [route.params]); | ||
|
||
useEffect(() => { | ||
if (data) { | ||
setResponseData(data); | ||
} | ||
}, [data]); | ||
|
||
const getThemeData = async () => { | ||
const theme = await getAsyncStorageData('@theme'); | ||
if (theme) { | ||
setTheme(theme); | ||
} | ||
}; | ||
|
||
const onRefresh = () => { | ||
setRefreshing(true); | ||
|
||
getThemeData(); | ||
client?.clearStore(); | ||
setResponseData(null); | ||
if (route.params) { | ||
const busServiceNo = (route.params as any).busServiceNo; | ||
getBusServiceByBusServiceNo({ | ||
variables: { busServiceNo: busServiceNo }, | ||
}); | ||
} | ||
|
||
if (!loading) { | ||
setRefreshing(false); | ||
} | ||
}; | ||
|
||
const handleBackButtonClick = () => { | ||
props.navigation.goBack(); | ||
}; | ||
|
||
const renderBusMapViewResultDiv = () => { | ||
let busMapViewResultDiv = ( | ||
<View style={styles.noDataContainer}> | ||
<Text>There is no data</Text> | ||
</View> | ||
); | ||
|
||
if (loading) { | ||
busMapViewResultDiv = ( | ||
<View style={styles.loadingContainer}> | ||
<Text>Loading...</Text> | ||
</View> | ||
); | ||
} else { | ||
if (error) { | ||
busMapViewResultDiv = ( | ||
<View style={styles.errorContainer}> | ||
<Text>There is error</Text> | ||
</View> | ||
); | ||
} else { | ||
if (responseData && responseData.busServiceByBusServiceNo) { | ||
const markerList: any[] = []; | ||
const coordinatesList: any[] = []; | ||
|
||
responseData.busServiceByBusServiceNo.forEach((item: any, i: number) => { | ||
if (item.originBusStop && item.destinationBusStop) { | ||
if (item.direction === 1) { | ||
setData(item, markerList, coordinatesList); | ||
} | ||
} | ||
}); | ||
|
||
busMapViewResultDiv = ( | ||
<View style={styles.mapContainer}> | ||
<MapView style={styles.map} region={region} showsUserLocation={true} followsUserLocation={true}> | ||
{renderMarkers(markerList)} | ||
{renderPolyline(coordinatesList)} | ||
</MapView> | ||
</View> | ||
); | ||
} | ||
} | ||
} | ||
|
||
return busMapViewResultDiv; | ||
}; | ||
|
||
const setData = (item: any, markerList: any[], coordinatesList: any[]) => { | ||
// marker | ||
const originBusStopLatLng = { | ||
title: item.originBusStop.roadName, | ||
description: item.originBusStop.description, | ||
latlng: { | ||
latitude: item.originBusStop.latitude, | ||
longitude: item.originBusStop.longitude, | ||
}, | ||
}; | ||
markerList.push(originBusStopLatLng); | ||
|
||
const destinationBusStopLatLng = { | ||
title: item.destinationBusStop.roadName, | ||
description: item.destinationBusStop.description, | ||
latlng: { | ||
latitude: item.destinationBusStop.latitude, | ||
longitude: item.destinationBusStop.longitude, | ||
}, | ||
}; | ||
markerList.push(destinationBusStopLatLng); | ||
|
||
// coordinates | ||
const originBusStopCoordinates = { | ||
latitude: item.originBusStop.latitude, | ||
longitude: item.originBusStop.longitude, | ||
}; | ||
coordinatesList.push(originBusStopCoordinates); | ||
|
||
const destinationBusStopCoordinates = { | ||
latitude: item.destinationBusStop.latitude, | ||
longitude: item.destinationBusStop.longitude, | ||
}; | ||
coordinatesList.push(destinationBusStopCoordinates); | ||
}; | ||
|
||
const renderMarkers = (markerList: any[]) => { | ||
let markers: any[] = []; | ||
|
||
if (markerList) { | ||
markers = markerList.map((marker: any, i: number) => { | ||
return <Marker key={i} coordinate={marker.latlng} title={marker.title} description={marker.description} />; | ||
}); | ||
} | ||
|
||
return markers; | ||
}; | ||
|
||
const renderPolyline = (coordinatesList: any[]) => { | ||
const polyline = ( | ||
<Polyline | ||
coordinates={coordinatesList} | ||
strokeColor="#FF6347" // fallback for when `strokeColors` is not supported by the map-provider | ||
strokeColors={['tomato']} | ||
strokeWidth={5} | ||
/> | ||
); | ||
return polyline; | ||
}; | ||
|
||
return ( | ||
<ScrollView | ||
style={{ flex: 1, backgroundColor: theme === 'light' ? 'white' : 'black' }} | ||
refreshControl={ | ||
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} colors={['tomato', 'tomato', 'black']} /> | ||
} | ||
contentContainerStyle={{ flexGrow: 1 }} | ||
> | ||
<View style={styles.viewContainer}> | ||
<TouchableOpacity onPress={() => handleBackButtonClick()}> | ||
<MaterialIcons name="arrow-back" size={24} color={theme === 'light' ? 'black' : 'white'} /> | ||
</TouchableOpacity> | ||
|
||
<View style={{ marginVertical: 15 }}></View> | ||
|
||
<Text style={{ fontSize: 25, fontWeight: 'bold', color: theme === 'light' ? 'black' : 'white' }}> | ||
Bus Map View | ||
</Text> | ||
|
||
<View style={{ marginVertical: 15 }}></View> | ||
|
||
{renderBusMapViewResultDiv()} | ||
</View> | ||
</ScrollView> | ||
); | ||
} | ||
|
||
export default BusMapView; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.