Returns the address of the geographically closest store from the dataset based upon input location
Upon typing in an address in the proper format, a user fires off an onKeyDown
event by pressing the enter button. At this point getNearestLocation
is invoked with this.state.value
as an argument. The value is updated onChange
by an event bound to the input field. After getNearestLocation
is invoked data from the event is parsed and stored in a data object. A /POST request is then sent to an API endpoint with the data object. This /POST request is promisified with axios.
The server receives a /POST request to its /distance
endpoint and middlewear getLatLong
is invoked. This method assigns minDistance
to Number.MAX_VALUE
and minLocation
to undefined
. Both of these variables are defined in the outer scope for use in calculateDistance
. Location information is parsed from the request object and a /GET request is made to the Geocoding API endpoit. When the response comes back latitude and longitude are parsed and stored in variables.
A promise is then instantiated and loadCsv
is invoked with lat and long variables. This promise is set to resolve in 1 second. After loadCsv
is invoked a fs readStream is created to read store-locations.csv
. Relevant headers are set to be read from the stream and for each line, calculateDistance
is invoked with lat, long, and data from the CSV line. calculateDistance
performs operations which determine distance based on longitude and latitude. After these operations are complete, the conditional checks to see if the current distance is less than the current minDistance
. If this is true minDistance
and minLocation
are updated to the current variables. When there are no more lines in the CSV file an end
event is fired off, which closes the stream.
At this point, our promise resolves and a response is sent back to the client's request with a json encoded object containing minDistance
and minLocation
. The client receives this response and stores the data in variables, which are then used to setState
. After the state is set there is a ternary condition that returns the MapImage
component when this.state.lat.length && this.state.long.length
are true. MapImage
contains attributes, which are used to pass in the state as props.
After MapImage
receives new props the component renders. This component contains an img
tag, which has a src
attribute set to the Static Maps API endpoint. The response of this endpoint is a 432X300 map of the location from our dataset nearest to the input address.
- Node/Express
- React
- Webpack
- Babel
- Bootstrap
- Mocha/Chai
Set environment variables:
# open the following file
nano ~/.bash_profile
# add the following lines of code to set environment variables
# activate the API and get an API key (get API key from docs referenced in APIs used)
export MAPS_KEY=<insertKey>
export PORT='8080'
# force session to read file
source ~/.bash_profile
Clone repo from github:
# run git clone
git clone https://github.com/juliusbuckley/geo-location.git
Install project dependencies:
# run install script
npm install
Install nodemon for dev environment:
# install nodemon globally
npm install -g nodemon
Start server and transpile with babel-cli:
# run dev start script
npm run dev:start
Transpile server folder and start app:
# run prod start script
npm start
To search for the nearest store just start typing your current location and the input box will update.
After typing in the location press the enter button.
The closest store will appear on a google map along with its address and distance.
Confirm api is working properly and returing Status Code 200
Start server for testing (Make sure server is not running prior to test):
# run test script
npm test
Documentation for: Google -- Geocoding API
Documentation for: Google -- Static Maps API