Phase 7a: Uebersicht, Fahrzeugstatus und Mein Audi

Erste drei Screens auf der fertigen Datenschicht. Uebersicht mit Fahrzeugbild,
Sicherungsstatus, Reichweite und Tankfuellstand, Kilometerstand samt
Service-Faelligkeit und Vorschau auf letzte Fahrt und Tankung. Fahrzeugstatus
zeigt die 16 Einzelpruefungen, wobei ein unbekannter Sensor als hohler Ring
erscheint statt als gruen geratener Punkt - dieselbe Vorsicht, die schon das
Backend walten laesst. Mein Audi buendelt Fotogalerie und Wege zu den
Unterseiten.

Dazu die geteilte Rechenlogik der Statistik portiert (Zeitraeume,
Langzeitverbrauch mit Plausibilitaetsfenster, Gruppierung nach Jahr und
Monat) und Formatierung im deutschen Format.

Bild-Komponente kapselt eine Reibung zwischen App und Bibliothek: die App
laeuft mit exactOptionalPropertyTypes, ein undefined an einem optionalen Prop
waere sonst an jeder Aufrufstelle einzeln zu behandeln.
This commit is contained in:
Paul Nothaft
2026-08-11 11:07:03 +02:00
parent 0103508cea
commit 4dbf3cb173
12 changed files with 1003 additions and 4 deletions
+49
View File
@@ -0,0 +1,49 @@
/**
* Fahrzeugfotos. Die Dateinamen sind fest: `bilderverwaltung.py` prüft jeden
* Upload gegen eine Positivliste und lehnt alles andere ab — hier steht
* dieselbe Liste, damit die Oberfläche gar nicht erst etwas anbieten kann,
* das der Server ablehnen würde.
*/
import { zugangLesenSynchron } from "./zugang"
export interface Bildplatz {
name: string
beschreibung: string
datei: string
}
/** Die sieben Plätze der Fotogalerie unter „Mein Audi". */
export const BILDPLAETZE: Bildplatz[] = [
{ name: "Seitenansicht", beschreibung: "Auto von der Seite", datei: "seitenansicht.webp" },
{ name: "Front schräg", beschreibung: "Auto von vorn schräg", datei: "front-schraeg.webp" },
{ name: "Frontansicht", beschreibung: "Auto von vorn", datei: "frontansicht.webp" },
{ name: "Heckansicht", beschreibung: "Auto von hinten", datei: "heckansicht.webp" },
{ name: "Cockpit", beschreibung: "Innenraum Cockpit", datei: "cockpit.webp" },
{ name: "Scheinwerfer", beschreibung: "Scheinwerfer", datei: "scheinwerfer.webp" },
{ name: "Sitze", beschreibung: "Innenraum Sitze", datei: "sitze.webp" },
]
/** Zusätzlich erlaubt, aber außerhalb der Galerie geführt. */
export const WEITERE_BILDER = [
"seitenansicht-winter.webp",
"rad-sommer.webp",
"rad-winter.webp",
] as const
export const ERLAUBTE_DATEINAMEN: readonly string[] = [
...BILDPLAETZE.map((b) => b.datei),
...WEITERE_BILDER,
]
/**
* Adresse eines Fahrzeugfotos auf dem Server. Die Bilder liegen unter
* `/local/bilder/` — anders als beim alten Panel läuft die App nicht
* zwangsläufig auf derselben Adresse, deshalb die vollständige URL.
*/
export function bildUrl(dateiname: string | null | undefined): string | undefined {
if (!dateiname) return undefined
const basis = zugangLesenSynchron()?.basisUrl
if (!basis) return undefined
return `${basis}/local/bilder/${dateiname}`
}