LEVADIS® Haushaltsrechner :root { --lev-primary: #574b90; --lev-primary-soft: rgba(87, 75, 144, 0.06); --lev-bg: #f5f5fa; --lev-text: #222; --lev-muted: #777; --lev-border: #ddd; --lev-radius: 12px; } * { box-sizing: border-box; } body { margin: 0; padding: 0; background: var(--lev-bg); color: var(--lev-text); font-family: "Open Sans", system-ui, sans-serif; } /* Wrapper */ .lev-wrapper { max-width: 1100px; margin: 0 auto; padding: 20px 16px 40px; } /* Header */ header { background: #fff; border-radius: 16px; padding: 22px; margin-bottom: 20px; box-shadow: 0 8px 24px rgba(0,0,0,0.06); border: 1px solid rgba(87,75,144,0.10); } header h1 { margin: 0 0 10px; color: var(--lev-primary); font-size: 1.8rem; font-weight: 700; letter-spacing: 0.01em; } header p { margin: 0 0 14px; color: var(--lev-muted); line-height: 1.55; font-size: 0.95rem; } /* Namensfeld */ .lev-name-label { display: block; margin-bottom: 4px; font-size: 0.8rem; color: var(--lev-muted); } .lev-name-input { width: 260px; max-width: 100%; padding: 8px; border-radius: 8px; border: 1px solid #ccc; font-size: 0.9rem; font-family: inherit; } /* Karten */ .lev-card { width: 100%; background: #fff; border-radius: var(--lev-radius); padding: 16px 16px 20px; margin-bottom: 18px; border: 1px solid var(--lev-border); box-shadow: 0 4px 14px rgba(0,0,0,0.04); } .lev-card-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; } .lev-card-header h2 { margin: 0; color: var(--lev-primary); font-size: 1.25rem; font-weight: 600; } .lev-subtext { margin: 6px 0 14px; color: var(--lev-muted); font-size: 0.85rem; line-height: 1.45; } /* Accordion Button */ .lev-toggle-btn { background: #fff; border: 1px solid rgba(87,75,144,0.45); color: var(--lev-primary); padding: 4px 10px; border-radius: 999px; font-size: 0.75rem; cursor: pointer; display: inline-flex; align-items: center; gap: 4px; } .lev-toggle-btn .icon { font-size: 0.85rem; } /* Collapsed body */ .lev-card-body.collapsed { display: none; } /* Tabellen */ table { width: 100%; border-collapse: collapse; table-layout: fixed; font-size: 0.86rem; } th, td { padding: 6px 6px; border-bottom: 1px solid #eee; text-align: left; vertical-align: middle; } th { color: var(--lev-muted); font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.03em; line-height: 1.3; white-space: normal; } tr:last-child td { border-bottom: none; } /* Inputs */ input[type="text"], input[type="number"], select { width: 100%; padding: 6px; border-radius: 6px; border: 1px solid #ccc; font-size: 0.86rem; font-family: inherit; } input[type="number"] { text-align: right; } /* Buttons */ .lev-btn { padding: 6px 12px; border-radius: 999px; border: none; font-size: 0.8rem; font-weight: 600; cursor: pointer; background: var(--lev-primary); color: #fff; display: inline-flex; align-items: center; gap: 5px; } .lev-btn.small { padding: 4px 10px; font-size: 0.75rem; } .lev-btn.secondary { background: #fff; color: var(--lev-primary); border: 1px solid rgba(87,75,144,0.4); } .lev-btn.danger { background: #fff; color: #b3261e; border: 1px solid #b3261e; } /* Summenzeilen */ .lev-row-sum { text-align: right; margin-top: 6px; color: var(--lev-muted); font-size: 0.82rem; } /* Szenarien */ .lev-summary-card { background: var(--lev-primary-soft); border: 1px solid rgba(87,75,144,0.2); padding: 12px; border-radius: var(--lev-radius); margin-bottom: 12px; } .lev-summary-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px,1fr)); gap: 10px; } .lev-summary-item .lev-summary-label { font-size: 0.75rem; color: var(--lev-muted); text-transform: uppercase; letter-spacing: .03em; margin-bottom: 2px; } .lev-summary-value { font-weight: 600; font-size: 0.9rem; } .lev-scenarios { display: grid; grid-template-columns: repeat(auto-fit,minmax(240px,1fr)); gap: 12px; margin-top: 12px; } .lev-scenario { border: 1px solid rgba(87,75,144,0.25); border-radius: var(--lev-radius); padding: 12px; background: #fff; box-shadow: 0 3px 10px rgba(87,75,144,0.08); font-size: 0.85rem; } .lev-scenario-title { color: var(--lev-primary); font-weight: 600; font-size: 0.92rem; margin-bottom: 4px; } .lev-scenario-text { font-size: 0.78rem; color: var(--lev-muted); line-height: 1.4; margin-top: 6px; } /* Quiz */ #quizTable th:nth-child(1){width:45%;} #quizTable th:nth-child(2){width:20%;} #quizTable th:nth-child(3){width:18%;} #quizTable th:nth-child(4){width:17%;} .quiz-save { font-size: 0.8rem; color: var(--lev-muted); } /* Footer buttons */ .lev-footer-actions { display: flex; flex-wrap: wrap; gap: 10px; justify-content: flex-end; margin-top: 12px; } .lev-tag { display: inline-block; padding: 3px 8px; border-radius: 999px; background: rgba(0,0,0,0.05); font-size: 0.72rem; color: var(--lev-muted); } /* FOOTER */ .page-footer { margin-top: 28px; text-align: center; font-size: 0.8rem; color: var(--lev-muted); width: 100%; }

LEVADIS® Haushaltsrechner

Ein smarter Überblick über dein Geld – mit Spar-Szenarien von „sanft“ bis „radikal“. Keine Registrierung, keine Datenübertragung – alles bleibt auf deinem Gerät.

Für vollständige Tabellenansicht am Smartphone bitte ins Querformat drehen.

Einnahmen

Monats- oder Jahreswerte

Trage hier deine regelmäßigen Einnahmen ein. Du kannst Beträge monatlich oder jährlich angeben. Bei „monatlich“ wird zwischen 12× und 14× Auszahlung pro Jahr unterschieden.

Quelle Betrag
(in €)
Art der Auszahlung
Monatliche Gesamt-Einnahmen: 0 €
Jährliche Gesamt-Einnahmen: 0 €

Fixkosten A – unvermeidbar

Alle laufenden Kosten, die verpflichtend oder existenziell sind. Du kannst Beträge monatlich oder jährlich angeben – der Rechner wandelt alles in Monatswerte um. Die Notwendigkeitsskala (1–5) zeigt, wie viel Optimierung möglich ist.

Position Betrag
(in €)
Intervall
(Monat/Jahr)
Notwendigkeit
(1–5)
Summe Fixkosten A (Monat): 0 €

Fixkosten B – verzichtbar / optimierbar

Komfort- und Lifestyle-Kosten, die du anpassen oder reduzieren könntest.

Position Betrag
(in €)
Intervall
(Monat/Jahr)
Notwendigkeit
(1–5)
Summe Fixkosten B (Monat): 0 €

Variable Ausgaben

Alles, was von Monat zu Monat schwankt – z. B. Lebensmittel, Freizeit, Shopping.

Position Betrag
(in €)
Intervall
(Monat/Jahr)
Notwendigkeit
(1–5)
Summe variable Ausgaben (Monat): 0 €

Schulden & Rückzahlungen

Kreditraten und andere Verpflichtungen. Sie werden in die Ist-Ausgaben eingerechnet – die Spar-Szenarien zeigen, wie viel du zusätzlich für schnelleren Schuldenabbau freispielen könntest.

Position Betrag
(in €)
Intervall
(Monat/Jahr)
Notwendigkeit
(1–5)
Summe Schuldenrückzahlungen (Monat): 0 €

Rücklagen & Sparziele

Geplante Rücklagen und Sparraten. Sie reduzieren deinen aktuellen Spielraum, sind aber wichtig für Sicherheit und Zukunft.

Position Betrag
(in €)
Intervall
(Monat/Jahr)
Notwendigkeit
(1–5)
Summe Rücklagen (Monat): 0 €

Ergebnis & Spar-Szenarien

Auf Basis deiner Angaben werden drei Szenarien berechnet – von leichten Anpassungen bis zu maximal möglichen Einsparungen.

Jahres-Einnahmen
0 €
Jahres-Ausgaben (Ist)
0 €
Saldo (Ist)
0 €
Sanftes Szenario
Potenziell frei pro Monat: 0 €
Potenziell frei pro Jahr: 0 €
Im sanften Szenario würdest du ohne große Einschränkungen etwa 0 € pro Monat freispielen. Das sind jährlich 0 € frei verfügbar – damit kannst du auf etwas ansparen, dir einen finanziellen Puffer aufbauen oder dir andere schöne Dinge gönnen. Wenn du Kreditraten oder andere Verpflichtungen hast, kann dieser Betrag auch helfen, deine finanziellen Verpflichtungen spürbar zu reduzieren.
Spürbare Optimierung
Potenziell frei pro Monat: 0 €
Potenziell frei pro Jahr: 0 €
Hier setzt du bewusst Prioritäten, reduzierst mehr Komfort-Ausgaben und schaffst deutlich spürbaren finanziellen Spielraum – ideal, um Rücklagen aufzubauen oder größere Ziele gezielt zu finanzieren.
Radikaler Cut
Potenziell frei pro Monat: 0 €
Potenziell frei pro Jahr: 0 €
Alles, was irgendwie verzichtbar ist, wird auf den Prüfstand gestellt. Dieses Szenario kann helfen, Schulden schneller abzubauen, eine größere Investition zu ermöglichen oder in kurzer Zeit ein starkes Finanzpolster aufzubauen.
💾 Daten werden automatisch lokal gespeichert

🛒 Lebensmittel-Preis-Check

Schätze deine aktuellen Preise für typische Lebensmittel. Du siehst sofort, ob du eher günstig oder teuer einkaufst – und welches Sparpotential beim Einkaufen möglich wäre.

Produkt Dein Preis
(in €)
Günstiger Richtwert Sparpotential
1 kg Hühnerfilet ab ca. 7,99 €
1 kg Mischbrot ab ca. 2,99 €
1 kg Kaffee ab ca. 9,99 €
1 kg Gouda ab ca. 7,90 €
1 kg Äpfel ab ca. 1,29 €
Geschätztes Sparpotential im Lebensmittelbudget:
Sanft: 0 € / Monat – 0 € / Jahr
Spürbar: 0 € / Monat – 0 € / Jahr
Radikal: 0 € / Monat – 0 € / Jahr

Annahme: Die Preisunterschiede bei den ausgewählten Produkten entsprechen deinem generellen Einkaufsverhalten. Die Szenarien nutzen etwa 30 %, 60 % bzw. 100 % des theoretisch möglichen Sparpotentials auf dein eingetragenes Monatsbudget für „Lebensmittel“.

Richtwerte basieren auf typischen Preisspannen in Österreich und dienen nur als Orientierung. Im Alltag hängen Preise von Marke, Aktion und Geschäft ab – entscheidend ist, dass du deine Einkaufsgewohnheiten bewusst im Blick behältst.

Dieser Haushaltsrechner unterstützt Sie dabei, Ihre finanzielle Situation besser einzuschätzen und mögliche Optionen sichtbar zu machen. Die Berechnung stellt keine Empfehlung und keine Beratung im finanziellen, steuerlichen oder rechtlichen Sinn dar. Für verbindliche Entscheidungen wenden Sie sich bitte an qualifizierte Fachpersonen.

/* ----------------------------------------------------- FORMAT-HILFSFUNKTION (EUR) ------------------------------------------------------ */ function fmtCurrency(value) { if (isNaN(value) || !isFinite(value)) value = 0; try { return new Intl.NumberFormat('de-AT', { style: 'currency', currency: 'EUR', minimumFractionDigits: 0, maximumFractionDigits: 2 }).format(value); } catch (e) { return value.toFixed(2) + ' €'; } } /* ----------------------------------------------------- LOCAL STORAGE KEY ------------------------------------------------------ */ const STORAGE_KEY = "levadis_haushaltsrechner_v2"; /* ----------------------------------------------------- DEFAULT MODELL MIT STANDARDWERTEN ------------------------------------------------------ */ const defaultModel = { userName: "", incomes: [ { name: "Gehalt 1", amount: 2500, mode: "m14" }, { name: "Gehalt 2", amount: 0, mode: "m12" }, { name: "Familienbeihilfe / Sozialleistungen", amount: 0, mode: "m12" } ], expenses: { fixedNecessary: [ { name: "Miete", amount: 900, period: "month", score: 5 }, { name: "Betriebskosten", amount: 200, period: "month", score: 4 }, { name: "Strom", amount: 80, period: "month", score: 4 }, { name: "Heizung / Gas / Fernwärme", amount: 80, period: "month", score: 4 }, { name: "Haushaltsversicherung", amount: 25, period: "month", score: 4 }, { name: "Krankenversicherung", amount: 0, period: "month", score: 5 }, { name: "Öffi-Ticket", amount: 50, period: "month", score: 4 }, { name: "KFZ – Versicherung / Steuer", amount: 0, period: "year", score: 4 }, { name: "Kinderbetreuung / Schule", amount: 0, period: "month", score: 4 } ], fixedOptional: [ { name: "Handyvertrag(e) Premium", amount: 60, period: "month", score: 3 }, { name: "Internet (Premium)", amount: 20, period: "month", score: 3 }, { name: "Streamingdienste", amount: 40, period: "month", score: 2 }, { name: "Fitnessstudio", amount: 30, period: "month", score: 2 }, { name: "Mitgliedschaften / Vereine", amount: 20, period: "month", score: 2 }, { name: "Zeitungen / Magazine / Apps", amount: 20, period: "month", score: 2 } ], variable: [ { name: "Lebensmittel", amount: 450, period: "month", score: 4 }, { name: "Restaurants / Cafés", amount: 120, period: "month", score: 2 }, { name: "Freizeit / Hobbys", amount: 100, period: "month", score: 2 }, { name: "Kleidung / Schuhe", amount: 80, period: "month", score: 2 }, { name: "Urlaub / Reisen", amount: 1200, period: "year", score: 2 }, { name: "Spontankäufe / Sonstiges", amount: 80, period: "month", score: 2 } ], debts: [ { name: "Kreditrate Konsumkredit", amount: 0, period: "month", score: 5 }, { name: "Kreditrate Auto", amount: 0, period: "month", score: 5 } ], savings: [ { name: "Notgroschen / Rücklagen", amount: 100, period: "month", score: 4 }, { name: "Sparen für Ziel A/B/C", amount: 0, period: "month", score: 3 } ] } }; /* ----------------------------------------------------- MODEL LADEN / SPEICHERN ------------------------------------------------------ */ function clone(obj) { return JSON.parse(JSON.stringify(obj)); } function loadModel() { try { const raw = localStorage.getItem(STORAGE_KEY); if (!raw) return clone(defaultModel); const parsed = JSON.parse(raw); const merged = clone(defaultModel); Object.assign(merged, parsed); merged.expenses = Object.assign({}, defaultModel.expenses, parsed.expenses || {}); return merged; } catch (e) { return clone(defaultModel); } } function saveModel() { try { localStorage.setItem(STORAGE_KEY, JSON.stringify(model)); } catch (e) { console.warn("Speichern nicht möglich:", e); } } let model = loadModel(); /* ----------------------------------------------------- TABELLEN-ELEMENTE REFERENZEN ------------------------------------------------------ */ const incomeTableBody = document.querySelector("#incomeTable tbody"); const fixedNecessaryTableBody = document.querySelector("#fixedNecessaryTable tbody"); const fixedOptionalTableBody = document.querySelector("#fixedOptionalTable tbody"); const variableTableBody = document.querySelector("#variableTable tbody"); const debtsTableBody = document.querySelector("#debtsTable tbody"); const savingsTableBody = document.querySelector("#savingsTable tbody"); /* ----------------------------------------------------- TABELLEN RENDERN ------------------------------------------------------ */ function renderTableRows() { /* ------------------ EINNAHMEN ------------------ */ incomeTableBody.innerHTML = ""; model.incomes.forEach((inc, index) => { const tr = document.createElement("tr"); tr.innerHTML = ` Monatlich (12×) Monatlich (14×) Jährlicher Betrag `; incomeTableBody.appendChild(tr); }); /* ---------------- AUSGABEN-GENERIERUNG ---------------- */ function renderExpenseRows(tbody, list, categoryKey) { tbody.innerHTML = ""; list.forEach((item, index) => { const tr = document.createElement("tr"); tr.innerHTML = ` Monat Jahr ${[1,2,3,4,5].map(s => `${s}`).join("")} `; tbody.appendChild(tr); }); } renderExpenseRows(fixedNecessaryTableBody, model.expenses.fixedNecessary, "fixedNecessary"); renderExpenseRows(fixedOptionalTableBody, model.expenses.fixedOptional, "fixedOptional"); renderExpenseRows(variableTableBody, model.expenses.variable, "variable"); renderExpenseRows(debtsTableBody, model.expenses.debts, "debts"); renderExpenseRows(savingsTableBody, model.expenses.savings, "savings"); } /* ----------------------------------------------------- MONATS-/JAHRES-UMRECHNUNG ------------------------------------------------------ */ function incomeToMonthlyYearly(inc) { const amount = Number(inc.amount) || 0; let monthly = 0, yearly = 0; if (inc.mode === "m12") { monthly = amount; yearly = amount * 12; } else if (inc.mode === "m14") { monthly = amount; yearly = amount * 14; } else { yearly = amount; monthly = amount / 12; } return { monthly, yearly }; } function expenseToMonthly(item) { const amount = Number(item.amount) || 0; return item.period === "year" ? amount / 12 : amount; } /* ----------------------------------------------------- GESAMT-SUMMEN & SZENARIEN RECHNEN ------------------------------------------------------ */ function calculateTotals() { let incomeMonthly = 0; let incomeYearly = 0; model.incomes.forEach(i => { const { monthly, yearly } = incomeToMonthlyYearly(i); incomeMonthly += monthly; incomeYearly += yearly; }); function sumCat(list) { return list.reduce((acc, item) => acc + expenseToMonthly(item), 0); } const fixedA = sumCat(model.expenses.fixedNecessary); const fixedB = sumCat(model.expenses.fixedOptional); const variable = sumCat(model.expenses.variable); const debts = sumCat(model.expenses.debts); const savings = sumCat(model.expenses.savings); const monthlyExpenses = fixedA + fixedB + variable + debts + savings; const yearlyExpenses = monthlyExpenses * 12; const saldoYear = incomeYearly - yearlyExpenses; /* Szenario-Faktoren */ const factors = { soft: {1:0.30, 2:0.20, 3:0.10, 4:0.00, 5:0.00}, medium: {1:0.60, 2:0.50, 3:0.30, 4:0.10, 5:0.00}, hard: {1:1.00, 2:0.80, 3:0.50, 4:0.30, 5:0.10} }; function scenarioReduce(list, key) { return list.reduce((sum, item) => { const base = expenseToMonthly(item); const score = Number(item.score) || 3; return sum + base * (factors[key][score] || 0); }, 0); } /* Nur diese Kategorien werden gekürzt */ const scenarioMonthly = { soft: scenarioReduce(model.expenses.fixedNecessary, "soft") + scenarioReduce(model.expenses.fixedOptional, "soft") + scenarioReduce(model.expenses.variable, "soft"), medium: scenarioReduce(model.expenses.fixedNecessary, "medium") + scenarioReduce(model.expenses.fixedOptional, "medium") + scenarioReduce(model.expenses.variable, "medium"), hard: scenarioReduce(model.expenses.fixedNecessary, "hard") + scenarioReduce(model.expenses.fixedOptional, "hard") + scenarioReduce(model.expenses.variable, "hard") }; return { incomeMonthly, incomeYearly, yearlyExpenses, saldoYear, scenarioMonthly, scenarioYearly: { soft: scenarioMonthly.soft * 12, medium: scenarioMonthly.medium * 12, hard: scenarioMonthly.hard * 12 }, category: { fixedA, fixedB, variable, debts, savings } }; } /* ----------------------------------------------------- UI AKTUALISIEREN ------------------------------------------------------ */ function updateSummaryUI() { const t = calculateTotals(); /* Einnahmen */ document.getElementById("incomeMonthlySum").textContent = fmtCurrency(t.incomeMonthly); document.getElementById("incomeYearlySum").textContent = fmtCurrency(t.incomeYearly); /* Kategorien */ document.getElementById("fixedNecessaryMonthlySum").textContent = fmtCurrency(t.category.fixedA); document.getElementById("fixedOptionalMonthlySum").textContent = fmtCurrency(t.category.fixedB); document.getElementById("variableMonthlySum").textContent = fmtCurrency(t.category.variable); document.getElementById("debtsMonthlySum").textContent = fmtCurrency(t.category.debts); document.getElementById("savingsMonthlySum").textContent = fmtCurrency(t.category.savings); /* Jahres-Summen */ document.getElementById("sumIncomeYear").textContent = fmtCurrency(t.incomeYearly); document.getElementById("sumExpensesYear").textContent = fmtCurrency(t.yearlyExpenses); document.getElementById("saldoYear").textContent = fmtCurrency(t.saldoYear); /* Szenarien */ document.getElementById("softMonth").textContent = fmtCurrency(t.scenarioMonthly.soft); document.getElementById("softYear").textContent = fmtCurrency(t.scenarioYearly.soft); document.getElementById("mediumMonth").textContent = fmtCurrency(t.scenarioMonthly.medium); document.getElementById("mediumYear").textContent = fmtCurrency(t.scenarioYearly.medium); document.getElementById("hardMonth").textContent = fmtCurrency(t.scenarioMonthly.hard); document.getElementById("hardYear").textContent = fmtCurrency(t.scenarioYearly.hard); /* Sanft-Szenario – Text ersetzen */ const softText = document.getElementById("softText"); softText.textContent = `Im sanften Szenario würdest du ohne große Einschränkungen etwa ${fmtCurrency(t.scenarioMonthly.soft)} pro Monat ` + `freispielen. Das sind jährlich ${fmtCurrency(t.scenarioYearly.soft)} frei verfügbar – damit kannst du auf etwas ` + `ansparen, dir einen Puffer aufbauen oder dir andere schöne Dinge gönnen. Wenn du Kreditraten hast, kann dieser ` + `Betrag auch helfen, deine finanziellen Verpflichtungen spürbar zu reduzieren.`; } /* Block 4 folgt … */ /* ----------------------------------------------------- TABELLE → INPUT CHANGE HANDLING ------------------------------------------------------ */ function onTableInputChange(e) { const el = e.target; const type = el.dataset.type; const field = el.dataset.field; const index = parseInt(el.dataset.index, 10); if (!type || isNaN(index)) return; if (type === "income") { if (field === "name") model.incomes[index].name = el.value; if (field === "amount") model.incomes[index].amount = Number(el.value) || 0; if (field === "mode") model.incomes[index].mode = el.value; } else { const list = model.expenses[type]; if (!list) return; if (field === "name") list[index].name = el.value; if (field === "amount") list[index].amount = Number(el.value) || 0; if (field === "period") list[index].period = el.value; if (field === "score") list[index].score = Number(el.value) || 3; } saveModel(); updateSummaryUI(); } /* ----------------------------------------------------- TABELLE → BUTTON EVENTS (REMOVE) ------------------------------------------------------ */ function onTableButtonClick(e) { const btn = e.target.closest("button"); if (!btn) return; const action = btn.dataset.action; const index = parseInt(btn.dataset.index, 10); const category = btn.dataset.category; if (!action) return; /* Einnahme entfernen */ if (action === "remove-income") { model.incomes.splice(index, 1); /* Wenn alle weg → eine leere Zeile erzeugen */ if (model.incomes.length === 0) { model.incomes.push({ name: "Einnahme", amount: 0, mode: "m12" }); } } /* Ausgaben entfernen */ if (action === "remove-expense" && category) { if (model.expenses[category]) { model.expenses[category].splice(index, 1); } } saveModel(); renderTableRows(); updateSummaryUI(); } function updateQuiz() { const rows = document.querySelectorAll("#quizTable tbody tr"); let totalDiff = 0; // Summe der theoretisch möglichen Einsparung pro Einheit let totalPaid = 0; // Summe der aktuell gezahlten Preise rows.forEach(row => { const low = parseFloat(row.dataset.low); const high = parseFloat(row.dataset.high); const input = row.querySelector("input.quiz-price"); const saveCell = row.querySelector(".quiz-save"); if (!input || !saveCell || isNaN(low) || isNaN(high)) return; const raw = (input.value || "").replace(",", "."); const val = parseFloat(raw); if (isNaN(val) || val <= 0) { saveCell.textContent = "–"; return; } // Summe der gezahlten Preise totalPaid += val; const diff = val - low; if (diff <= 0) { saveCell.textContent = "Du liegst bereits im günstigen Bereich."; return; } totalDiff += diff; const span = high - low; let hint; if (diff < span * 0.3) { hint = "leicht teurer – kleines Sparpotential."; } else if (diff 0 && totalDiff > 0) { relativePotential = totalDiff / totalPaid; if (relativePotential > 1) relativePotential = 1; } // Lebensmittel-Monatsbudget aus der Kategorie "variable" → Position "Lebensmittel" let lebensmittelMonthly = 0; try { const list = (model.expenses && model.expenses.variable) ? model.expenses.variable : []; const item = list.find(it => (it.name || "").toLowerCase().startsWith("lebensmittel")); if (item) { lebensmittelMonthly = expenseToMonthly(item); // Funktion aus Block 3 } } catch (e) { console.warn("Konnte Lebensmittel-Budget nicht auslesen:", e); } // theoretisches Sparpotential auf das gesamte Lebensmittelbudget const theoreticalMonthly = lebensmittelMonthly * relativePotential; // Drei Szenarien: sanft ~30 %, spürbar ~60 %, radikal ~100 % des theoretischen Potentials const factorSoft = 0.30; const factorMedium = 0.60; const factorHard = 1.00; const softMonth = theoreticalMonthly * factorSoft; const mediumMonth = theoreticalMonthly * factorMedium; const hardMonth = theoreticalMonthly * factorHard; const softYear = softMonth * 12; const mediumYear = mediumMonth * 12; const hardYear = hardMonth * 12; // Werte ins UI schreiben document.getElementById("quizSoftMonth").textContent = fmtCurrency(softMonth); document.getElementById("quizSoftYear").textContent = fmtCurrency(softYear); document.getElementById("quizMediumMonth").textContent = fmtCurrency(mediumMonth); document.getElementById("quizMediumYear").textContent = fmtCurrency(mediumYear); document.getElementById("quizHardMonth").textContent = fmtCurrency(hardMonth); document.getElementById("quizHardYear").textContent = fmtCurrency(hardYear); } /* ----------------------------------------------------- PDF EXPORT ------------------------------------------------------ */ async function downloadPdf() { const { jsPDF } = window.jspdf; const doc = new jsPDF(); const t = calculateTotals(); const userName = model.userName ? ` – ${model.userName}` : ""; let y = 14; doc.setFont("helvetica", "bold"); doc.setFontSize(14); doc.text(`LEVADIS® Haushalts-Summary${userName}`, 14, y); y += 8; doc.setFontSize(10); doc.setFont("helvetica", "normal"); doc.text(`Jahres-Einnahmen: ${fmtCurrency(t.incomeYearly)}`, 14, y); y += 5; doc.text(`Jahres-Ausgaben (Ist): ${fmtCurrency(t.yearlyExpenses)}`, 14, y); y += 5; doc.text(`Saldo (Ist): ${fmtCurrency(t.saldoYear)}`, 14, y); y += 8; doc.setFont("helvetica", "bold"); doc.text("Spar-Szenarien:", 14, y); y += 6; doc.setFont("helvetica", "normal"); doc.text(`Sanft: ${fmtCurrency(t.scenarioMonthly.soft)} / Monat – ${fmtCurrency(t.scenarioYearly.soft)} / Jahr`, 14, y); y += 5; doc.text(`Spürbar: ${fmtCurrency(t.scenarioMonthly.medium)} / Monat – ${fmtCurrency(t.scenarioYearly.medium)} / Jahr`, 14, y); y += 5; doc.text(`Radikal: ${fmtCurrency(t.scenarioMonthly.hard)} / Monat – ${fmtCurrency(t.scenarioYearly.hard)} / Jahr`, 14, y); y += 10; const sanft = `Im sanften Szenario würdest du ohne große Einschränkungen etwa ${fmtCurrency(t.scenarioMonthly.soft)} pro Monat freispielen. ` + `Das sind jährlich ${fmtCurrency(t.scenarioYearly.soft)} frei verfügbar – damit kannst du ansparen, einen Puffer aufbauen ` + `oder dir andere schöne Dinge gönnen. Wenn du Kreditraten hast, kann dieser Betrag helfen, Verpflichtungen spürbar zu reduzieren.`; const wrapped = doc.splitTextToSize(sanft, 180); doc.text(wrapped, 14, y); y += wrapped.length * 4 + 4; doc.setFontSize(8); doc.setTextColor(120); doc.text("Hinweis: Alle Werte sind Schätzungen auf Basis deiner Eingaben.", 14, y); doc.save("levadis-haushalts-summary.pdf"); } /* ----------------------------------------------------- EVENTHANDLER / INITIALISIERUNG ------------------------------------------------------ */ function attachEvents() { /* Name speichern */ const nameInput = document.getElementById("userName"); nameInput.value = model.userName; nameInput.addEventListener("input", () => { model.userName = nameInput.value; saveModel(); }); /* Tabellen -> Input Events */ [ incomeTableBody, fixedNecessaryTableBody, fixedOptionalTableBody, variableTableBody, debtsTableBody, savingsTableBody ].forEach(tbody => { tbody.addEventListener("input", onTableInputChange); tbody.addEventListener("change", onTableInputChange); tbody.addEventListener("click", onTableButtonClick); }); /* ADD Buttons */ document.getElementById("addIncomeBtn").addEventListener("click", () => { model.incomes.push({ name: "Weitere Einnahme", amount: 0, mode: "m12" }); saveModel(); renderTableRows(); updateSummaryUI(); }); document.getElementById("addFixedNecessaryBtn").addEventListener("click", () => { model.expenses.fixedNecessary.push({ name: "Neue Position", amount: 0, period: "month", score: 5 }); saveModel(); renderTableRows(); updateSummaryUI(); }); document.getElementById("addFixedOptionalBtn").addEventListener("click", () => { model.expenses.fixedOptional.push({ name: "Neue Position", amount: 0, period: "month", score: 3 }); saveModel(); renderTableRows(); updateSummaryUI(); }); document.getElementById("addVariableBtn").addEventListener("click", () => { model.expenses.variable.push({ name: "Neue Position", amount: 0, period: "month", score: 3 }); saveModel(); renderTableRows(); updateSummaryUI(); }); document.getElementById("addDebtBtn").addEventListener("click", () => { model.expenses.debts.push({ name: "Neue Position", amount: 0, period: "month", score: 5 }); saveModel(); renderTableRows(); updateSummaryUI(); }); document.getElementById("addSavingBtn").addEventListener("click", () => { model.expenses.savings.push({ name: "Neue Position", amount: 0, period: "month", score: 4 }); saveModel(); renderTableRows(); updateSummaryUI(); }); /* RESET */ document.getElementById("resetBtn").addEventListener("click", () => { if (!confirm("Alle Eingaben auf Standardwerte zurücksetzen?")) return; localStorage.removeItem(STORAGE_KEY); model = clone(defaultModel); nameInput.value = ""; renderTableRows(); updateSummaryUI(); saveModel(); }); /* ALLES LÖSCHEN */ document.getElementById("clearAllBtn").addEventListener("click", () => { if (!confirm("Möchtest du wirklich ALLE Eingaben löschen?")) return; localStorage.removeItem(STORAGE_KEY); model = { userName: "", incomes: [{ name: "Einnahme", amount: 0, mode: "m12" }], expenses: { fixedNecessary: [], fixedOptional: [], variable: [], debts: [], savings: [] } }; nameInput.value = ""; renderTableRows(); updateSummaryUI(); saveModel(); }); /* Accordion */ document.querySelectorAll(".lev-toggle-btn").forEach(btn => { btn.addEventListener("click", () => { const tgt = document.getElementById(btn.dataset.target); const collapsed = tgt.classList.toggle("collapsed"); btn.querySelector(".icon").textContent = collapsed ? "▸" : "▾"; }); }); /* PDF */ document.getElementById("pdfBtn").addEventListener("click", downloadPdf); /* Quiz */ const quizTable = document.getElementById("quizTable"); quizTable.addEventListener("input", updateQuiz); quizTable.addEventListener("change", updateQuiz); } /* ----------------------------------------------------- START ------------------------------------------------------ */ renderTableRows(); updateSummaryUI(); attachEvents(); updateQuiz();
© LEVADIS® – Organisationswirksamkeit · Vom Müssen zum Wollen · Culture Ladder & Culture Sprints
// aktuelles Jahr im Footer document.getElementById('year').textContent = new Date().getFullYear();