Skip to content
8 changes: 8 additions & 0 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,11 @@
margin: 0 auto;
max-width: 700px;
}

.people-in-space {
margin-top: 50px;
}

.people-list {
list-style-type: none;
}
11 changes: 9 additions & 2 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import React from 'react';
import React, { useContext } from 'react';
import './App.css';
import ISSLocation from './components/ISSLocation';
import ToggleMap from './components/ToggleMap';
import ISSContext from './context/ISSContext';
import PeopleInSpace from './components/PeopleInSpace';

function App() {
const { showMap } = useContext(ISSContext);

return (
<div className="App">
<h1>International Space Station Location Tracker</h1>
<ISSLocation />
<ToggleMap />
{showMap && <ISSLocation />}
<PeopleInSpace />
</div>
);
}
Expand Down
84 changes: 38 additions & 46 deletions src/components/ISSLocation.js
Original file line number Diff line number Diff line change
@@ -1,54 +1,46 @@
import React, { Component } from 'react';
import React, { useContext, useEffect } from 'react';
import Map from 'pigeon-maps';
import Marker from 'pigeon-marker';

import ISSContext from '../context/ISSContext';

class ISSLocation extends Component {
componentDidMount() {
const { getCurrentISSLocation } = this.context;

this.timer = setInterval(
getCurrentISSLocation,
2000,
);
}

componentWillUnmount() {
clearInterval(this.timer);
}

render() {
const {
error,
isFetching,
latitude,
longitude,
} = this.context;
const isLocationPresent = latitude && longitude;

return (
<div>
<div className="map">
<Map
center={[0, 0]}
defaultWidth={700}
height={450}
minZoom={1}
maxZoom={20}
zoom={1}
>
{!isFetching && isLocationPresent && <Marker anchor={[latitude, longitude]} />}
</Map>
</div>
{isFetching && 'Loading...'}
{!isFetching && isLocationPresent && `Current ISS location: latitude = ${latitude}, longitude = ${longitude}`}
{!isFetching && error}
import useTimer from '../effects/useTimer';

function ISSLocation() {
const {
error,
isFetching,
latitude,
longitude,
getCurrentISSLocation,
} = useContext(ISSContext);
const isLocationPresent = latitude && longitude;

useTimer(getCurrentISSLocation, 2000);

useEffect(() => {
const now = new Date();
document.title = now.toLocaleTimeString();
});

return (
<div>
<div className="map">
<Map
center={[0, 0]}
defaultWidth={700}
height={450}
minZoom={1}
maxZoom={20}
zoom={1}
>
{!isFetching && isLocationPresent && <Marker anchor={[latitude, longitude]} />}
</Map>
</div>
);
}
{isFetching && 'Loading...'}
{!isFetching && isLocationPresent && `Current ISS location: latitude = ${latitude}, longitude = ${longitude}`}
{!isFetching && error}
</div>
);
}

ISSLocation.contextType = ISSContext;

export default ISSLocation;
25 changes: 25 additions & 0 deletions src/components/PeopleInSpace.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React, { useContext } from 'react';

import ISSContext from '../context/ISSContext';
import useTimer from '../effects/useTimer';

const PeopleInSpace = () => {
const { peopleInSpace, getPeopleInSpace } = useContext(ISSContext);

useTimer(getPeopleInSpace, 5000);

if (!peopleInSpace) return null;

return (
<div className="people-in-space">
<span>{`Number of people in space now: ${peopleInSpace.length}`}</span>
<ul className="people-list">
{peopleInSpace.map(({ name }) => (
<li key={name}>{name}</li>
))}
</ul>
</div>
);
};

export default PeopleInSpace;
17 changes: 17 additions & 0 deletions src/components/ToggleMap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React, { useContext } from 'react';
import ISSContext from '../context/ISSContext';

const ToggleMap = () => {
const { showMap, toggleMap } = useContext(ISSContext);

return (
<button
type="button"
onClick={toggleMap}
>
{showMap ? 'Esconder mapa' : 'Mostrar mapa'}
</button>
);
};

export default ToggleMap;
21 changes: 20 additions & 1 deletion src/context/Provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';

import ISSContext from './ISSContext';
import { getCurrentISSLocation } from '../services/issAPI';
import { getCurrentISSLocation, getPeopleInSpace } from '../services/issAPI';

class Provider extends Component {
constructor(props) {
Expand All @@ -12,11 +12,16 @@ class Provider extends Component {
isFetching: false,
latitude: null,
longitude: null,
showMap: true,
peopleInSpace: undefined,
};

this.fetchISSLocation = this.fetchISSLocation.bind(this);
this.handleISSLocationSuccess = this.handleISSLocationSuccess.bind(this);
this.handleISSLocationFailure = this.handleISSLocationFailure.bind(this);
this.handleToggleMap = this.handleToggleMap.bind(this);
this.fetchNumberOfPeopleInSpace = this.fetchNumberOfPeopleInSpace.bind(this);
this.handlePepoleInSpaceSuccess = this.handlePepoleInSpaceSuccess.bind(this);
}

fetchISSLocation() {
Expand All @@ -30,6 +35,10 @@ class Provider extends Component {
.then(this.handleISSLocationSuccess, this.handleISSLocationFailure);
}

fetchNumberOfPeopleInSpace() {
getPeopleInSpace().then(this.handlePepoleInSpaceSuccess);
}

handleISSLocationSuccess(response) {
const { iss_position: { latitude, longitude } } = response;

Expand All @@ -47,10 +56,20 @@ class Provider extends Component {
});
}

handlePepoleInSpaceSuccess(response) {
this.setState({ peopleInSpace: response.people });
}

handleToggleMap() {
this.setState(({ showMap }) => ({ showMap: !showMap }));
}

render() {
const contextValue = {
...this.state,
getCurrentISSLocation: this.fetchISSLocation,
toggleMap: this.handleToggleMap,
getPeopleInSpace: this.fetchNumberOfPeopleInSpace,
};
const { children } = this.props;

Expand Down
18 changes: 18 additions & 0 deletions src/effects/useTimer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useEffect } from 'react';

const useTimer = (func, interval) => {
useEffect(() => {
func();

const timer = setInterval(
func,
interval,
);

return () => {
clearInterval(timer);
};
}, []);
};

export default useTimer;
8 changes: 8 additions & 0 deletions src/services/issAPI.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,12 @@ export const getCurrentISSLocation = () => (
))
);

export const getPeopleInSpace = () => (
fetch(`${ISS_BASE_API}/astros.json`)
.then((response) => (
response.json()
.then((json) => (response.ok ? Promise.resolve(json) : Promise.reject(json)))
))
);

export default getCurrentISSLocation;