Move project from bordanlage/ to repo root
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
37
dashboard/src/components/nav/ChartPlaceholder.jsx
Normal file
37
dashboard/src/components/nav/ChartPlaceholder.jsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import { useNMEA } from '../../hooks/useNMEA.js'
|
||||
|
||||
export default function ChartPlaceholder() {
|
||||
const { lat, lon } = useNMEA()
|
||||
const signalkHost = import.meta.env.VITE_SIGNALK_HOST || 'localhost'
|
||||
|
||||
// SignalK has a built-in chart viewer
|
||||
const chartUrl = `http://${signalkHost}:3000/@signalk/freeboard-sk/`
|
||||
|
||||
return (
|
||||
<div style={styles.container}>
|
||||
<iframe
|
||||
src={chartUrl}
|
||||
style={styles.iframe}
|
||||
title="Chart"
|
||||
onError={() => {}}
|
||||
/>
|
||||
{lat != null && (
|
||||
<div style={styles.coords}>
|
||||
<span style={styles.coord}>{lat.toFixed(5)}°N</span>
|
||||
<span style={styles.coord}>{lon.toFixed(5)}°E</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = {
|
||||
container: { position: 'relative', flex: 1, borderRadius: 'var(--radius)', overflow: 'hidden', border: '1px solid var(--border)' },
|
||||
iframe: { width: '100%', height: '100%', border: 'none', background: 'var(--surface2)' },
|
||||
coords: {
|
||||
position: 'absolute', bottom: 12, left: 12,
|
||||
background: '#07111fcc', borderRadius: 6, padding: '6px 10px',
|
||||
display: 'flex', gap: 12,
|
||||
},
|
||||
coord: { fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--accent)' },
|
||||
}
|
||||
67
dashboard/src/components/nav/InstrumentPanel.jsx
Normal file
67
dashboard/src/components/nav/InstrumentPanel.jsx
Normal file
@@ -0,0 +1,67 @@
|
||||
import { useNMEA } from '../../hooks/useNMEA.js'
|
||||
import Gauge from '../instruments/Gauge.jsx'
|
||||
import Compass from '../instruments/Compass.jsx'
|
||||
import WindRose from '../instruments/WindRose.jsx'
|
||||
|
||||
function DataRow({ label, value, unit }) {
|
||||
return (
|
||||
<div style={styles.row}>
|
||||
<span style={styles.label}>{label}</span>
|
||||
<span style={styles.value}>
|
||||
{value != null ? `${typeof value === 'number' ? value.toFixed(1) : value}` : '—'}
|
||||
{unit && <span style={styles.unit}> {unit}</span>}
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function InstrumentPanel() {
|
||||
const nmea = useNMEA()
|
||||
|
||||
return (
|
||||
<div style={styles.panel}>
|
||||
{/* Gauges row */}
|
||||
<div style={styles.gauges}>
|
||||
<Compass heading={nmea.heading} cog={nmea.cog} />
|
||||
<WindRose windAngle={nmea.windAngle} windSpeed={nmea.windSpeed} />
|
||||
<Gauge value={nmea.depth} min={0} max={30} label="Depth" unit="m" warning={3} danger={1.5} />
|
||||
<Gauge value={nmea.sog} min={0} max={12} label="SOG" unit="kn" />
|
||||
</div>
|
||||
|
||||
{/* Data table */}
|
||||
<div style={styles.table}>
|
||||
<DataRow label="COG" value={nmea.cog != null ? Math.round(nmea.cog) : null} unit="°" />
|
||||
<DataRow label="Heading" value={nmea.heading != null ? Math.round(nmea.heading) : null} unit="°" />
|
||||
<DataRow label="SOG" value={nmea.sog} unit="kn" />
|
||||
<DataRow label="Depth" value={nmea.depth} unit="m" />
|
||||
<DataRow label="Wind Speed" value={nmea.windSpeed} unit="kn" />
|
||||
<DataRow label="Wind Angle" value={nmea.windAngle} unit="°" />
|
||||
<DataRow label="Water Temp" value={nmea.waterTemp} unit="°C" />
|
||||
<DataRow label="Air Temp" value={nmea.airTemp} unit="°C" />
|
||||
<DataRow label="RPM" value={nmea.rpm} unit="" />
|
||||
<DataRow label="Rudder" value={nmea.rudder} unit="°" />
|
||||
<DataRow label="Fuel" value={nmea.fuel} unit="%" />
|
||||
<DataRow label="Lat" value={nmea.lat?.toFixed(5)} unit="°N" />
|
||||
<DataRow label="Lon" value={nmea.lon?.toFixed(5)} unit="°E" />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = {
|
||||
panel: { display: 'flex', flexDirection: 'column', gap: 16 },
|
||||
gauges: { display: 'flex', gap: 8, flexWrap: 'wrap', justifyContent: 'center' },
|
||||
table: {
|
||||
display: 'grid', gridTemplateColumns: '1fr 1fr',
|
||||
gap: '0 24px', background: 'var(--surface)',
|
||||
borderRadius: 'var(--radius)', padding: 16,
|
||||
border: '1px solid var(--border)',
|
||||
},
|
||||
row: {
|
||||
display: 'flex', justifyContent: 'space-between', alignItems: 'center',
|
||||
padding: '7px 0', borderBottom: '1px solid var(--border)',
|
||||
},
|
||||
label: { fontSize: 12, color: 'var(--muted)' },
|
||||
value: { fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text)' },
|
||||
unit: { color: 'var(--muted)', fontSize: 11 },
|
||||
}
|
||||
Reference in New Issue
Block a user