Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export default function App() {
<Route path="/" element={<Home />} />
<Route path="/weather" element={<Weather />} />
<Route path="/crypto" element={<Crypto />} />
<Route path="/space" element={<Space />} />
<Route path="/space" element={<Space theme={theme} />} />
<Route path="/movies" element={<Movies />} />
<Route path="/recipes" element={<Recipes />} />
<Route path="/trivia" element={<Trivia />} />
Expand Down
204 changes: 175 additions & 29 deletions src/pages/Space.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
* ---------------------------------
* Easy:
* - [x] Refresh button / auto-refresh interval selector
* - [ ] Show last updated timestamp
* - [ ] Style astronauts list with craft grouping
* - [x] Show last updated timestamp
* - [x] Style astronauts list with craft grouping
* - [ ] Add loading skeleton or placeholder map area
* Medium:
* - [ ] Integrate Leaflet map w/ marker at ISS coords
Expand All @@ -24,13 +24,16 @@ import Card from '../components/Card.jsx';
import IssMap from '../components/IssMap.jsx';
import DashboardControls from "../components/DashboardControls.jsx";

export default function Space() {

export default function Space({ theme = 'light' }) {
const [iss, setIss] = useState(null);
const [crew, setCrew] = useState([]);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(false);
const [lastUpdated, setLastUpdated] = useState(null);


const isDark = theme === 'dark';

// Fetch both ISS position + crew
async function fetchData() {
try {
Expand All @@ -56,34 +59,177 @@ export default function Space() {
useEffect(() => {
fetchData();
}, []);

//leaflet map component

// Proper dark/light theme colors
const bgColor = isDark ? '#0f172a' : '#f8fafc';
const textColor = isDark ? '#f1f5f9' : '#1e293b';
const cardBg = isDark ? '#1e293b' : '#ffffff';
const subText = isDark ? '#94a3b8' : '#64748b';
const accent = isDark ? '#38bdf8' : '#2563eb';
const listBg = isDark ? '#334155' : '#f1f5f9';
const borderColor = isDark ? '#334155' : '#e2e8f0';

return (
<div>
<h2>Space & Astronomy</h2>
<DashboardControls onRefresh={fetchData} />
<div
style={{
maxWidth: '1000px',
margin: '2rem auto',
padding: '2rem',
backgroundColor: bgColor,
borderRadius: '16px',
boxShadow: isDark
? '0 4px 10px rgba(0,0,0,0.3)'
: '0 4px 10px rgba(0,0,0,0.08)',
color: textColor,
fontFamily: 'Inter, system-ui, sans-serif',
transition: 'background-color 0.3s ease, color 0.3s ease',
border: isDark ? '1px solid #334155' : 'none',
}}
>
<h2
style={{
textAlign: 'center',
marginBottom: '1.8rem',
fontSize: '2rem',
fontWeight: '600',
color: accent,
letterSpacing: '0.5px',
}}
>
🌌 Space & Astronomy Dashboard
</h2>

<div style={{ display: 'flex', justifyContent: 'center', marginBottom: '1.5rem' }}>
<DashboardControls onRefresh={fetchData} />
</div>

{loading && <Loading />}
<ErrorMessage error={error} />
{iss && (
<Card title="ISS Current Location">
<p>Latitude: {iss.iss_position.latitude}</p>
<p>Longitude: {iss.iss_position.longitude}</p>
{lastUpdated && (
<p style={{ fontSize: '0.8rem', color: '#666' }}>
Last updated: {lastUpdated.toLocaleTimeString()}
</p>
)}
<IssMap latitude={iss.iss_position.latitude} longitude={iss.iss_position.longitude} />

<div
style={{
display: 'flex',
flexDirection: 'column',
gap: '1.5rem',
justifyContent: 'center',
}}
>
{iss && (
<Card
title="🛰️ ISS Current Location"
style={{
backgroundColor: cardBg,
borderRadius: '12px',
padding: '1.5rem',
boxShadow: isDark
? '0 2px 8px rgba(0,0,0,0.2)'
: '0 2px 8px rgba(0,0,0,0.05)',
transition: 'all 0.3s ease',
border: `1px solid ${borderColor}`,
}}
>
<div style={{ lineHeight: '1.6' }}>
<p style={{ color: textColor, margin: '0.5rem 0' }}>
<strong>Latitude:</strong> {iss.iss_position.latitude}
</p>
<p style={{ color: textColor, margin: '0.5rem 0' }}>
<strong>Longitude:</strong> {iss.iss_position.longitude}
</p>
{lastUpdated && (
<p style={{ fontSize: '0.9rem', color: subText, margin: '0.5rem 0' }}>
Last updated: {lastUpdated.toLocaleTimeString()}
</p>
)}
</div>

<div style={{ marginTop: '1rem' }}>
<IssMap
latitude={iss.iss_position.latitude}
longitude={iss.iss_position.longitude}
/>
</div>
</Card>
)}

<Card
title={`👩‍🚀 Astronauts in Space (${crew.length})`}
style={{
backgroundColor: cardBg,
borderRadius: '12px',
padding: '1.5rem',
boxShadow: isDark
? '0 2px 8px rgba(0,0,0,0.2)'
: '0 2px 8px rgba(0,0,0,0.05)',
transition: 'all 0.3s ease',
border: `1px solid ${borderColor}`,
}}
>
<ul style={{
paddingLeft: '0',
listStyleType: 'none',
margin: '0',
display: 'flex',
flexDirection: 'column',
gap: '0.5rem'
}}>
{crew.map((p) => (
<li
key={p.name}
style={{
backgroundColor: listBg,
padding: '0.75rem 1rem',
borderRadius: '8px',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
transition: 'all 0.3s ease',
border: `1px solid ${borderColor}`,
}}
>
<span style={{
fontWeight: '500',
color: textColor
}}>
{p.name}
</span>
<span style={{
fontSize: '0.9rem',
color: subText,
backgroundColor: isDark ? '#475569' : '#e2e8f0',
padding: '0.25rem 0.75rem',
borderRadius: '6px',
fontWeight: '500'
}}>
🚀 {p.craft}
</span>
</li>
))}
</ul>
</Card>
)}
<Card title={`Astronauts in Space (${crew.length})`}>
<ul>
{crew.map(p => (
<li key={p.name}>{p.name} — {p.craft}</li>
))}
</ul>
</Card>
{/* TODO: Add next ISS pass prediction form */}
</div>

<p
style={{
marginTop: '2rem',
textAlign: 'center',
fontSize: '0.9rem',
color: subText,
}}
>
Data sourced from{' '}
<a
href="http://api.open-notify.org"
style={{
color: accent,
textDecoration: 'none',
fontWeight: '500',
}}
onMouseEnter={(e) => e.target.style.textDecoration = 'underline'}
onMouseLeave={(e) => e.target.style.textDecoration = 'none'}
>
Open Notify API
</a>
</p>
</div>
);
}
}
Loading