Paritaetsrunden 2 und 3, Designpruefung umgesetzt (2026.8.30.8)

Drei zusammenhaengende Runden, alle live bei 375x812 gegen audi_ha_test
geprueft und in beiden Codebasen angewandt.

Paritaetsrunde 2: der gemeinsame Rahmen war das eigentliche Problem -
Seitenrand, Kachelabstaende, Kopfleiste, Tableiste und vier Bausteine des
Design-Systems trugen noch den Stand vor der iOS-Entscheidung. Dazu sieben
Bildschirme neu aufgebaut. Zwei Panel-Fehler dabei mitbehoben: teaser()
zeigte unter "Letzte Fahrt" den aeltesten Datensatz, und "Daten bearbeiten"
war ein toter Knopf.

Paritaetsrunde 3: das Panel hat nie Audi Type gerendert. @font-face in einem
Shadow Root wird ignoriert - Schriftschnitte registriert der Browser pro
Dokument, nie pro Shadow Tree. Die drei Schnitte liegen jetzt in
audi-dashboard-schriften.css und werden ins Dokument gehaengt. Damit erledigt
sich eine ganze Reihe von "die Schrift sieht anders aus"-Eindruecken: die
beiden Anwendungen zeigten tatsaechlich verschiedene Schriften.
Ausserdem "Daten bearbeiten" im Panel gebaut und portiert, das Zeilenmenue
entfernt und die letzten neun Bildschirme angeglichen.

Designpruefung: die fuenf Punkte der Reihenfolge. Beim vierten hat das Messen
den Befund veraendert - gezaehlt waren die deklarierten Groessen, wirksam war
laengst eine saubere Sieben-Schritt-Skala mit 27 Ausreissern; die sind jetzt
auf den naechsten Schritt gezogen, keiner verschiebt sich um mehr als 1px.

Zuletzt: die Standortvorschau zeichnete die falsche Nadel (das Panel wechselt
den Icon-Satz ab 34px, die App nahm immer den grossen), und der Kopfabstand
der App ist auf den sicheren Bereich reduziert - die 56px des Panels liegen
dort unter der Kopfleiste von Home Assistant, in der nativen Huelle steht
darueber nichts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-30 18:31:41 +02:00
parent 25c0d073c4
commit 4a58021670
64 changed files with 4130 additions and 1432 deletions
+41 -8
View File
@@ -14,9 +14,14 @@ export function eur(wert: number | null | undefined): string {
return de(wert, 2)
}
/** Wie de(), aber „—" statt „0" wenn nichts bekannt ist. */
/* Fehlende Werte zeigt das Panel durchgängig als Halbgeviertstrich „–", nicht
als Geviertstrich „—" (30 Fundstellen gegen eine). Hier stand app-weit der
längere Strich — sichtbar breiter, sobald beide Anwendungen nebeneinander
liegen. */
/** Wie de(), aber „–" statt „0" wenn nichts bekannt ist. */
export function deOderStrich(wert: number | null | undefined, nachkomma = 0): string {
return wert === null || wert === undefined ? "" : de(wert, nachkomma)
return wert === null || wert === undefined ? "" : de(wert, nachkomma)
}
/** Summe über eine Liste. */
@@ -61,32 +66,32 @@ function alsDatum(wert: string | number | Date | null | undefined): Date | null
export function datum(wert: string | number | Date | null | undefined): string {
const d = alsDatum(wert)
return d ? DATUM_KURZ.format(d) : ""
return d ? DATUM_KURZ.format(d) : ""
}
export function datumLang(wert: string | number | Date | null | undefined): string {
const d = alsDatum(wert)
return d ? DATUM_LANG.format(d) : ""
return d ? DATUM_LANG.format(d) : ""
}
export function uhrzeit(wert: string | number | Date | null | undefined): string {
const d = alsDatum(wert)
return d ? UHRZEIT.format(d) : ""
return d ? UHRZEIT.format(d) : ""
}
export function datumZeit(wert: string | number | Date | null | undefined): string {
const d = alsDatum(wert)
return d ? `${DATUM_KURZ.format(d)}, ${UHRZEIT.format(d)} Uhr` : ""
return d ? `${DATUM_KURZ.format(d)}, ${UHRZEIT.format(d)} Uhr` : ""
}
export function monatJahr(wert: string | number | Date | null | undefined): string {
const d = alsDatum(wert)
return d ? MONAT_JAHR.format(d) : ""
return d ? MONAT_JAHR.format(d) : ""
}
/** Dauer in Sekunden als „2 h 14 min" bzw. „14 min". */
export function dauer(sekunden: number | null | undefined): string {
if (!sekunden || sekunden <= 0) return ""
if (!sekunden || sekunden <= 0) return ""
const minutenGesamt = Math.round(sekunden / 60)
const stunden = Math.floor(minutenGesamt / 60)
const minuten = minutenGesamt % 60
@@ -94,6 +99,23 @@ export function dauer(sekunden: number | null | undefined): string {
return `${stunden} h ${String(minuten).padStart(2, "0")} min`
}
/**
* Alter des letzten Datenstands als „vor 3 Std." — wortgleich mit
* `standAlterText()` im Panel, das diesen Text in der Kopfzeile der Übersicht
* neben dem Aktualisieren-Symbol zeigt.
*/
export function standAlter(wert: string | number | Date | null | undefined): string {
const d = alsDatum(wert)
if (!d) return "unbekannt"
const sekunden = Math.max(0, Math.floor((Date.now() - d.getTime()) / 1000))
if (sekunden < 60) return `vor ${sekunden} Sek.`
const minuten = Math.floor(sekunden / 60)
if (minuten < 60) return `vor ${minuten} Min.`
const stunden = Math.floor(minuten / 60)
if (stunden < 24) return `vor ${stunden} Std.`
return `vor ${Math.floor(stunden / 24)} Tage`
}
/** ISO-Tagesdatum (YYYY-MM-DD) für Vergleiche und Eingabefelder. */
export function isoTag(wert: string | number | Date | null | undefined = new Date()): string {
const d = alsDatum(wert)
@@ -101,3 +123,14 @@ export function isoTag(wert: string | number | Date | null | undefined = new Dat
const versatz = d.getTimezoneOffset() * 60_000
return new Date(d.getTime() - versatz).toISOString().slice(0, 10)
}
/**
* Datum und Uhrzeit mit „ · " getrennt — so setzt das Panel den Zeitstempel in
* der Batterie-Messwertliste (`dedat(...) + " · " + toLocaleTimeString(...)`).
* `datumZeit()` daneben bleibt die Komma-Schreibweise für die Stellen, die sie
* schon benutzen.
*/
export function datumUndZeit(wert: string | number | Date | null | undefined): string {
const d = alsDatum(wert)
return d ? `${DATUM_KURZ.format(d)} · ${UHRZEIT.format(d)} Uhr` : ""
}