Reifen/Version/Wartungsplan: erste Runde des Sammel-Feedbacks behoben

- Archiv-Knopf jetzt in Zeile mit "Montiert" (stale margin-top entfernt),
  bekommt einen sichtbaren Hintergrund
- companion-app: Wechseltermin-Datumsfeld (appearance-Reset gegen
  natives Safari-Chrome, Breite auf Inhalt geschrumpft)
- Mein Audi/Reifen-Box: "montiert: Sommerräder" links statt Marke/Modell,
  "offen" durch "-" ersetzt
- "Servicebuch" ueberall in "Wartungsplan" umbenannt (nur Anzeigetext,
  beide Codebasen)
- Version-Kachel: tote Fahrzeugdaten-/Position-/Dashboard-Zeilen entfernt
  (inkl. der nie aktualisierten CONFIG.version-Konstante)

Version 2026.8.28.1, live im Testcontainer verifiziert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-28 09:43:40 +02:00
parent bdd8cb89a3
commit edefdd66d8
9 changed files with 129 additions and 31 deletions
@@ -116,7 +116,6 @@ function profilZuConfig(p) {
fahrzeuguntertitel: p.fahrzeug.untertitel,
kennzeichen: p.fahrzeug.kennzeichen,
startbild: p.einstellungen.uebersichtsbild,
version: "1.0",
tankvolumen: p.fahrzeug.tankvolumen_liter,
nachtVon: p.einstellungen.nacht_von,
nachtBis: p.einstellungen.nacht_bis,
@@ -1394,7 +1393,7 @@ function terminText(t) {
const restKmAbs = restKm !== null ? Math.abs(restKm) : null;
const haupt = t.zuerst === "km" && restKm !== null ? "in " + de(restKmAbs) + " km" : dedat(t.datum);
const neben = t.zuerst === "km" ? "voraussichtlich " + dedat(t.kmDatum) + " · " + dedat(t.datum)
: (t.km !== null ? "in " + de(restKmAbs) + " km" : (t.art === "Hauptuntersuchung" ? "" : "aus dem Servicebuch fortgeschrieben"));
: (t.km !== null ? "in " + de(restKmAbs) + " km" : (t.art === "Hauptuntersuchung" ? "" : "aus dem Wartungsplan fortgeschrieben"));
return { haupt, neben, restKm };
}
@@ -1468,7 +1467,7 @@ function vHome() {
</div>`;
if (!t) return `<div class="tile" style="margin-bottom:22px">
<span class="label">Nächster Service:</span>
<div class="wert" style="margin-top:8px">kein Eintrag im Servicebuch</div>
<div class="wert" style="margin-top:8px">kein Eintrag im Wartungsplan</div>
${kmZeile}
</div>`;
// naechsterTermin() waehlt bereits ueber alle drei Arten hinweg (Oelwechsel,
@@ -1656,13 +1655,13 @@ function vAudi() {
<dd>${eur(CAR.versicherung.beitrag + CAR.steuer.betrag)} </dd></div>
</dl></button>
<button class="tile tilebtn" data-go="reifen:x">
<span class="label">Reifen · ${r.aktiv} montiert</span>
<span class="label">Reifen</span>
<svg class="go" viewBox="0 0 6 10"><polyline points="1,1 5,5 1,9"/></svg>
<dl class="rows" style="margin-top:10px">
<div class="row"><dt>${esc(a.marke)} ${esc(a.modell)}</dt><dd>${esc(a.mass)}</dd></div>
<div class="row"><dt>montiert: ${r.aktiv}räder</dt><dd>${esc(a.mass)}</dd></div>
<div class="row"><dt>Laufleistung</dt><dd>${a.km != null ? de(a.km) + " km" : "unbekannt"}</dd></div>
<div class="row" style="border-bottom:0"><dt>Wechseltermin</dt>
<dd>${dedat(new Date(r.wechsel.datum))}<small>${r.wechsel.vereinbart ? "vereinbart" : "offen"}</small></dd></div>
<dd>${dedat(new Date(r.wechsel.datum))}<small>${r.wechsel.vereinbart ? "vereinbart" : ""}</small></dd></div>
</dl></button>`;
}
@@ -2039,7 +2038,7 @@ function vService() {
const iv = intervalle(t);
if (!iv && !hatMeldung) return `<div class="termingruppe">
<div class="tg-kopf">${kopf}</div>
<div class="tg-wert leer">kein Eintrag im Servicebuch</div>
<div class="tg-wert leer">kein Eintrag im Wartungsplan</div>
</div>`;
const anzeige = iv ? (iv.hersteller || iv.eigen) : null;
// Forecast-Zeile aus dem kundeneigenen Intervall in "Einrichten" mit
@@ -2119,13 +2118,13 @@ function vService() {
href="https://maps.google.com/?q=${encodeURIComponent(sv.autohaus.adresse)}"
style="display:block;text-decoration:none;text-align:center">In Karten öffnen</a>
</div>
<div class="tile"><span class="label">Servicebuch</span>
<div class="tile"><span class="label">Wartungsplan</span>
${sv.buch.length ? sv.buch.map((e, i) => swipeZeile(`sbuch:${i}`, `<button class="leaf" style="padding-left:0" data-go="sbuch:${i}">
<span class="k">${esc(e.art)}<small>${esc(e.werkstatt)}</small></span>
<span class="v">${e.datum}<small>${de(e.km)} km${e.kosten != null ? " · " + eur(e.kosten) + " €" : ""}</small></span>
<svg class="chev" viewBox="0 0 6 10"><polyline points="1,1 5,5 1,9"/></svg></button>`)).join("") : `<div class="leer" style="margin-top:12px">
<strong>Noch keine Einträge</strong>
<p>Aus dem Servicebuch berechnet die App die Fälligkeit von Inspektion, Ölwechsel und Hauptuntersuchung. Der erste Eintrag ist die Grundlage für jede Prognose.</p>
<p>Aus dem Wartungsplan berechnet die App die Fälligkeit von Inspektion, Ölwechsel und Hauptuntersuchung. Der erste Eintrag ist die Grundlage für jede Prognose.</p>
</div>`}
<button class="aktion primaer" data-sbneu>Eintrag hinzufügen</button>
</div>`;
@@ -2653,14 +2652,11 @@ function vEinst() {
Tabellenprogrammen aufgehen.</span>
<button class="aktion" data-csv="fahrten">Fahrten als CSV</button>
<button class="aktion" data-csv="tanken">Tankvorgänge als CSV</button>
<button class="aktion" data-csv="service">Servicebuch als CSV</button>
<button class="aktion" data-csv="service">Wartungsplan als CSV</button>
</div>
<div class="tile"><span class="label">Version</span>
<dl class="rows">
<div class="row"><dt>Dashboard</dt><dd>${esc(CONFIG.version)}</dd></div>
<div class="row"><dt>Installiert</dt><dd>${esc(APP_VERSION || "unbekannt")}<small>Home-Assistant-Integration</small></dd></div>
<div class="row"><dt>Fahrzeugdaten</dt><dd>FMM003<small>Zündung · Batterie</small></dd></div>
<div class="row" style="border-bottom:0"><dt>Position</dt><dd>FMM003<small>GPS-Tracker</small></dd></div>
<div class="row" style="border-bottom:0"><dt>Installiert</dt><dd>${esc(APP_VERSION || "unbekannt")}<small>Home-Assistant-Integration</small></dd></div>
</dl>
</div>
<div class="tile"><span class="label">Integration-Update</span>
@@ -2958,9 +2954,9 @@ function vReifen() {
<button type="button" data-bildersetzen="${radDatei}">Foto ersetzen</button>
<button type="button" class="loeschen" data-bildloeschen="${radDatei}">Löschen</button>
</div>` : ""}
<div style="display:flex;justify-content:space-between;align-items:center">
<div style="display:flex;justify-content:space-between;align-items:center;margin-top:var(--sp-4)">
<button data-satz="${k === "sommer" ? "Sommer" : "Winter"}" class="montiert ${aktiv ? "on" : ""}">Montiert</button>
<button class="iconbtn" data-reifenarchivieren="${k}" aria-label="Neue Räder anlegen">${ciSVG(CI.packageS, 18)}</button>
<button class="iconbtn archivbtn" data-reifenarchivieren="${k}" aria-label="Neue Räder anlegen">${ciSVG(CI.packageS, 18)}</button>
</div>
<div style="margin-top:12px">
${feld(k, "marke", "Hersteller")}
@@ -3418,14 +3414,14 @@ function swipeZeile(id, inhaltHtml) {
const LOESCH_TEXT = {
trip: "Fahrt löschen?",
fill: "Tankvorgang löschen?",
sbuch: "Servicebuch-Eintrag löschen?",
sbuch: "Wartungsplan-Eintrag löschen?",
bild: "Foto löschen?",
batt: "Messwert löschen?",
};
const LOESCH_HINWEIS = {
trip: "Die Fahrt wird aus dem Fahrtenbuch entfernt. Das lässt sich nicht widerrufen.",
fill: "Der Tankvorgang und der zugehörige Beleg werden entfernt. Das lässt sich nicht widerrufen.",
sbuch: "Der Eintrag wird aus dem Servicebuch entfernt. Das lässt sich nicht widerrufen.",
sbuch: "Der Eintrag wird aus dem Wartungsplan entfernt. Das lässt sich nicht widerrufen.",
bild: "Das Foto wird vom Server gelöscht. Der Platz bleibt bestehen und kann neu belegt werden.",
batt: "Der Tageseintrag wird aus der Messwertliste entfernt. Das lässt sich nicht widerrufen.",
};
@@ -4077,7 +4073,7 @@ function render() {
else if (route.name === "werkstatt") { head = ["Service", "Autohaus"]; v.innerHTML = vWerkstatt(); }
else if (route.name === "battverlauf") { head = ["Fahrzeug", "Batteriespannung"]; v.innerHTML = vBatterieverlauf(); bvZeichnen(); }
else if (route.name === "battliste") { head = ["Batteriespannung", "Messwerte"]; v.innerHTML = vBatterieliste(); }
else if (route.name === "sbuch") { head = ["Servicebuch", "Eintrag"]; v.innerHTML = vSbuch(); }
else if (route.name === "sbuch") { head = ["Wartungsplan", "Eintrag"]; v.innerHTML = vSbuch(); }
else if (route.name === "standort") { head = ["Fahrzeug", "Standort"]; v.innerHTML = vStandort(); }
else { const t = TABS.find((x) => x.id === route.name); head = [t.eyebrow, t.id === "audi" ? "Mein Audi" : t.title];
v.innerHTML = { audi: vAudi, trips: vTrips, stat: vStat, fuel: vFuel }[route.name](); }
@@ -182,6 +182,12 @@
}
.iconbtn:hover { background: var(--tile-2); color: var(--fg); }
.iconbtn:active { background: var(--tile-2); color: var(--fg); transform: scale(.92); }
/* "Neue Räder anlegen" auf der Reifen-Seite: bewusst dauerhaft mit
sichtbarem Hintergrund statt nur bei Hover/Tap wie .iconbtn sonst - sitzt
direkt neben dem gefüllten "Montiert"-Knopf und wirkt ohne eigene Fläche
zu unscheinbar, um dort als eigenständiger Knopf erkannt zu werden. */
.archivbtn { background: var(--tile-2); color: var(--fg2); }
.archivbtn:hover, .archivbtn:active { color: var(--fg); }
/* D4 war urspruenglich: die Ringe sind Marke, kein Knopf. Seit die
iOS-Auflage in Telefonbreite das Zahnrad ausblendet, sind sie dort aber der
einzige Zugang zu den Einstellungen - und als reines div mit
@@ -1131,7 +1137,7 @@ button.leaf:active { background: var(--tile-2); }
überlagert (das saß nur dort, solange Überschrift+km diesen Platz noch
nicht beanspruchten). */
.montiert {
position: relative; margin-top: var(--sp-4);
position: relative;
display: inline-flex; align-items: center; justify-content: center;
font-family: inherit; font-size: 12px; letter-spacing: normal;
color: var(--fg2);
@@ -1,7 +1,7 @@
{
"domain": "audi_dashboard",
"name": "Audi Dashboard",
"version": "2026.8.27.22",
"version": "2026.8.28.1",
"documentation": "https://gitea.nothaft.cloud/paul/audi-app/src/branch/main/README.md",
"issue_tracker": "https://gitea.nothaft.cloud/paul/audi-app/issues",
"codeowners": ["@paul"],