From f115af50ab7451db2563ac2bc6ec72022ee07b8a Mon Sep 17 00:00:00 2001 From: Tobi G Date: Sun, 23 Aug 2026 16:50:58 +0200 Subject: [PATCH] Versicherung/Steuer: Wortlaut-Feinschliff und Vertrag komplett editierbar Mein-Audi-Kachel "Versicherung/Steuer" (vAudi()) und Kfz-Steuer-Detail (vSteuer()): "Zusammen" heisst jetzt "Summe", die Fusszeile "feste Kosten im Jahr" darunter entfaellt ersatzlos. Die Kfz-Steuer-Zeile zeigt "im Jahr" statt des rohen Datenwerts "jaehrlich", deckungsgleich mit der Versicherungs-Zeile darueber - nur wenn steuer.zeitraum tatsaechlich "jaehrlich" ist. Der gespeicherte Wert und die "jaehrlich"/"halbjaehrlich"-Auswahl in vSteuerBearbeiten() bleiben unveraendert, das war ein reiner Anzeige-Fix, keine Datenmodell- Aenderung. companion-app hatte an keiner der beiden Stellen ein Gegenstueck (kein "Zusammen"-Tile, keine Nur-Lese-Anzeige des Zeitraums) - dokumentiert als vorbestehende strukturelle Luecke statt kommentarlos uebersprungen. Vertrag-Kachel: war komplett nur lesbar (Gesellschaft, Umfang, Vertragsnummer, Selbstbeteiligung, Schadenfreiheitsklasse). Neue vVertragBearbeiten()-Ansicht (Panel, Route "vertrag") ueber ein neues Zahnrad auf der Vertrag-Kachel - alle Felder editierbar, Selbstbeteiligung zusaetzlich mit Hinzufuegen/Loeschen pro Zeile (neue .zeile-loeschen-Klasse, 44x44pt-Tippflaeche wie .km-edit). Die aktuelle Schadenfreiheitsklasse bleibt bewusst nur ueber "Beitrag anpassen" editierbar (Querverweis statt Duplikat), nur "zuvor" (sfAlt) ist neu in der Vertrag-Ansicht. companion-app: neue Vertrag()-Seite (Route "vertrag", eigene NaviKachel auf der Versicherungs-Seite) nach dem dortigen etablierten Muster (lokaler Entwurf-State + expliziter Speichern-Knopf statt Panel-Autosave pro Feld - gleiches Verhalten, eigenes Idiom). Die bisherige Nur-Lese-Selbstbeteiligung in Vertragsdetails() entfaellt, da sie jetzt (editierbar) in Vertrag() lebt. Schadenfreiheitsklasse wird in companion-app bewusst nicht ergaenzt: das Feld war dort noch nie sichtbar, auch nicht lesend - eine komplette neue UI-Sektion dafuer waere kein "Zeile editierbar machen" mehr, sondern ein neues Feature; als Luecke dokumentiert statt still uebergangen. tsc --noEmit sauber, companion-app-Tests 100/100 (inkl. dem Alle-Seiten-Rendertest, der jetzt auch "vertrag" abdeckt), vite build erfolgreich. Panel live im Docker-Testcontainer geprueft: Zeile hinzufuegen/bearbeiten/loeschen, Daten bleiben nach Re-Render erhalten. Co-Authored-By: Claude Sonnet 5 --- AGENTS.md | 59 ++++++++- companion-app/src/navigation.ts | 3 + companion-app/src/screens/Versicherung.tsx | 120 ++++++++++++++++-- companion-app/src/screens/register.tsx | 3 + companion-app/src/stile/screens.css | 36 ++++++ .../www/audi-dashboard-app.js | 58 ++++++++- .../www/audi-dashboard-version.json | 2 +- .../installationspaket/www/audi-dashboard.css | 15 +++ homeassistant/www/audi-dashboard-app.js | 58 ++++++++- homeassistant/www/audi-dashboard-version.json | 2 +- homeassistant/www/audi-dashboard.css | 15 +++ 11 files changed, 347 insertions(+), 24 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 1ed7691..1a8d9be 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ # AGENTS.md — Project state, review findings, open items, and working rules -**Last updated: 2026-08-18** (merged the `umsetzung-datametric360` branch — companion app phases +**Last updated: 2026-08-19** (merged the `umsetzung-datametric360` branch — companion app phases 1–10 done, see `UMSETZUNGSPLAN.md`; 2026-08-13: cleaned up remaining EU Data Act residue, fixed oversized toggle switches, and fixed a desktop-layout audit (settings button / rings logo / popups overflowing past the capped content column) — see `DESIGN_AUDIT_2026-08-13.md`; 2026-08-16: fixed @@ -52,7 +52,41 @@ solve them - both answer the same way, and the merged "9,0 tkm/ 04/27" number fi "Anstehende Termine" boxes ("Lost information") - no code from that proposal was built; instead the existing Nächster-Service box on the Übersicht had its "bis zum/zur ..." wording replaced by the real Audi CI oil-change/inspection icons (user-supplied SVGs) placed left of the figure, in both -codebases, per the owner's explicit request). +codebases, per the owner's explicit request); 2026-08-19: two small wording fixes on the panel's +"Mein Audi" Versicherung/Steuer summary tile (`vAudi()`) and its "Kfz-Steuer" detail tile +(`vSteuer()`) — "Zusammen" renamed to "Summe" and the "feste Kosten im Jahr" caption under the sum +dropped entirely, and the Kfz-Steuer amount's period caption now reads "im Jahr" instead of the raw +data value "jährlich" (matching the Versicherung row above it) whenever `steuer.zeitraum === +"jährlich"`; the underlying stored value and the "jährlich"/"halbjährlich" edit-form dropdown +(`vSteuerBearbeiten()`) were deliberately left untouched, since this was a display-label fix, not a +data-model rename. No companion-app port was needed for the "Zusammen" row: `companion-app`'s "Mein +Audi" page (`MeinAudi.tsx`) only links to the Versicherung/Steuer screen via a `NaviKachel`, it never +rendered a combined Versicherung+Steuer sum in the first place, so there was nothing to change there +(pre-existing structural gap, not part of this fix). Companion's `Steuer()` edit screen has no +read-only "im Jahr"/"jährlich" display either — its only "jährlich" is a fallback default string +inside an editable-sentence, structurally different from the panel's read-only tiles — so it was left +as-is too. Later the same day: the "Vertrag" tile on that same "Mein Audi" Versicherung/Steuer page +was previously read-only end-to-end (Gesellschaft, Umfang, Vertragsnummer, Selbstbeteiligung, +Schadenfreiheitsklasse) — made every line editable, plus add/delete for the Selbstbeteiligung list +specifically (the only true repeating list among those fields). Panel: new `vVertragBearbeiten()` +view (route `vertrag`, back to `vers`) reached via a new zahnrad button on the "Vertrag" tile in +`vVers()`; Selbstbeteiligung rows get a small inline "×" delete button (new `.zeile-loeschen` CSS, +same 44×44pt invisible-`::before` tap-target trick as `.km-edit`) and a "+ Position hinzufügen" +`.aktion` button that pushes `["", ""]`; Schadenfreiheitsklasse "zuvor" (`sfAlt`) is edited here too +(the *current* SF stays editable only via the pre-existing "Beitrag anpassen" screen, cross- +referenced with a hint span, not duplicated). Companion: new `Vertrag()` screen (route `vertrag`, +its own NaviKachel on the Versicherung page) follows the codebase's own established edit-screen idiom +(local `entwurf` state + explicit "Speichern" button) rather than the panel's per-field autosave — +same behavior, different idiom, per the parity rule. Selbstbeteiligung edit/add/delete moved here +from the old read-only display inside `Vertragsdetails()`, which is removed (was showing the same +list twice would have been confusing). Schadenfreiheitsklasse is *not* added to companion's new +screen: companion never displayed `teile[].sf`/`sfAlt` anywhere before this change (not even +read-only) — building a whole new UI section for a field the app never surfaced is out of scope for +"make the existing lines editable"; documented here as a pre-existing gap, not silently dropped. +Verified live in the Docker test container (panel: add/edit/delete a Selbstbeteiligung position, +values persisted through profilSpeichern()+re-render) and via `tsc --noEmit` + the companion-app test +suite (100/100 incl. the render-every-page smoke test, which now also covers `vertrag`) + `vite +build`, since companion-app needs a live backend connection the local dev server doesn't have. This file is the entry point for every new agent session: what this repo is, what is finished, what is missing, and how to work here. Detail lives in the linked documents — this file points, it does not duplicate. @@ -1650,6 +1684,27 @@ wraps the web app for iPhone; a PWA home-screen install is the accepted intermed - [ ] **Archive** `audi-dashboard-app.js`, don't delete (settled decision, architecture §1) +### E) Versicherungs-Details overhaul (planned, not started — noted 2026-08-19) + +The owner wants to revisit "Versicherung/Steuer" more broadly next session, beyond the line-editing +work already done (see section C in the changelog above: "Vertrag" tile made fully editable with +add/delete for Selbstbeteiligung). Three separate asks, none scoped or started yet: + +- [ ] Store the insurer's own Vertragsdetails PDF against the policy (upload/attach + view later) — + needs a decision on storage location (mirrors the existing vehicle-photo/backup file handling + under `www/bilder/`? a new profile-attachment concept?) and where it's surfaced (new tile on + "Vertragsdetails", or the main "Vertrag" tile) +- [ ] A free-text field for the owner's own manual notes/summary on the insurance (not derived from + any structured field) — likely a `notiz`-style textarea, panel already has a `.notiz` CSS class + pattern used elsewhere (see `feld.notiz` in `audi-dashboard.css`) that could apply here +- [ ] Redesign the "Versicherung/Steuer" Übersicht/summary box — **owner explicitly said they don't + yet know what they want here**; needs a requirements conversation (what should be surfaced at a + glance vs. moved to detail screens) before any mockup, not just a straight implementation + +Not planned/scoped in either codebase yet — start with clarifying questions on the PDF storage model +and the summary-box redesign goals before touching code, per this project's mockup-first convention +for open-ended redesign asks (see the "Anstehende Termine" 3-round mockup process, section C). + --- ## Working conventions (observed — keep them) diff --git a/companion-app/src/navigation.ts b/companion-app/src/navigation.ts index 5be5078..92481c4 100644 --- a/companion-app/src/navigation.ts +++ b/companion-app/src/navigation.ts @@ -23,6 +23,7 @@ export type SeitenName = | "reifen" | "vers" | "beitrag" + | "vertrag" | "vertragsdetails" | "schutz" | "notruf" @@ -54,6 +55,7 @@ export const ZURUECK: Partial> = { battverlauf: "audi", vers: "audi", beitrag: "vers", + vertrag: "vers", vertragsdetails: "vers", schutz: "vertragsdetails", steuer: "vers", @@ -80,6 +82,7 @@ export const TITEL: Record = { reifen: "Reifen", vers: "Versicherung & Steuer", beitrag: "Beitrag", + vertrag: "Vertrag", vertragsdetails: "Vertragsdetails", schutz: "Schutzbrief", notruf: "Notruf", diff --git a/companion-app/src/screens/Versicherung.tsx b/companion-app/src/screens/Versicherung.tsx index 92b1f1b..eff3fd0 100644 --- a/companion-app/src/screens/Versicherung.tsx +++ b/companion-app/src/screens/Versicherung.tsx @@ -56,6 +56,11 @@ export function Versicherung({ geheZu }: { geheZu: (name: SeitenName, id?: strin
geheZu("beitrag")} /> + geheZu("vertrag")} + /> (() => + ((v["selbst"] as (string | number)[][]) ?? []).map(([b, w]) => [String(b ?? ""), String(w ?? "")]), + ) + const [laeuft, setzeLaeuft] = useState(false) + const [gespeichert, setzeGespeichert] = useState(false) + + if (!fahrzeug) return null + + const speichern = async () => { + setzeLaeuft(true) + setzeGespeichert(false) + try { + await profilSpeichern({ + fahrzeug: { + ...fahrzeug, + versicherung: { ...v, gesellschaft, vertrag: umfang, nummer, selbst }, + }, + }) + setzeGespeichert(true) + } finally { + setzeLaeuft(false) + } + } + + return ( + <> + + Vertrag + + setzeGesellschaft(e.target.value)} + /> + + + setzeUmfang(e.target.value)} /> + + + setzeNummer(e.target.value)} /> + + + + + Selbstbeteiligung + {selbst.map((zeile, i) => ( + + + { + const wert = e.target.value + setzeSelbst((alt) => alt.map((z, idx) => (idx === i ? [wert, z[1] ?? ""] : z))) + }} + /> + { + const wert = e.target.value + setzeSelbst((alt) => alt.map((z, idx) => (idx === i ? [z[0] ?? "", wert] : z))) + }} + /> + + + + ))} + {selbst.length === 0 &&

Keine Selbstbeteiligung hinterlegt.

} +
+ setzeSelbst((alt) => [...alt, ["", ""]])}> + + Position hinzufügen + +
+
+ + {gespeichert &&

Gespeichert.

} +
+ void speichern()} disabled={laeuft}> + {laeuft ? "Speichere …" : "Speichern"} + +
+ + ) +} + export function Vertragsdetails({ geheZu }: { geheZu: (name: SeitenName, id?: string) => void }) { const { fahrzeug } = useDaten() if (!fahrzeug) return null const v = fahrzeug.versicherung const leistungen = (v["leistungen"] ?? []) as { bez?: string; wert?: string }[] - const selbst = (v["selbst"] ?? []) as (string | number)[][] return ( <> @@ -178,17 +285,6 @@ export function Vertragsdetails({ geheZu }: { geheZu: (name: SeitenName, id?: st )} - {selbst.length > 0 && ( - - Selbstbeteiligung - ( - - ))} - /> - - )} - case "beitrag": return + case "vertrag": + return case "vertragsdetails": return case "schutz": diff --git a/companion-app/src/stile/screens.css b/companion-app/src/stile/screens.css index b871012..1713fcb 100644 --- a/companion-app/src/stile/screens.css +++ b/companion-app/src/stile/screens.css @@ -24,6 +24,42 @@ color: var(--fg3); } +/* Eine Zeile aus einer bearbeitbaren Liste (z. B. Selbstbeteiligung im + Vertrag) - zwei Eingaben plus Löschen-Knopf in einer Reihe, deckungsgleich + mit .feld/.zeile-loeschen im Panel (audi-dashboard.css). */ +.dm-selbst-zeile { + display: inline-flex; + align-items: center; + gap: var(--sp-2); +} + +.dm-zeile-loeschen { + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + width: 22px; + height: 22px; + border: none; + background: none; + color: var(--fg3); + font-size: 18px; + line-height: 1; + padding: 0; + cursor: pointer; + flex: 0 0 auto; +} + +.dm-zeile-loeschen::before { + content: ""; + position: absolute; + inset: -11px; +} + +.dm-zeile-loeschen:active { + color: var(--bad); +} + .dm-auswahl { text-align: right; appearance: none; diff --git a/homeassistant/installationspaket/www/audi-dashboard-app.js b/homeassistant/installationspaket/www/audi-dashboard-app.js index 0b82ca2..8e6fd68 100644 --- a/homeassistant/installationspaket/www/audi-dashboard-app.js +++ b/homeassistant/installationspaket/www/audi-dashboard-app.js @@ -1415,9 +1415,9 @@ function vAudi() {
Versicherung
${eur(CAR.versicherung.beitrag)} €im Jahr
-
Kfz-Steuer
${eur(CAR.steuer.betrag)} €${esc(CAR.steuer.zeitraum)}
-
Zusammen
-
${eur(CAR.versicherung.beitrag + CAR.steuer.betrag)} €feste Kosten im Jahr
+
Kfz-Steuer
${eur(CAR.steuer.betrag)} €${CAR.steuer.zeitraum === "jährlich" ? "im Jahr" : esc(CAR.steuer.zeitraum)}
+
Summe
+
${eur(CAR.versicherung.beitrag + CAR.steuer.betrag)} €
Vertrag +
Gesellschaft
${esc(v.gesellschaft)}
Umfang
${esc(v.vertrag)}
@@ -1976,6 +1979,40 @@ function vVertragsdetails() {
`).join("")}`; } +function vVertragBearbeiten() { + const v = CAR.versicherung; + return ` +
Vertrag +
+
+
+
+
+
+
+
Selbstbeteiligung + ${v.selbst.map(([b, w], i) => ` +
+ + + + + + +
`).join("")} + ${!v.selbst.length ? `Keine Selbstbeteiligung hinterlegt` : ""} + +
+
Schadenfreiheitsklasse · zuvor +
+
+
+
+ Die aktuelle Schadenfreiheitsklasse änderst du unter + "Beitrag anpassen" — hier steht nur der vorherige Wert für den Vergleich. +
`; +} + function vSchutz() { const v = CAR.versicherung, sb = v.schutzbrief; return ` @@ -2028,7 +2065,7 @@ function vSteuer() {
-
Betrag
${eur(t.betrag)} €${esc(t.zeitraum)}
+
Betrag
${eur(t.betrag)} €${t.zeitraum === "jährlich" ? "im Jahr" : esc(t.zeitraum)}
Nächste Fälligkeit
${t.faellig ? dedat(new Date(t.faellig)) : "unbekannt"}
@@ -3157,6 +3194,7 @@ let route = { name: "home" }; const ZURUECK = { trip: "trips", fill: "fuel", service: "audi", reifen: "audi", ident: "audi", vers: "audi", beitrag: "vers", vertragsdetails: "vers", schutz: "vertragsdetails", + vertrag: "vers", steuer: "vers", notruf: "vers", werkstatt: "service", sbuch: "service", einst: "home", battverlauf: "audi", /* Fehlte: die Sicherheitsansicht war eine Sackgasse ohne sichtbaren @@ -3439,6 +3477,7 @@ function render() { else if (route.name === "vers") { head = ["Fahrzeug", "Versicherung/Steuer"]; v.innerHTML = vVers(); } else if (route.name === "beitrag") { head = ["Versicherung", "Beitrag anpassen"]; v.innerHTML = vBeitrag(); } else if (route.name === "vertragsdetails") { head = ["Versicherung", "Vertragsdetails"]; v.innerHTML = vVertragsdetails(); } + else if (route.name === "vertrag") { head = ["Versicherung", "Vertrag"]; v.innerHTML = vVertragBearbeiten(); } else if (route.name === "steuer") { head = ["Versicherung", "Kfz-Steuer"]; v.innerHTML = vSteuerBearbeiten(); } else if (route.name === "notruf") { head = ["Versicherung", "Rufnummern"]; v.innerHTML = vNotrufBearbeiten(); } else if (route.name === "schutz") { head = ["Im Ernstfall", "Schutzbrief"]; v.innerHTML = vSchutz(); } @@ -4105,6 +4144,9 @@ function ereignisseVerdrahten() { } const del = e.target.closest("[data-loeschen]"); if (del) { delete CAR.service.vereinbart[del.dataset.loeschen]; profilSpeichern(); render(); return; } + const vseldel = e.target.closest("[data-vselbstdel]"); + if (vseldel) { CAR.versicherung.selbst.splice(+vseldel.dataset.vselbstdel, 1); profilSpeichern(); render(); return; } + if (e.target.closest("[data-vselbstadd]")) { CAR.versicherung.selbst.push(["", ""]); profilSpeichern(); render(); return; } const oel = e.target.closest("[data-oel]"); if (oel) { CAR.oel.modus = oel.dataset.oel; profilSpeichern(); render(); return; } const mode = e.target.closest("[data-mode]"); @@ -4363,6 +4405,14 @@ function ereignisseVerdrahten() { if (e.target.dataset.vgueltigab !== undefined) { CAR.versicherung.gueltigAb = e.target.value; profilSpeichern(); render(); return; } const vnotruf = e.target.dataset.vnotruf; if (vnotruf) { CAR.versicherung[vnotruf] = e.target.value; profilSpeichern(); render(); return; } + const vvertrag = e.target.dataset.vvertrag; + if (vvertrag) { CAR.versicherung[vvertrag] = e.target.value; profilSpeichern(); render(); return; } + const vselbst = e.target.dataset.vselbst; + if (vselbst) { + const [i, feld] = vselbst.split("|"); + CAR.versicherung.selbst[+i][+feld] = e.target.value; + profilSpeichern(); render(); return; + } if (e.target.dataset.pause !== undefined) { CONFIG.pauseMin = parseInt(e.target.value, 10) || 0; profilSpeichern(); return; } if (e.target.dataset.sd !== undefined) { if (e.target.checked) { smartdealPopupOffen = true; render(); } diff --git a/homeassistant/installationspaket/www/audi-dashboard-version.json b/homeassistant/installationspaket/www/audi-dashboard-version.json index def37c1..4c4ab29 100644 --- a/homeassistant/installationspaket/www/audi-dashboard-version.json +++ b/homeassistant/installationspaket/www/audi-dashboard-version.json @@ -1 +1 @@ -{"version": 1787013003} +{"version": 1787014000} diff --git a/homeassistant/installationspaket/www/audi-dashboard.css b/homeassistant/installationspaket/www/audi-dashboard.css index 3574918..350e3f8 100644 --- a/homeassistant/installationspaket/www/audi-dashboard.css +++ b/homeassistant/installationspaket/www/audi-dashboard.css @@ -1044,6 +1044,21 @@ button.tile, .tilebtn { transition: background .15s, transform .1s; } .km-edit:hover { color: var(--fg); } .km-edit:active { color: var(--fg); transform: scale(.92); } +/* Zeile aus einer bearbeitbaren Liste entfernen (z. B. Selbstbeteiligung im + Vertrag) - 44x44pt Tippflaeche per unsichtbarem ::before wie bei .km-edit, + optisch bleibt nur das kleine × sichtbar. */ +.zeile-loeschen { + position: relative; + display: inline-flex; align-items: center; justify-content: center; + width: 22px; height: 22px; + border: none; background: none; color: var(--fg3); + font-size: 18px; line-height: 1; + padding: 0; cursor: pointer; flex: 0 0 auto; +} +.zeile-loeschen::before { content: ""; position: absolute; inset: -11px; } +.zeile-loeschen:hover { color: var(--bad); } +.zeile-loeschen:active { color: var(--bad); transform: scale(.92); } + /* Kompakte Pille statt voller Breite (Apple-HIG-Pull-down-Maß): normale Flusslage unter der Kachel-Überschrift/km, nicht mehr über dem Foto überlagert (das saß nur dort, solange Überschrift+km diesen Platz noch diff --git a/homeassistant/www/audi-dashboard-app.js b/homeassistant/www/audi-dashboard-app.js index 0b82ca2..8e6fd68 100644 --- a/homeassistant/www/audi-dashboard-app.js +++ b/homeassistant/www/audi-dashboard-app.js @@ -1415,9 +1415,9 @@ function vAudi() {
Versicherung
${eur(CAR.versicherung.beitrag)} €im Jahr
-
Kfz-Steuer
${eur(CAR.steuer.betrag)} €${esc(CAR.steuer.zeitraum)}
-
Zusammen
-
${eur(CAR.versicherung.beitrag + CAR.steuer.betrag)} €feste Kosten im Jahr
+
Kfz-Steuer
${eur(CAR.steuer.betrag)} €${CAR.steuer.zeitraum === "jährlich" ? "im Jahr" : esc(CAR.steuer.zeitraum)}
+
Summe
+
${eur(CAR.versicherung.beitrag + CAR.steuer.betrag)} €
Gesellschaft
${esc(v.gesellschaft)}
Umfang
${esc(v.vertrag)}
@@ -1976,6 +1979,40 @@ function vVertragsdetails() {
`).join("")}`; } +function vVertragBearbeiten() { + const v = CAR.versicherung; + return ` +
Vertrag +
+
+
+
+
+
+
+
Selbstbeteiligung + ${v.selbst.map(([b, w], i) => ` +
+ + + + + + +
`).join("")} + ${!v.selbst.length ? `Keine Selbstbeteiligung hinterlegt` : ""} + +
+
Schadenfreiheitsklasse · zuvor +
+
+
+
+ Die aktuelle Schadenfreiheitsklasse änderst du unter + "Beitrag anpassen" — hier steht nur der vorherige Wert für den Vergleich. +
`; +} + function vSchutz() { const v = CAR.versicherung, sb = v.schutzbrief; return ` @@ -2028,7 +2065,7 @@ function vSteuer() {
-
Betrag
${eur(t.betrag)} €${esc(t.zeitraum)}
+
Betrag
${eur(t.betrag)} €${t.zeitraum === "jährlich" ? "im Jahr" : esc(t.zeitraum)}
Nächste Fälligkeit
${t.faellig ? dedat(new Date(t.faellig)) : "unbekannt"}
@@ -3157,6 +3194,7 @@ let route = { name: "home" }; const ZURUECK = { trip: "trips", fill: "fuel", service: "audi", reifen: "audi", ident: "audi", vers: "audi", beitrag: "vers", vertragsdetails: "vers", schutz: "vertragsdetails", + vertrag: "vers", steuer: "vers", notruf: "vers", werkstatt: "service", sbuch: "service", einst: "home", battverlauf: "audi", /* Fehlte: die Sicherheitsansicht war eine Sackgasse ohne sichtbaren @@ -3439,6 +3477,7 @@ function render() { else if (route.name === "vers") { head = ["Fahrzeug", "Versicherung/Steuer"]; v.innerHTML = vVers(); } else if (route.name === "beitrag") { head = ["Versicherung", "Beitrag anpassen"]; v.innerHTML = vBeitrag(); } else if (route.name === "vertragsdetails") { head = ["Versicherung", "Vertragsdetails"]; v.innerHTML = vVertragsdetails(); } + else if (route.name === "vertrag") { head = ["Versicherung", "Vertrag"]; v.innerHTML = vVertragBearbeiten(); } else if (route.name === "steuer") { head = ["Versicherung", "Kfz-Steuer"]; v.innerHTML = vSteuerBearbeiten(); } else if (route.name === "notruf") { head = ["Versicherung", "Rufnummern"]; v.innerHTML = vNotrufBearbeiten(); } else if (route.name === "schutz") { head = ["Im Ernstfall", "Schutzbrief"]; v.innerHTML = vSchutz(); } @@ -4105,6 +4144,9 @@ function ereignisseVerdrahten() { } const del = e.target.closest("[data-loeschen]"); if (del) { delete CAR.service.vereinbart[del.dataset.loeschen]; profilSpeichern(); render(); return; } + const vseldel = e.target.closest("[data-vselbstdel]"); + if (vseldel) { CAR.versicherung.selbst.splice(+vseldel.dataset.vselbstdel, 1); profilSpeichern(); render(); return; } + if (e.target.closest("[data-vselbstadd]")) { CAR.versicherung.selbst.push(["", ""]); profilSpeichern(); render(); return; } const oel = e.target.closest("[data-oel]"); if (oel) { CAR.oel.modus = oel.dataset.oel; profilSpeichern(); render(); return; } const mode = e.target.closest("[data-mode]"); @@ -4363,6 +4405,14 @@ function ereignisseVerdrahten() { if (e.target.dataset.vgueltigab !== undefined) { CAR.versicherung.gueltigAb = e.target.value; profilSpeichern(); render(); return; } const vnotruf = e.target.dataset.vnotruf; if (vnotruf) { CAR.versicherung[vnotruf] = e.target.value; profilSpeichern(); render(); return; } + const vvertrag = e.target.dataset.vvertrag; + if (vvertrag) { CAR.versicherung[vvertrag] = e.target.value; profilSpeichern(); render(); return; } + const vselbst = e.target.dataset.vselbst; + if (vselbst) { + const [i, feld] = vselbst.split("|"); + CAR.versicherung.selbst[+i][+feld] = e.target.value; + profilSpeichern(); render(); return; + } if (e.target.dataset.pause !== undefined) { CONFIG.pauseMin = parseInt(e.target.value, 10) || 0; profilSpeichern(); return; } if (e.target.dataset.sd !== undefined) { if (e.target.checked) { smartdealPopupOffen = true; render(); } diff --git a/homeassistant/www/audi-dashboard-version.json b/homeassistant/www/audi-dashboard-version.json index def37c1..4c4ab29 100644 --- a/homeassistant/www/audi-dashboard-version.json +++ b/homeassistant/www/audi-dashboard-version.json @@ -1 +1 @@ -{"version": 1787013003} +{"version": 1787014000} diff --git a/homeassistant/www/audi-dashboard.css b/homeassistant/www/audi-dashboard.css index 3574918..350e3f8 100644 --- a/homeassistant/www/audi-dashboard.css +++ b/homeassistant/www/audi-dashboard.css @@ -1044,6 +1044,21 @@ button.tile, .tilebtn { transition: background .15s, transform .1s; } .km-edit:hover { color: var(--fg); } .km-edit:active { color: var(--fg); transform: scale(.92); } +/* Zeile aus einer bearbeitbaren Liste entfernen (z. B. Selbstbeteiligung im + Vertrag) - 44x44pt Tippflaeche per unsichtbarem ::before wie bei .km-edit, + optisch bleibt nur das kleine × sichtbar. */ +.zeile-loeschen { + position: relative; + display: inline-flex; align-items: center; justify-content: center; + width: 22px; height: 22px; + border: none; background: none; color: var(--fg3); + font-size: 18px; line-height: 1; + padding: 0; cursor: pointer; flex: 0 0 auto; +} +.zeile-loeschen::before { content: ""; position: absolute; inset: -11px; } +.zeile-loeschen:hover { color: var(--bad); } +.zeile-loeschen:active { color: var(--bad); transform: scale(.92); } + /* Kompakte Pille statt voller Breite (Apple-HIG-Pull-down-Maß): normale Flusslage unter der Kachel-Überschrift/km, nicht mehr über dem Foto überlagert (das saß nur dort, solange Überschrift+km diesen Platz noch