diff --git a/src/components/DashboardControls.jsx b/src/components/DashboardControls.jsx new file mode 100644 index 0000000..66999b2 --- /dev/null +++ b/src/components/DashboardControls.jsx @@ -0,0 +1,35 @@ +import { useEffect, useState } from 'react'; + +export default function DashboardControls({ onRefresh }) { + const [intervalTime, setIntervalTime] = useState(null); + + useEffect(() => { + if (intervalTime) { + const id = setInterval(() => { + onRefresh(); + }, intervalTime); + return () => clearInterval(id); + } + }, [intervalTime, onRefresh]); + + return ( +
+ + + +
+ ); +} diff --git a/src/pages/Space.jsx b/src/pages/Space.jsx index 01b38e9..d6a9115 100644 --- a/src/pages/Space.jsx +++ b/src/pages/Space.jsx @@ -2,7 +2,7 @@ * SPACE & ASTRONOMY DASHBOARD TODOs * --------------------------------- * Easy: - * - [ ] Refresh button / auto-refresh interval selector + * - [x] Refresh button / auto-refresh interval selector * - [ ] Show last updated timestamp * - [ ] Style astronauts list with craft grouping * - [ ] Add loading skeleton or placeholder map area @@ -17,11 +17,12 @@ * - [ ] Track path trail (polyline) on map over session * - [ ] Extract map component & custom hook (useIssPosition) */ -import { useEffect, useState, useRef } from 'react'; +import { useEffect, useState } from 'react'; import Loading from '../components/Loading.jsx'; import ErrorMessage from '../components/ErrorMessage.jsx'; import Card from '../components/Card.jsx'; import IssMap from '../components/IssMap.jsx'; +import DashboardControls from "../components/DashboardControls.jsx"; export default function Space() { const [iss, setIss] = useState(null); @@ -29,20 +30,12 @@ export default function Space() { const [error, setError] = useState(null); const [loading, setLoading] = useState(false); const [lastUpdated, setLastUpdated] = useState(null); - const intervalRef = useRef(null); - - useEffect(() => { - fetchData(); - // Poll every 5s for updated ISS position only - intervalRef.current = setInterval(() => { - refreshIssOnly(); - }, 5000); - return () => { if (intervalRef.current) clearInterval(intervalRef.current); }; - }, []); - + + // Fetch both ISS position + crew async function fetchData() { try { - setLoading(true); setError(null); + setLoading(true); + setError(null); const [issRes, crewRes] = await Promise.all([ fetch('http://api.open-notify.org/iss-now.json'), fetch('http://api.open-notify.org/astros.json') @@ -53,38 +46,41 @@ export default function Space() { setIss(issJson); setCrew(crewJson.people || []); setLastUpdated(new Date()); - } catch (e) { setError(e); } finally { setLoading(false); } - } - - async function refreshIssOnly() { - try { - const res = await fetch('http://api.open-notify.org/iss-now.json'); - if (!res.ok) throw new Error('Failed to refresh ISS'); - const issJson = await res.json(); - setIss(issJson); - setLastUpdated(new Date()); } catch (e) { - // don't clobber existing data, but surface error setError(e); + } finally { + setLoading(false); } } -//leaflet map component + + useEffect(() => { + fetchData(); + }, []); + + //leaflet map component return (

Space & Astronomy

+ {loading && } {iss && (

Latitude: {iss.iss_position.latitude}

Longitude: {iss.iss_position.longitude}

- {lastUpdated &&

Last updated: {lastUpdated.toLocaleTimeString()}

} + {lastUpdated && ( +

+ Last updated: {lastUpdated.toLocaleTimeString()} +

+ )}
)}
    - {crew.map(p =>
  • {p.name} — {p.craft}
  • )} + {crew.map(p => ( +
  • {p.name} — {p.craft}
  • + ))}
{/* TODO: Add next ISS pass prediction form */}