22 * SPACE & ASTRONOMY DASHBOARD TODOs
33 * ---------------------------------
44 * Easy:
5- * - [ ] Refresh button / auto-refresh interval selector
5+ * - [x ] Refresh button / auto-refresh interval selector
66 * - [ ] Show last updated timestamp
77 * - [ ] Style astronauts list with craft grouping
88 * - [ ] Add loading skeleton or placeholder map area
1717 * - [ ] Track path trail (polyline) on map over session
1818 * - [ ] Extract map component & custom hook (useIssPosition)
1919 */
20- import { useEffect , useState , useRef } from 'react' ;
20+ import { useEffect , useState } from 'react' ;
2121import Loading from '../components/Loading.jsx' ;
2222import ErrorMessage from '../components/ErrorMessage.jsx' ;
2323import Card from '../components/Card.jsx' ;
2424import IssMap from '../components/IssMap.jsx' ;
25+ import DashboardControls from "../components/DashboardControls.jsx" ;
2526
2627export default function Space ( ) {
2728 const [ iss , setIss ] = useState ( null ) ;
2829 const [ crew , setCrew ] = useState ( [ ] ) ;
2930 const [ error , setError ] = useState ( null ) ;
3031 const [ loading , setLoading ] = useState ( false ) ;
3132 const [ lastUpdated , setLastUpdated ] = useState ( null ) ;
32- const intervalRef = useRef ( null ) ;
33-
34- useEffect ( ( ) => {
35- fetchData ( ) ;
36- // Poll every 5s for updated ISS position only
37- intervalRef . current = setInterval ( ( ) => {
38- refreshIssOnly ( ) ;
39- } , 5000 ) ;
40- return ( ) => { if ( intervalRef . current ) clearInterval ( intervalRef . current ) ; } ;
41- } , [ ] ) ;
42-
33+
34+ // Fetch both ISS position + crew
4335 async function fetchData ( ) {
4436 try {
45- setLoading ( true ) ; setError ( null ) ;
37+ setLoading ( true ) ;
38+ setError ( null ) ;
4639 const [ issRes , crewRes ] = await Promise . all ( [
4740 fetch ( 'http://api.open-notify.org/iss-now.json' ) ,
4841 fetch ( 'http://api.open-notify.org/astros.json' )
@@ -53,38 +46,41 @@ export default function Space() {
5346 setIss ( issJson ) ;
5447 setCrew ( crewJson . people || [ ] ) ;
5548 setLastUpdated ( new Date ( ) ) ;
56- } catch ( e ) { setError ( e ) ; } finally { setLoading ( false ) ; }
57- }
58-
59- async function refreshIssOnly ( ) {
60- try {
61- const res = await fetch ( 'http://api.open-notify.org/iss-now.json' ) ;
62- if ( ! res . ok ) throw new Error ( 'Failed to refresh ISS' ) ;
63- const issJson = await res . json ( ) ;
64- setIss ( issJson ) ;
65- setLastUpdated ( new Date ( ) ) ;
6649 } catch ( e ) {
67- // don't clobber existing data, but surface error
6850 setError ( e ) ;
51+ } finally {
52+ setLoading ( false ) ;
6953 }
7054 }
71- //leaflet map component
55+
56+ useEffect ( ( ) => {
57+ fetchData ( ) ;
58+ } , [ ] ) ;
59+
60+ //leaflet map component
7261 return (
7362 < div >
7463 < h2 > Space & Astronomy </ h2 >
64+ < DashboardControls onRefresh = { fetchData } />
7565 { loading && < Loading /> }
7666 < ErrorMessage error = { error } />
7767 { iss && (
7868 < Card title = "ISS Current Location" >
7969 < p > Latitude: { iss . iss_position . latitude } </ p >
8070 < p > Longitude: { iss . iss_position . longitude } </ p >
81- { lastUpdated && < p style = { { fontSize : '0.8rem' , color : '#666' } } > Last updated: { lastUpdated . toLocaleTimeString ( ) } </ p > }
71+ { lastUpdated && (
72+ < p style = { { fontSize : '0.8rem' , color : '#666' } } >
73+ Last updated: { lastUpdated . toLocaleTimeString ( ) }
74+ </ p >
75+ ) }
8276 < IssMap latitude = { iss . iss_position . latitude } longitude = { iss . iss_position . longitude } />
8377 </ Card >
8478 ) }
8579 < Card title = { `Astronauts in Space (${ crew . length } )` } >
8680 < ul >
87- { crew . map ( p => < li key = { p . name } > { p . name } — { p . craft } </ li > ) }
81+ { crew . map ( p => (
82+ < li key = { p . name } > { p . name } — { p . craft } </ li >
83+ ) ) }
8884 </ ul >
8985 </ Card >
9086 { /* TODO: Add next ISS pass prediction form */ }
0 commit comments