78 lines
2.4 KiB
JavaScript
78 lines
2.4 KiB
JavaScript
import { useState } from 'react'
|
|
import { useNMEA } from '../../hooks/useNMEA.js'
|
|
|
|
const isDev = import.meta.env.DEV
|
|
|
|
function formatTime() {
|
|
return new Date().toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' })
|
|
}
|
|
|
|
export default function TopBar() {
|
|
const { sog, heading, connected } = useNMEA()
|
|
const [time, setTime] = useState(formatTime())
|
|
|
|
// Clock tick
|
|
useState(() => {
|
|
const t = setInterval(() => setTime(formatTime()), 5000)
|
|
return () => clearInterval(t)
|
|
})
|
|
|
|
return (
|
|
<header style={styles.bar}>
|
|
<div style={styles.left}>
|
|
<span style={styles.logo}>⚓ Bordanlage</span>
|
|
{isDev && <span style={styles.devBadge}>DEV · MOCK DATA</span>}
|
|
</div>
|
|
|
|
<div style={styles.center}>
|
|
{connected && sog != null && (
|
|
<span style={styles.stat}>
|
|
<span style={styles.val}>{sog.toFixed(1)}</span>
|
|
<span style={styles.unit}>kn</span>
|
|
</span>
|
|
)}
|
|
{connected && heading != null && (
|
|
<span style={styles.stat}>
|
|
<span style={styles.val}>{Math.round(heading)}°</span>
|
|
<span style={styles.unit}>HDG</span>
|
|
</span>
|
|
)}
|
|
{!connected && (
|
|
<span style={{ color: 'var(--muted)', fontSize: 13 }}>No signal</span>
|
|
)}
|
|
</div>
|
|
|
|
<div style={styles.right}>
|
|
<span style={styles.time}>{time}</span>
|
|
</div>
|
|
</header>
|
|
)
|
|
}
|
|
|
|
const styles = {
|
|
bar: {
|
|
height: 52,
|
|
background: 'var(--surface)',
|
|
borderBottom: '1px solid var(--border)',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
padding: '0 16px',
|
|
gap: 16,
|
|
flexShrink: 0,
|
|
},
|
|
left: { display: 'flex', alignItems: 'center', gap: 10, flex: 1 },
|
|
center: { display: 'flex', gap: 20, alignItems: 'center' },
|
|
right: { flex: 1, display: 'flex', justifyContent: 'flex-end' },
|
|
logo: { fontWeight: 700, fontSize: 15, color: 'var(--accent)', letterSpacing: '0.04em' },
|
|
devBadge: {
|
|
fontSize: 10, fontWeight: 600, padding: '2px 7px',
|
|
background: '#f59e0b22', color: 'var(--warning)',
|
|
border: '1px solid var(--warning)', borderRadius: 4,
|
|
letterSpacing: '0.06em',
|
|
},
|
|
stat: { display: 'flex', alignItems: 'baseline', gap: 3 },
|
|
val: { fontFamily: 'var(--font-mono)', fontSize: 16, color: 'var(--text)' },
|
|
unit: { fontSize: 10, color: 'var(--muted)' },
|
|
time: { fontFamily: 'var(--font-mono)', fontSize: 14, color: 'var(--muted)' },
|
|
}
|