You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
164 lines
4.8 KiB
164 lines
4.8 KiB
/**
|
|
* LocationPanel Component
|
|
* Displays DE and DX location info with grid squares and sun times
|
|
*/
|
|
import React from 'react';
|
|
import { calculateGridSquare, calculateBearing, calculateDistance, getMoonPhase, getMoonPhaseEmoji } from '../utils/geo.js';
|
|
|
|
export const LocationPanel = ({
|
|
config,
|
|
dxLocation,
|
|
deSunTimes,
|
|
dxSunTimes,
|
|
currentTime
|
|
}) => {
|
|
const deGrid = calculateGridSquare(config.location.lat, config.location.lon);
|
|
const dxGrid = calculateGridSquare(dxLocation.lat, dxLocation.lon);
|
|
const bearing = calculateBearing(config.location.lat, config.location.lon, dxLocation.lat, dxLocation.lon);
|
|
const distance = calculateDistance(config.location.lat, config.location.lon, dxLocation.lat, dxLocation.lon);
|
|
const moonPhase = getMoonPhase(currentTime);
|
|
const moonEmoji = getMoonPhaseEmoji(moonPhase);
|
|
|
|
return (
|
|
<div className="panel" style={{ padding: '12px' }}>
|
|
<div className="panel-header">◎ LOCATIONS</div>
|
|
|
|
{/* DE Location */}
|
|
<div style={{ marginBottom: '12px' }}>
|
|
<div style={{
|
|
display: 'flex',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
marginBottom: '4px'
|
|
}}>
|
|
<span style={{
|
|
color: 'var(--accent-amber)',
|
|
fontWeight: '700',
|
|
fontSize: '14px'
|
|
}}>
|
|
DE: {config.callsign}
|
|
</span>
|
|
<span style={{
|
|
color: 'var(--accent-green)',
|
|
fontFamily: 'JetBrains Mono, monospace',
|
|
fontSize: '12px'
|
|
}}>
|
|
{deGrid}
|
|
</span>
|
|
</div>
|
|
<div style={{
|
|
fontSize: '11px',
|
|
color: 'var(--text-muted)',
|
|
fontFamily: 'JetBrains Mono, monospace'
|
|
}}>
|
|
{config.location.lat.toFixed(4)}°, {config.location.lon.toFixed(4)}°
|
|
</div>
|
|
<div style={{
|
|
fontSize: '11px',
|
|
color: 'var(--text-secondary)',
|
|
marginTop: '4px'
|
|
}}>
|
|
☀ {deSunTimes.sunrise} / {deSunTimes.sunset} UTC
|
|
</div>
|
|
</div>
|
|
|
|
{/* DX Location */}
|
|
<div style={{ marginBottom: '12px' }}>
|
|
<div style={{
|
|
display: 'flex',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
marginBottom: '4px'
|
|
}}>
|
|
<span style={{
|
|
color: 'var(--accent-blue)',
|
|
fontWeight: '700',
|
|
fontSize: '14px'
|
|
}}>
|
|
DX Target
|
|
</span>
|
|
<span style={{
|
|
color: 'var(--accent-green)',
|
|
fontFamily: 'JetBrains Mono, monospace',
|
|
fontSize: '12px'
|
|
}}>
|
|
{dxGrid}
|
|
</span>
|
|
</div>
|
|
<div style={{
|
|
fontSize: '11px',
|
|
color: 'var(--text-muted)',
|
|
fontFamily: 'JetBrains Mono, monospace'
|
|
}}>
|
|
{dxLocation.lat.toFixed(4)}°, {dxLocation.lon.toFixed(4)}°
|
|
</div>
|
|
<div style={{
|
|
fontSize: '11px',
|
|
color: 'var(--text-secondary)',
|
|
marginTop: '4px'
|
|
}}>
|
|
☀ {dxSunTimes.sunrise} / {dxSunTimes.sunset} UTC
|
|
</div>
|
|
</div>
|
|
|
|
{/* Path Info */}
|
|
<div style={{
|
|
padding: '10px',
|
|
background: 'var(--bg-tertiary)',
|
|
borderRadius: '6px',
|
|
marginBottom: '12px'
|
|
}}>
|
|
<div style={{
|
|
display: 'grid',
|
|
gridTemplateColumns: '1fr 1fr',
|
|
gap: '12px',
|
|
textAlign: 'center'
|
|
}}>
|
|
<div>
|
|
<div style={{ fontSize: '10px', color: 'var(--text-muted)' }}>BEARING</div>
|
|
<div style={{
|
|
fontSize: '18px',
|
|
fontWeight: '700',
|
|
color: 'var(--accent-cyan)',
|
|
fontFamily: 'Orbitron, monospace'
|
|
}}>
|
|
{bearing.toFixed(0)}°
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div style={{ fontSize: '10px', color: 'var(--text-muted)' }}>DISTANCE</div>
|
|
<div style={{
|
|
fontSize: '18px',
|
|
fontWeight: '700',
|
|
color: 'var(--accent-cyan)',
|
|
fontFamily: 'Orbitron, monospace'
|
|
}}>
|
|
{distance.toFixed(0)} km
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Moon Phase */}
|
|
<div style={{
|
|
textAlign: 'center',
|
|
padding: '8px',
|
|
background: 'var(--bg-tertiary)',
|
|
borderRadius: '6px'
|
|
}}>
|
|
<span style={{ fontSize: '20px', marginRight: '8px' }}>{moonEmoji}</span>
|
|
<span style={{
|
|
fontSize: '11px',
|
|
color: 'var(--text-secondary)'
|
|
}}>
|
|
{moonPhase < 0.25 ? 'Waxing' : moonPhase < 0.5 ? 'Waxing' : moonPhase < 0.75 ? 'Waning' : 'Waning'}
|
|
{' '}
|
|
{Math.round(moonPhase * 100)}%
|
|
</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default LocationPanel;
|