feat(todo): Reporting, with goals, streaks and what was done (ADR 0033, D36)

A daily and a weekly goal, each with its progress, streak and chart, days
off and vacation mode, and the history of completed tasks by project, all
worked out on the device from what the tasks keep. Today shows a quiet card
once a day when the goal is reached. No karma, nothing to share.

Whats-New: Reporting: set a daily and a weekly goal, follow your streaks and see what you've done, with days off and vacation, under Browse.
Whats-New-De: Auswertung: Lege ein Tages- und ein Wochenziel fest, verfolge deine Serien und sieh, was du erledigt hast, mit freien Tagen und Urlaub, in der Übersicht.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-11-06 19:58:53 +01:00
commit bd1b19ed32
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64
5 changed files with 1651 additions and 3 deletions

View file

@ -64,6 +64,33 @@
"commentDelete": "Kommentar löschen",
"commentDeleteTitle": "Kommentar löschen?",
"commentEdited": "{when}, bearbeitet",
"reportingTitle": "Auswertung",
"reportingHint": "Ziele, Serien und was du erledigt hast",
"reportingDaily": "Täglich",
"reportingWeekly": "Wöchentlich",
"reportingHistory": "Verlauf",
"reportingLast7Days": "Erledigt in den letzten 7 Tagen",
"reportingLast4Weeks": "Erledigt in den letzten 4 Wochen",
"historyProject": "Projekt",
"historyAllProjects": "Alle Projekte",
"historyNothing": "Noch nichts erledigt.",
"goalsDaily": "Aufgaben am Tag",
"goalsWeekly": "Aufgaben in der Woche",
"goalsDaysOff": "Freie Tage",
"goalsVacation": "Urlaub",
"goalsVacationHint": "Serien warten, bis du zurück bist",
"goalsEdit": "Ziele bearbeiten",
"goalsDailyTitle": "Tagesziel",
"goalsWeeklyTitle": "Wochenziel",
"goalsDailyStreak": "Tagesserie",
"goalsWeeklyStreak": "Wochenserie",
"goalsOnVacation": "Im Urlaub",
"goalsProgress": "{done} von {goal} Aufgaben",
"goalsLongest": "Längste: {length} ({from} bis {to})",
"goalsDays": "{count, plural, =1{1 Tag} other{{count} Tage}}",
"goalsWeeks": "{count, plural, =1{1 Woche} other{{count} Wochen}}",
"reportingTasks": "{count, plural, =1{1 Aufgabe} other{{count} Aufgaben}}",
"goalsReached": "Tagesziel erreicht: heute {count, plural, =1{1 Aufgabe} other{{count} Aufgaben}} erledigt.",
"labelsTitle": "Labels",
"labelsNone": "Noch keine Labels.",
"labelsNoneSet": "Keine Labels",

View file

@ -132,6 +132,84 @@
}
}
},
"reportingTitle": "Reporting",
"reportingHint": "Goals, streaks and what you've done",
"reportingDaily": "Daily",
"reportingWeekly": "Weekly",
"reportingHistory": "History",
"reportingLast7Days": "Done in the last 7 days",
"reportingLast4Weeks": "Done in the last 4 weeks",
"historyProject": "Project",
"historyAllProjects": "All projects",
"historyNothing": "Nothing done yet.",
"goalsDaily": "Tasks a day",
"goalsWeekly": "Tasks a week",
"goalsDaysOff": "Days off",
"goalsVacation": "Vacation",
"goalsVacationHint": "Streaks wait until you're back",
"goalsEdit": "Edit goals",
"goalsDailyTitle": "Daily goal",
"goalsWeeklyTitle": "Weekly goal",
"goalsDailyStreak": "Daily streak",
"goalsWeeklyStreak": "Weekly streak",
"goalsOnVacation": "On vacation",
"goalsProgress": "{done} of {goal} tasks",
"@goalsProgress": {
"placeholders": {
"done": {
"type": "int"
},
"goal": {
"type": "int"
}
}
},
"goalsLongest": "Longest: {length} ({from} to {to})",
"@goalsLongest": {
"placeholders": {
"length": {
"type": "String"
},
"from": {
"type": "String"
},
"to": {
"type": "String"
}
}
},
"goalsDays": "{count, plural, =1{1 day} other{{count} days}}",
"@goalsDays": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"goalsWeeks": "{count, plural, =1{1 week} other{{count} weeks}}",
"@goalsWeeks": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"reportingTasks": "{count, plural, =1{1 task} other{{count} tasks}}",
"@reportingTasks": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"goalsReached": "Daily goal reached: {count, plural, =1{1 task} other{{count} tasks}} done today.",
"@goalsReached": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"labelsTitle": "Labels",
"labelsNone": "No labels yet.",
"labelsNoneSet": "No labels",

View file

@ -484,6 +484,168 @@ abstract class AppLocalizations {
/// **'{when}, edited'**
String commentEdited(String when);
/// No description provided for @reportingTitle.
///
/// In en, this message translates to:
/// **'Reporting'**
String get reportingTitle;
/// No description provided for @reportingHint.
///
/// In en, this message translates to:
/// **'Goals, streaks and what you\'ve done'**
String get reportingHint;
/// No description provided for @reportingDaily.
///
/// In en, this message translates to:
/// **'Daily'**
String get reportingDaily;
/// No description provided for @reportingWeekly.
///
/// In en, this message translates to:
/// **'Weekly'**
String get reportingWeekly;
/// No description provided for @reportingHistory.
///
/// In en, this message translates to:
/// **'History'**
String get reportingHistory;
/// No description provided for @reportingLast7Days.
///
/// In en, this message translates to:
/// **'Done in the last 7 days'**
String get reportingLast7Days;
/// No description provided for @reportingLast4Weeks.
///
/// In en, this message translates to:
/// **'Done in the last 4 weeks'**
String get reportingLast4Weeks;
/// No description provided for @historyProject.
///
/// In en, this message translates to:
/// **'Project'**
String get historyProject;
/// No description provided for @historyAllProjects.
///
/// In en, this message translates to:
/// **'All projects'**
String get historyAllProjects;
/// No description provided for @historyNothing.
///
/// In en, this message translates to:
/// **'Nothing done yet.'**
String get historyNothing;
/// No description provided for @goalsDaily.
///
/// In en, this message translates to:
/// **'Tasks a day'**
String get goalsDaily;
/// No description provided for @goalsWeekly.
///
/// In en, this message translates to:
/// **'Tasks a week'**
String get goalsWeekly;
/// No description provided for @goalsDaysOff.
///
/// In en, this message translates to:
/// **'Days off'**
String get goalsDaysOff;
/// No description provided for @goalsVacation.
///
/// In en, this message translates to:
/// **'Vacation'**
String get goalsVacation;
/// No description provided for @goalsVacationHint.
///
/// In en, this message translates to:
/// **'Streaks wait until you\'re back'**
String get goalsVacationHint;
/// No description provided for @goalsEdit.
///
/// In en, this message translates to:
/// **'Edit goals'**
String get goalsEdit;
/// No description provided for @goalsDailyTitle.
///
/// In en, this message translates to:
/// **'Daily goal'**
String get goalsDailyTitle;
/// No description provided for @goalsWeeklyTitle.
///
/// In en, this message translates to:
/// **'Weekly goal'**
String get goalsWeeklyTitle;
/// No description provided for @goalsDailyStreak.
///
/// In en, this message translates to:
/// **'Daily streak'**
String get goalsDailyStreak;
/// No description provided for @goalsWeeklyStreak.
///
/// In en, this message translates to:
/// **'Weekly streak'**
String get goalsWeeklyStreak;
/// No description provided for @goalsOnVacation.
///
/// In en, this message translates to:
/// **'On vacation'**
String get goalsOnVacation;
/// No description provided for @goalsProgress.
///
/// In en, this message translates to:
/// **'{done} of {goal} tasks'**
String goalsProgress(int done, int goal);
/// No description provided for @goalsLongest.
///
/// In en, this message translates to:
/// **'Longest: {length} ({from} to {to})'**
String goalsLongest(String length, String from, String to);
/// No description provided for @goalsDays.
///
/// In en, this message translates to:
/// **'{count, plural, =1{1 day} other{{count} days}}'**
String goalsDays(int count);
/// No description provided for @goalsWeeks.
///
/// In en, this message translates to:
/// **'{count, plural, =1{1 week} other{{count} weeks}}'**
String goalsWeeks(int count);
/// No description provided for @reportingTasks.
///
/// In en, this message translates to:
/// **'{count, plural, =1{1 task} other{{count} tasks}}'**
String reportingTasks(int count);
/// No description provided for @goalsReached.
///
/// In en, this message translates to:
/// **'Daily goal reached: {count, plural, =1{1 task} other{{count} tasks}} done today.'**
String goalsReached(int count);
/// No description provided for @labelsTitle.
///
/// In en, this message translates to:

View file

@ -232,6 +232,123 @@ class AppLocalizationsDe extends AppLocalizations {
return '$when, bearbeitet';
}
@override
String get reportingTitle => 'Auswertung';
@override
String get reportingHint => 'Ziele, Serien und was du erledigt hast';
@override
String get reportingDaily => 'Täglich';
@override
String get reportingWeekly => 'Wöchentlich';
@override
String get reportingHistory => 'Verlauf';
@override
String get reportingLast7Days => 'Erledigt in den letzten 7 Tagen';
@override
String get reportingLast4Weeks => 'Erledigt in den letzten 4 Wochen';
@override
String get historyProject => 'Projekt';
@override
String get historyAllProjects => 'Alle Projekte';
@override
String get historyNothing => 'Noch nichts erledigt.';
@override
String get goalsDaily => 'Aufgaben am Tag';
@override
String get goalsWeekly => 'Aufgaben in der Woche';
@override
String get goalsDaysOff => 'Freie Tage';
@override
String get goalsVacation => 'Urlaub';
@override
String get goalsVacationHint => 'Serien warten, bis du zurück bist';
@override
String get goalsEdit => 'Ziele bearbeiten';
@override
String get goalsDailyTitle => 'Tagesziel';
@override
String get goalsWeeklyTitle => 'Wochenziel';
@override
String get goalsDailyStreak => 'Tagesserie';
@override
String get goalsWeeklyStreak => 'Wochenserie';
@override
String get goalsOnVacation => 'Im Urlaub';
@override
String goalsProgress(int done, int goal) {
return '$done von $goal Aufgaben';
}
@override
String goalsLongest(String length, String from, String to) {
return 'Längste: $length ($from bis $to)';
}
@override
String goalsDays(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count Tage',
one: '1 Tag',
);
return '$_temp0';
}
@override
String goalsWeeks(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count Wochen',
one: '1 Woche',
);
return '$_temp0';
}
@override
String reportingTasks(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count Aufgaben',
one: '1 Aufgabe',
);
return '$_temp0';
}
@override
String goalsReached(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count Aufgaben',
one: '1 Aufgabe',
);
return 'Tagesziel erreicht: heute $_temp0 erledigt.';
}
@override
String get labelsTitle => 'Labels';

View file

@ -232,6 +232,123 @@ class AppLocalizationsEn extends AppLocalizations {
return '$when, edited';
}
@override
String get reportingTitle => 'Reporting';
@override
String get reportingHint => 'Goals, streaks and what you\'ve done';
@override
String get reportingDaily => 'Daily';
@override
String get reportingWeekly => 'Weekly';
@override
String get reportingHistory => 'History';
@override
String get reportingLast7Days => 'Done in the last 7 days';
@override
String get reportingLast4Weeks => 'Done in the last 4 weeks';
@override
String get historyProject => 'Project';
@override
String get historyAllProjects => 'All projects';
@override
String get historyNothing => 'Nothing done yet.';
@override
String get goalsDaily => 'Tasks a day';
@override
String get goalsWeekly => 'Tasks a week';
@override
String get goalsDaysOff => 'Days off';
@override
String get goalsVacation => 'Vacation';
@override
String get goalsVacationHint => 'Streaks wait until you\'re back';
@override
String get goalsEdit => 'Edit goals';
@override
String get goalsDailyTitle => 'Daily goal';
@override
String get goalsWeeklyTitle => 'Weekly goal';
@override
String get goalsDailyStreak => 'Daily streak';
@override
String get goalsWeeklyStreak => 'Weekly streak';
@override
String get goalsOnVacation => 'On vacation';
@override
String goalsProgress(int done, int goal) {
return '$done of $goal tasks';
}
@override
String goalsLongest(String length, String from, String to) {
return 'Longest: $length ($from to $to)';
}
@override
String goalsDays(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count days',
one: '1 day',
);
return '$_temp0';
}
@override
String goalsWeeks(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count weeks',
one: '1 week',
);
return '$_temp0';
}
@override
String reportingTasks(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count tasks',
one: '1 task',
);
return '$_temp0';
}
@override
String goalsReached(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count tasks',
one: '1 task',
);
return 'Daily goal reached: $_temp0 done today.';
}
@override
String get labelsTitle => 'Labels';