33 * ---------------------------------
44 * Easy:
55 * - [x] Refresh button / auto-refresh interval selector
6- * - [ ] Show last updated timestamp
7- * - [ ] Style astronauts list with craft grouping
6+ * - [x ] Show last updated timestamp
7+ * - [x ] Style astronauts list with craft grouping
88 * - [ ] Add loading skeleton or placeholder map area
99 * Medium:
1010 * - [ ] Integrate Leaflet map w/ marker at ISS coords
@@ -24,13 +24,16 @@ import Card from '../components/Card.jsx';
2424import IssMap from '../components/IssMap.jsx' ;
2525import DashboardControls from "../components/DashboardControls.jsx" ;
2626
27- export default function Space ( ) {
27+
28+ export default function Space ( { theme = 'light' } ) {
2829 const [ iss , setIss ] = useState ( null ) ;
2930 const [ crew , setCrew ] = useState ( [ ] ) ;
3031 const [ error , setError ] = useState ( null ) ;
3132 const [ loading , setLoading ] = useState ( false ) ;
3233 const [ lastUpdated , setLastUpdated ] = useState ( null ) ;
33-
34+
35+ const isDark = theme === 'dark' ;
36+
3437 // Fetch both ISS position + crew
3538 async function fetchData ( ) {
3639 try {
@@ -56,34 +59,177 @@ export default function Space() {
5659 useEffect ( ( ) => {
5760 fetchData ( ) ;
5861 } , [ ] ) ;
59-
60- //leaflet map component
62+
63+ // Proper dark/light theme colors
64+ const bgColor = isDark ? '#0f172a' : '#f8fafc' ;
65+ const textColor = isDark ? '#f1f5f9' : '#1e293b' ;
66+ const cardBg = isDark ? '#1e293b' : '#ffffff' ;
67+ const subText = isDark ? '#94a3b8' : '#64748b' ;
68+ const accent = isDark ? '#38bdf8' : '#2563eb' ;
69+ const listBg = isDark ? '#334155' : '#f1f5f9' ;
70+ const borderColor = isDark ? '#334155' : '#e2e8f0' ;
71+
6172 return (
62- < div >
63- < h2 > Space & Astronomy </ h2 >
64- < DashboardControls onRefresh = { fetchData } />
73+ < div
74+ style = { {
75+ maxWidth : '1000px' ,
76+ margin : '2rem auto' ,
77+ padding : '2rem' ,
78+ backgroundColor : bgColor ,
79+ borderRadius : '16px' ,
80+ boxShadow : isDark
81+ ? '0 4px 10px rgba(0,0,0,0.3)'
82+ : '0 4px 10px rgba(0,0,0,0.08)' ,
83+ color : textColor ,
84+ fontFamily : 'Inter, system-ui, sans-serif' ,
85+ transition : 'background-color 0.3s ease, color 0.3s ease' ,
86+ border : isDark ? '1px solid #334155' : 'none' ,
87+ } }
88+ >
89+ < h2
90+ style = { {
91+ textAlign : 'center' ,
92+ marginBottom : '1.8rem' ,
93+ fontSize : '2rem' ,
94+ fontWeight : '600' ,
95+ color : accent ,
96+ letterSpacing : '0.5px' ,
97+ } }
98+ >
99+ 🌌 Space & Astronomy Dashboard
100+ </ h2 >
101+
102+ < div style = { { display : 'flex' , justifyContent : 'center' , marginBottom : '1.5rem' } } >
103+ < DashboardControls onRefresh = { fetchData } />
104+ </ div >
105+
65106 { loading && < Loading /> }
66107 < ErrorMessage error = { error } />
67- { iss && (
68- < Card title = "ISS Current Location" >
69- < p > Latitude: { iss . iss_position . latitude } </ p >
70- < p > Longitude: { iss . iss_position . longitude } </ p >
71- { lastUpdated && (
72- < p style = { { fontSize : '0.8rem' , color : '#666' } } >
73- Last updated: { lastUpdated . toLocaleTimeString ( ) }
74- </ p >
75- ) }
76- < IssMap latitude = { iss . iss_position . latitude } longitude = { iss . iss_position . longitude } />
108+
109+ < div
110+ style = { {
111+ display : 'flex' ,
112+ flexDirection : 'column' ,
113+ gap : '1.5rem' ,
114+ justifyContent : 'center' ,
115+ } }
116+ >
117+ { iss && (
118+ < Card
119+ title = "🛰️ ISS Current Location"
120+ style = { {
121+ backgroundColor : cardBg ,
122+ borderRadius : '12px' ,
123+ padding : '1.5rem' ,
124+ boxShadow : isDark
125+ ? '0 2px 8px rgba(0,0,0,0.2)'
126+ : '0 2px 8px rgba(0,0,0,0.05)' ,
127+ transition : 'all 0.3s ease' ,
128+ border : `1px solid ${ borderColor } ` ,
129+ } }
130+ >
131+ < div style = { { lineHeight : '1.6' } } >
132+ < p style = { { color : textColor , margin : '0.5rem 0' } } >
133+ < strong > Latitude:</ strong > { iss . iss_position . latitude }
134+ </ p >
135+ < p style = { { color : textColor , margin : '0.5rem 0' } } >
136+ < strong > Longitude:</ strong > { iss . iss_position . longitude }
137+ </ p >
138+ { lastUpdated && (
139+ < p style = { { fontSize : '0.9rem' , color : subText , margin : '0.5rem 0' } } >
140+ Last updated: { lastUpdated . toLocaleTimeString ( ) }
141+ </ p >
142+ ) }
143+ </ div >
144+
145+ < div style = { { marginTop : '1rem' } } >
146+ < IssMap
147+ latitude = { iss . iss_position . latitude }
148+ longitude = { iss . iss_position . longitude }
149+ />
150+ </ div >
151+ </ Card >
152+ ) }
153+
154+ < Card
155+ title = { `👩🚀 Astronauts in Space (${ crew . length } )` }
156+ style = { {
157+ backgroundColor : cardBg ,
158+ borderRadius : '12px' ,
159+ padding : '1.5rem' ,
160+ boxShadow : isDark
161+ ? '0 2px 8px rgba(0,0,0,0.2)'
162+ : '0 2px 8px rgba(0,0,0,0.05)' ,
163+ transition : 'all 0.3s ease' ,
164+ border : `1px solid ${ borderColor } ` ,
165+ } }
166+ >
167+ < ul style = { {
168+ paddingLeft : '0' ,
169+ listStyleType : 'none' ,
170+ margin : '0' ,
171+ display : 'flex' ,
172+ flexDirection : 'column' ,
173+ gap : '0.5rem'
174+ } } >
175+ { crew . map ( ( p ) => (
176+ < li
177+ key = { p . name }
178+ style = { {
179+ backgroundColor : listBg ,
180+ padding : '0.75rem 1rem' ,
181+ borderRadius : '8px' ,
182+ display : 'flex' ,
183+ justifyContent : 'space-between' ,
184+ alignItems : 'center' ,
185+ transition : 'all 0.3s ease' ,
186+ border : `1px solid ${ borderColor } ` ,
187+ } }
188+ >
189+ < span style = { {
190+ fontWeight : '500' ,
191+ color : textColor
192+ } } >
193+ { p . name }
194+ </ span >
195+ < span style = { {
196+ fontSize : '0.9rem' ,
197+ color : subText ,
198+ backgroundColor : isDark ? '#475569' : '#e2e8f0' ,
199+ padding : '0.25rem 0.75rem' ,
200+ borderRadius : '6px' ,
201+ fontWeight : '500'
202+ } } >
203+ 🚀 { p . craft }
204+ </ span >
205+ </ li >
206+ ) ) }
207+ </ ul >
77208 </ Card >
78- ) }
79- < Card title = { `Astronauts in Space (${ crew . length } )` } >
80- < ul >
81- { crew . map ( p => (
82- < li key = { p . name } > { p . name } — { p . craft } </ li >
83- ) ) }
84- </ ul >
85- </ Card >
86- { /* TODO: Add next ISS pass prediction form */ }
209+ </ div >
210+
211+ < p
212+ style = { {
213+ marginTop : '2rem' ,
214+ textAlign : 'center' ,
215+ fontSize : '0.9rem' ,
216+ color : subText ,
217+ } }
218+ >
219+ Data sourced from{ ' ' }
220+ < a
221+ href = "http://api.open-notify.org"
222+ style = { {
223+ color : accent ,
224+ textDecoration : 'none' ,
225+ fontWeight : '500' ,
226+ } }
227+ onMouseEnter = { ( e ) => e . target . style . textDecoration = 'underline' }
228+ onMouseLeave = { ( e ) => e . target . style . textDecoration = 'none' }
229+ >
230+ Open Notify API
231+ </ a >
232+ </ p >
87233 </ div >
88234 ) ;
89- }
235+ }
0 commit comments