GPS Geschwindigkeitsanzeige
This commit is contained in:
@@ -18,6 +18,13 @@ type StatusBarProps = {
|
||||
} | null;
|
||||
};
|
||||
|
||||
type StatusItemData = {
|
||||
icon?: ReactNode;
|
||||
label: string;
|
||||
value: string;
|
||||
speed?: boolean;
|
||||
};
|
||||
|
||||
export function StatusBar({
|
||||
gps,
|
||||
forecast,
|
||||
@@ -39,7 +46,7 @@ export function StatusBar({
|
||||
? "Position aktiv"
|
||||
: `±${gps.accuracyM} m`
|
||||
: gpsStatusLabel(gps.status);
|
||||
const speedValue = gps.speedKn === null ? "-- kn" : `${gps.speedKn.toFixed(1)} kn`;
|
||||
const speedValue = formatGpsSpeed(gps.speedKn);
|
||||
const tideValue = tide?.nextHigh
|
||||
? `HW ${new Date(tide.nextHigh.time).toLocaleTimeString("de-DE", {
|
||||
hour: "2-digit",
|
||||
@@ -48,7 +55,7 @@ export function StatusBar({
|
||||
: "Keine Daten";
|
||||
const conditionsValue = formatConditions(forecast);
|
||||
|
||||
const items =
|
||||
const items: StatusItemData[] =
|
||||
resolvedMode === "anchor"
|
||||
? [
|
||||
{
|
||||
@@ -95,9 +102,9 @@ export function StatusBar({
|
||||
value: `${routeWarningCount} offen`
|
||||
}
|
||||
: {
|
||||
icon: <Activity size={15} aria-hidden="true" />,
|
||||
label: "SOG",
|
||||
value: speedValue
|
||||
icon: <Navigation2 size={15} aria-hidden="true" />,
|
||||
label: "GPS",
|
||||
value: gpsValue
|
||||
}
|
||||
]
|
||||
: resolvedMode === "route"
|
||||
@@ -115,17 +122,11 @@ export function StatusBar({
|
||||
label: "GPS",
|
||||
value: gpsValue
|
||||
},
|
||||
gps.position
|
||||
? {
|
||||
icon: <Activity size={15} aria-hidden="true" />,
|
||||
label: "SOG",
|
||||
value: speedValue
|
||||
}
|
||||
: {
|
||||
icon: <Waves size={15} aria-hidden="true" />,
|
||||
label: "Tide",
|
||||
value: tideValue
|
||||
}
|
||||
{
|
||||
icon: <Waves size={15} aria-hidden="true" />,
|
||||
label: "Tide",
|
||||
value: tideValue
|
||||
}
|
||||
]
|
||||
: [
|
||||
{
|
||||
@@ -144,23 +145,44 @@ export function StatusBar({
|
||||
value: tideValue
|
||||
}
|
||||
];
|
||||
const statusItems: StatusItemData[] = [
|
||||
...items,
|
||||
{
|
||||
icon: <Activity size={15} aria-hidden="true" />,
|
||||
label: "GPS-Geschwindigkeit",
|
||||
value: speedValue,
|
||||
speed: true
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<footer
|
||||
className="status-bar"
|
||||
aria-label="Navigationsstatus"
|
||||
style={{ gridTemplateColumns: "repeat(3, minmax(0, 1fr))" }}
|
||||
>
|
||||
{items.map((item) => (
|
||||
<StatusItem key={item.label} icon={item.icon} label={item.label} value={item.value} />
|
||||
<footer className="status-bar" aria-label="Navigationsstatus">
|
||||
{statusItems.map((item) => (
|
||||
<StatusItem
|
||||
key={item.label}
|
||||
icon={item.icon}
|
||||
label={item.label}
|
||||
value={item.value}
|
||||
speed={item.speed}
|
||||
/>
|
||||
))}
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
|
||||
function StatusItem({ icon, label, value }: { icon?: ReactNode; label: string; value: string }) {
|
||||
function StatusItem({
|
||||
icon,
|
||||
label,
|
||||
value,
|
||||
speed = false
|
||||
}: {
|
||||
icon?: ReactNode;
|
||||
label: string;
|
||||
value: string;
|
||||
speed?: boolean;
|
||||
}) {
|
||||
return (
|
||||
<span className="status-item">
|
||||
<span className="status-item" data-kind={speed ? "speed" : undefined}>
|
||||
{icon}
|
||||
<span className="status-label">{label}</span>
|
||||
<strong>{value}</strong>
|
||||
@@ -168,6 +190,14 @@ function StatusItem({ icon, label, value }: { icon?: ReactNode; label: string; v
|
||||
);
|
||||
}
|
||||
|
||||
function formatGpsSpeed(speedKn: number | null): string {
|
||||
if (speedKn === null || !Number.isFinite(speedKn) || speedKn < 0) {
|
||||
return "-- km/h · -- kn";
|
||||
}
|
||||
const format = (value: number) => value.toFixed(1).replace(".", ",");
|
||||
return `${format(speedKn * 1.852)} km/h · ${format(speedKn)} kn`;
|
||||
}
|
||||
|
||||
function gpsStatusLabel(status: GpsState["status"]): string {
|
||||
switch (status) {
|
||||
case "idle":
|
||||
|
||||
@@ -1128,7 +1128,7 @@ button:disabled {
|
||||
|
||||
.route-weather-metrics {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr)) minmax(118px, 1.35fr);
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
@@ -1681,6 +1681,11 @@ button:disabled {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.status-item[data-kind="speed"] strong {
|
||||
overflow: visible;
|
||||
text-overflow: clip;
|
||||
}
|
||||
|
||||
.status-label {
|
||||
grid-column: 2;
|
||||
font-size: 10px;
|
||||
@@ -1778,7 +1783,7 @@ button:disabled {
|
||||
}
|
||||
|
||||
.status-bar {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr)) minmax(118px, 1.35fr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user