Skip to content
This repository has been archived by the owner on May 20, 2024. It is now read-only.

DIsplay a map full of stations and let a user select a station to view data at that station. #14

Closed
wants to merge 11 commits into from
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ local.properties
node_modules/
npm-debug.log
yarn-error.log
.env
.env*

# BUCK
buck-out/
Expand Down
Binary file added app/assets/images/map/callout.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/images/map/callout@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/images/map/callout@3x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/images/map/station-marker.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/images/map/station-marker@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/images/map/station-marker@3x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
66 changes: 66 additions & 0 deletions app/components/map-callout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React, { Component } from 'react'
import {
Image,
Text,
View,
StyleSheet,
} from 'react-native'

import BaseStyle from '../base-styles'
import callout from '../assets/images/map/callout.png'

export default class MapCallout extends Component {
get formatStationLocation() {
const { station } = this.props
const latitude = station.location[1]
const longitude = station.location[0]

return `${latitude} N ${longitude} W`
}

render() {
const { station } = this.props

return (
<View style={styles.container}>
<Image source={callout} style={styles.callout} />
<View style={styles.textContainer}>
<Text
style={styles.stationName}
numberOfLines={1}
ellipsizeMode={'tail'}
>
{station.name}
</Text>
<Text style={styles.stationLocation}>{this.formatStationLocation}</Text>
</View>
</View>
)
}
}

const styles = StyleSheet.create({
container: {
position: 'relative',
width: 258,
height: 98,
},
textContainer: {
zIndex: 1,
marginTop: 31,
marginLeft: 40,
},
callout: {
position: 'absolute',
},
stationName: {
fontSize: BaseStyle.smallFontSize,
marginBottom: 1,
width: 170,
},
stationLocation: {
fontFamily: BaseStyle.numericFontFamily,
fontSize: 10,
color: BaseStyle.subtleColor,
},
})
47 changes: 36 additions & 11 deletions app/components/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,35 @@ import React, { Component } from 'react'
import {
StyleSheet,
} from 'react-native'

import MapView from 'react-native-maps'

import { Actions } from 'react-native-router-flux'
import Config from '../lib/config'
import MapCallout from './map-callout'
import stationMarker from '../assets/images/map/station-marker.png'

export default class Map extends Component {
constructor(props) {
super(props)

this.state = { stations: null }
this.state = {
stations: null,
userLocation: null,
}
}

componentDidMount() {
navigator.geolocation.getCurrentPosition((position) => {
const { latitude, longitude } = position.coords

this.setState({
userLocation: { latitude, longitude },
userLocation: {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
},
})
})

fetch('http://localhost:8000/api/get-stations').then(res => res.json()).then((json) => {
this.setState({ stations: json.formattedStations })
fetch(`${Config.HOST}/get-stations`).then(res => res.json()).then((json) => {
this.setState({ stations: json.stations })
})
}

Expand All @@ -41,17 +49,34 @@ export default class Map extends Component {
longitude: userLocation.longitude,
latitudeDelta: 0.315,
longitudeDelta: 0.321,
showPointsOfInterest: false,
showBuildings: false,
}}
>
{stations.map(station => (
{stations.map((station, index) => (
<MapView.Marker
key={index}
image={stationMarker}
coordinate={{
latitude: station.location[0],
longitude: station.location[1],
}}
/>
calloutOffset={{ x: 0, y: 30 }}
>
<MapView.Callout
tooltip
width={258}
height={98}
onPress={() => {
Actions.stationDetail({
location: {
latitude: station.location[0],
longitude: station.location[1],
},
})
}}
>
<MapCallout station={station} />
</MapView.Callout>
</MapView.Marker>
))}
</MapView>
)
Expand Down
21 changes: 14 additions & 7 deletions app/components/station-detail/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const StationDetail = class extends Component {
}

componentDidMount() {
this.findCurrentLocation()
this.requestLoctionInformation()
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BlakeWilliams I am calling this on mount so it kicks off the first time (when you open the app for the first time). If you then select a new location via the map, this works as well. Lastly, while within this same state you go to the map and pick another station nothing happens. You see the new screen come in, but no actions are fetched.

Thinking about this now, this is accurate since the component is already mounted? But at the same time that is odd because it works once then stops.

I was hooking into componentWillReceiveProps and that was fired way too much due to the reducer setting the props after various actions were completed.

Could I still use that method above but do some logic to compare this.props and nextProps basically:

if (this.props.location !== this.nextProps) { // kick off a new request }

(Also as I was writing this I thought of that solution, another reason PR's and code reviews are so great. I have had this happen a few times).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you need two different components. One that fetches current location on mount and another that fetches the one from props?

AppState.addEventListener('change', this.handleAppStateChange)
}

Expand All @@ -44,15 +44,22 @@ const StationDetail = class extends Component {
}

if (appState === 'active' && this.state.previousState !== 'active') {
this.findCurrentLocation()
this.requestLoctionInformation()
}
}

findCurrentLocation() {
fetchLocation().then((location) => {
this.props.fetchTideData(location)
this.props.findCityName(location)
})
requestLoctionInformation() {
const { location, fetchTideData, findCityName } = this.props

if (location) {
fetchTideData(location)
findCityName(location)
} else {
fetchLocation().then((location) => {
fetchTideData(location)
findCityName(location)
})
}
}

render() {
Expand Down
3 changes: 1 addition & 2 deletions app/components/station-detail/tide-phrase.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ export default class TidePhrase extends Component {
ellipsizeMode="tail"
style={[
BaseStyle.tidePhraseStyle,
styles.fadedPhraseText,
styles.cityText,
]}
>
Expand All @@ -57,7 +56,7 @@ export default class TidePhrase extends Component {
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
marginBottom: BaseStyle.largeSpacing,
marginVertical: BaseStyle.largeSpacing,
},
arrow: {
marginTop: 10,
Expand Down
Loading