feat: Zweite Stufe der iOS-App - Uebersicht, Budget, Buchungen, Vertraege
Die App kann jetzt lesen, wofuer man sie oeffnet. Vier neue Reiter: - Uebersicht: Einnahmen/Ausgaben des Monats, Budget-Fortschritt je Gruppe, Kontostaende und die letzten Buchungen. Feste Auswahl statt des verschiebbaren Rasters der Weboberflaeche - auf Telefonbreite waere das Arbeit ohne Gewinn. Vier Endpunkte nebeneinander in einem Abruf, damit der Offline-Stand nicht aus vier verschiedenen Momenten stammt. - Budget: Soll gegen Ist je Gruppe und Kategorie, blaetterbar ueber prev/next aus der Antwort. Rot nur bei echter Ueberschreitung - wer mehr zuruecklegt als geplant, hat nichts ueberzogen. Vertraege ohne Kategorie und fehlende Wechselkurse stehen als Hinweis darunter, statt die Summen still zu verfaelschen. - Buchungen: Suche und Filter laufen im Server (Backend-Ergaenzung B), nicht im Telefon. Gesucht wird beim Absenden, nicht je Tastendruck. - Vertraege: Monats- und Jahressumme, Rhythmus, naechste Faelligkeit. Zwei Dinge, die das Backend bewusst dem Client ueberlaesst: Ein Uebertrag kommt in zwei Gestalten - am Stueck (eine Buchung mit to_account_id) oder als zwei verknuepfte Buchungen, wie die Bank sie liefert. Beide Beine als zwei Zeilen zu zeigen hiesse, dasselbe Geld zweimal zu zeigen. Buchungszeile.zeilen fasst sie zusammen, aber nur wenn beide in der Liste stehen - sonst liesse ein Kontofilter Zeilen verschwinden, die sehr wohl zu diesem Konto gehoeren. Die Richtung kommt aus der Verknuepfung, nicht aus dem Vorzeichen: Manche Banken liefern beide Beine positiv. Kategorien, Schlagwoerter und Konten liegen als Nachschlagewerk im AppZustand, einmal geladen. Je Ansicht neu zu holen waere genau das N+1, das das Backend sich selbst verbietet. Texte in Deutsch und Englisch, zeilengleich. 44 Tests gruen, darunter die Uebertrags-Paarung und jedes Modell gegen eine echte Serverantwort. Nicht geprueft: der Weg gegen ein echtes Backend. Die App laesst nur https zu, ein lokaler Server haette eine ATS-Ausnahme gebraucht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,8 +8,13 @@
|
||||
"allgemein.nochmal" = "Nochmal versuchen";
|
||||
"allgemein.abbrechen" = "Abbrechen";
|
||||
"allgemein.abmelden" = "Abmelden";
|
||||
"allgemein.unbekannt" = "Unbekannt";
|
||||
|
||||
/* --- Reiter --- */
|
||||
"reiter.dashboard" = "Übersicht";
|
||||
"reiter.budget" = "Budget";
|
||||
"reiter.buchungen" = "Buchungen";
|
||||
"reiter.abos" = "Verträge";
|
||||
"reiter.konten" = "Konten";
|
||||
"reiter.einstellungen" = "Einstellungen";
|
||||
|
||||
@@ -102,3 +107,59 @@
|
||||
"einstellungen.budgetStarttag" = "Budget beginnt am";
|
||||
"einstellungen.abmeldenFrage" = "Von diesem Gerät abmelden?";
|
||||
"einstellungen.abmeldenErklaerung" = "Beim Abmelden wird der Schlüssel dieses Geräts auch am Server entfernt.";
|
||||
|
||||
/* --- Dashboard --- */
|
||||
"dashboard.bilanz" = "Dieser Monat";
|
||||
"dashboard.einnahmen" = "Einnahmen";
|
||||
"dashboard.ausgaben" = "Ausgaben";
|
||||
"dashboard.budgetfortschritt" = "Budget";
|
||||
"dashboard.keinBudget" = "Für diesen Monat ist noch nichts geplant.";
|
||||
"dashboard.kontostaende" = "Konten";
|
||||
"dashboard.letzteBuchungen" = "Zuletzt";
|
||||
|
||||
/* --- Budget --- */
|
||||
"budget.einnahmen" = "Geplante Einnahmen";
|
||||
"budget.uebrig" = "übrig";
|
||||
"budget.vonGeplant" = "%1$@ von %2$@ ausgegeben";
|
||||
"budget.vonBetrag" = "von %@";
|
||||
"budget.angepasst" = "angepasst";
|
||||
"budget.vorigerMonat" = "Voriger Monat";
|
||||
"budget.naechsterMonat" = "Nächster Monat";
|
||||
"budget.ausVertraegenHinweis" = "%1$d Verträge: %2$@";
|
||||
"budget.ausVertraegenBerechnet" = "Berechnet aus %1$d Verträgen: %2$@";
|
||||
"budget.vertraegeOhneKategorie" = "%1$d Verträge ohne Kategorie (%2$@) fehlen in diesen Summen.";
|
||||
"budget.ohneKurs" = "Kein Wechselkurs für %@ – diese Beträge fehlen in den Summen.";
|
||||
|
||||
/* --- Buchungen --- */
|
||||
"buchungen.suchen" = "Empfänger, Zweck, Notiz";
|
||||
"buchungen.konto" = "Konto";
|
||||
"buchungen.alleKonten" = "Alle Konten";
|
||||
"buchungen.art" = "Art";
|
||||
"buchungen.alleArten" = "Alle Arten";
|
||||
"buchungen.leerTitel" = "Keine Buchungen";
|
||||
"buchungen.leerErklaerung" = "Sobald etwas gebucht ist, steht es hier.";
|
||||
"buchungen.leerGefiltert" = "Zu dieser Suche gibt es nichts. Andere Filter versuchen?";
|
||||
"buchung.ohneBezeichnung" = "Ohne Bezeichnung";
|
||||
"buchung.ohneKategorie" = "Ohne Kategorie";
|
||||
"buchung.uebertrag" = "Übertrag";
|
||||
|
||||
/* --- Buchungsarten --- */
|
||||
"buchungsart.ausgabe" = "Ausgabe";
|
||||
"buchungsart.einnahme" = "Einnahme";
|
||||
"buchungsart.uebertrag" = "Übertrag";
|
||||
|
||||
/* --- Verträge --- */
|
||||
"abos.leerTitel" = "Keine Verträge";
|
||||
"abos.leerErklaerung" = "Hier stehen Abos und Verträge, sobald welche angelegt sind.";
|
||||
"abos.beendeteZeigen" = "Beendete zeigen";
|
||||
"abos.beendet" = "beendet";
|
||||
"abos.jaehrlichUndAnzahl" = "%1$@ im Jahr · %2$d aktiv";
|
||||
"abos.ohneKurs" = "Kein Wechselkurs für %@ – diese Verträge fehlen in der Summe.";
|
||||
"abo.monatlich" = "monatlich";
|
||||
"abo.vierteljaehrlich" = "vierteljährlich";
|
||||
"abo.halbjaehrlich" = "halbjährlich";
|
||||
"abo.jaehrlich" = "jährlich";
|
||||
"abo.alleNMonate" = "alle %d Monate";
|
||||
"abo.proMonat" = "%@ im Monat";
|
||||
"abo.naechste" = "nächste am %@";
|
||||
"abo.inTagen" = "fällig in %d Tagen";
|
||||
|
||||
@@ -8,8 +8,13 @@
|
||||
"allgemein.nochmal" = "Try again";
|
||||
"allgemein.abbrechen" = "Cancel";
|
||||
"allgemein.abmelden" = "Sign out";
|
||||
"allgemein.unbekannt" = "Unknown";
|
||||
|
||||
/* --- Tabs --- */
|
||||
"reiter.dashboard" = "Overview";
|
||||
"reiter.budget" = "Budget";
|
||||
"reiter.buchungen" = "Transactions";
|
||||
"reiter.abos" = "Subscriptions";
|
||||
"reiter.konten" = "Accounts";
|
||||
"reiter.einstellungen" = "Settings";
|
||||
|
||||
@@ -102,3 +107,59 @@
|
||||
"einstellungen.budgetStarttag" = "Budget starts on";
|
||||
"einstellungen.abmeldenFrage" = "Sign out on this device?";
|
||||
"einstellungen.abmeldenErklaerung" = "Signing out also removes this device's key on the server.";
|
||||
|
||||
/* --- Dashboard --- */
|
||||
"dashboard.bilanz" = "This month";
|
||||
"dashboard.einnahmen" = "Income";
|
||||
"dashboard.ausgaben" = "Expenses";
|
||||
"dashboard.budgetfortschritt" = "Budget";
|
||||
"dashboard.keinBudget" = "Nothing planned for this month yet.";
|
||||
"dashboard.kontostaende" = "Accounts";
|
||||
"dashboard.letzteBuchungen" = "Recent";
|
||||
|
||||
/* --- Budget --- */
|
||||
"budget.einnahmen" = "Planned income";
|
||||
"budget.uebrig" = "left";
|
||||
"budget.vonGeplant" = "%1$@ of %2$@ spent";
|
||||
"budget.vonBetrag" = "of %@";
|
||||
"budget.angepasst" = "adjusted";
|
||||
"budget.vorigerMonat" = "Previous month";
|
||||
"budget.naechsterMonat" = "Next month";
|
||||
"budget.ausVertraegenHinweis" = "%1$d subscriptions: %2$@";
|
||||
"budget.ausVertraegenBerechnet" = "Calculated from %1$d subscriptions: %2$@";
|
||||
"budget.vertraegeOhneKategorie" = "%1$d subscriptions without a category (%2$@) are missing from these totals.";
|
||||
"budget.ohneKurs" = "No exchange rate for %@ – those amounts are missing from the totals.";
|
||||
|
||||
/* --- Transactions --- */
|
||||
"buchungen.suchen" = "Payee, description, note";
|
||||
"buchungen.konto" = "Account";
|
||||
"buchungen.alleKonten" = "All accounts";
|
||||
"buchungen.art" = "Type";
|
||||
"buchungen.alleArten" = "All types";
|
||||
"buchungen.leerTitel" = "No transactions";
|
||||
"buchungen.leerErklaerung" = "Once something is booked, it shows up here.";
|
||||
"buchungen.leerGefiltert" = "Nothing matches this search. Try different filters?";
|
||||
"buchung.ohneBezeichnung" = "Untitled";
|
||||
"buchung.ohneKategorie" = "No category";
|
||||
"buchung.uebertrag" = "Transfer";
|
||||
|
||||
/* --- Transaction types --- */
|
||||
"buchungsart.ausgabe" = "Expense";
|
||||
"buchungsart.einnahme" = "Income";
|
||||
"buchungsart.uebertrag" = "Transfer";
|
||||
|
||||
/* --- Subscriptions --- */
|
||||
"abos.leerTitel" = "No subscriptions";
|
||||
"abos.leerErklaerung" = "Subscriptions and contracts show up here once you add them.";
|
||||
"abos.beendeteZeigen" = "Show cancelled";
|
||||
"abos.beendet" = "cancelled";
|
||||
"abos.jaehrlichUndAnzahl" = "%1$@ per year · %2$d active";
|
||||
"abos.ohneKurs" = "No exchange rate for %@ – those subscriptions are missing from the total.";
|
||||
"abo.monatlich" = "monthly";
|
||||
"abo.vierteljaehrlich" = "quarterly";
|
||||
"abo.halbjaehrlich" = "twice a year";
|
||||
"abo.jaehrlich" = "yearly";
|
||||
"abo.alleNMonate" = "every %d months";
|
||||
"abo.proMonat" = "%@ per month";
|
||||
"abo.naechste" = "next on %@";
|
||||
"abo.inTagen" = "due in %d days";
|
||||
|
||||
Reference in New Issue
Block a user