feat: create statistics view
This commit is contained in:
@@ -44,3 +44,31 @@ enum Ruleset {
|
||||
|
||||
/// Different colors for highlighting games
|
||||
enum GameColor { red, orange, yellow, green, teal, blue, purple, pink }
|
||||
|
||||
enum StatisticType {
|
||||
totalMatches,
|
||||
totalWins,
|
||||
totalScore,
|
||||
totalLosses,
|
||||
averageScore,
|
||||
bestScore,
|
||||
worstScore,
|
||||
winrate,
|
||||
}
|
||||
|
||||
enum StatisticScope {
|
||||
allPlayers,
|
||||
//selectedPlayer,
|
||||
selectedGroups,
|
||||
selectedGames,
|
||||
timeframe,
|
||||
}
|
||||
|
||||
enum Timeframe {
|
||||
last7Days,
|
||||
last30Days,
|
||||
last90Days,
|
||||
last180Days,
|
||||
lastYear,
|
||||
allTime,
|
||||
}
|
||||
|
||||
19
lib/data/models/statistic.dart
Normal file
19
lib/data/models/statistic.dart
Normal file
@@ -0,0 +1,19 @@
|
||||
import 'package:tallee/core/enums.dart';
|
||||
import 'package:tallee/data/models/game.dart';
|
||||
import 'package:tallee/data/models/group.dart';
|
||||
|
||||
class Statistic {
|
||||
final StatisticType type;
|
||||
final List<StatisticScope> scopes;
|
||||
final Timeframe? timeframe;
|
||||
final List<Group>? selectedGroups;
|
||||
final List<Game>? selectedGames;
|
||||
|
||||
Statistic({
|
||||
required this.type,
|
||||
required this.scopes,
|
||||
this.timeframe,
|
||||
this.selectedGroups,
|
||||
this.selectedGames,
|
||||
});
|
||||
}
|
||||
@@ -26,6 +26,17 @@
|
||||
"create_match": "Spiel erstellen",
|
||||
"create_new_group": "Neue Gruppe erstellen",
|
||||
"create_new_match": "Neues Spiel erstellen",
|
||||
"create_statistic": "Statistik erstellen",
|
||||
"create_statistic_classifier_subtitle": "Wähle die anzuzeigende Hauptmetrik aus",
|
||||
"create_statistic_classifier_title": "Klassifikator",
|
||||
"create_statistic_games_subtitle": "Wähle die gefilterten Spielvorlagen",
|
||||
"create_statistic_games_title": "Spielvorlagen",
|
||||
"create_statistic_groups_subtitle": "Wähle die gefilterten Gruppen",
|
||||
"create_statistic_groups_title": "Gruppen",
|
||||
"create_statistic_scope_subtitle": "Wähle den Hauptfilter für deine Statistik. Er bestimmt, welche Daten zur Berechnung des Klassifikators verwendet werden.",
|
||||
"create_statistic_scope_title": "Bereich",
|
||||
"create_statistic_timeframe_subtitle": "Wähle einen Zeitraum, nach dem die Daten gefiltert werden. Nur Spiele, die innerhalb des Zeitraums beendet wurden, fließen in die Statistik ein.",
|
||||
"create_statistic_timeframe_title": "Zeitraum",
|
||||
"created_on": "Erstellt am",
|
||||
"data": "Daten",
|
||||
"data_successfully_deleted": "Daten erfolgreich gelöscht",
|
||||
@@ -82,6 +93,7 @@
|
||||
"legal_notice": "Impressum",
|
||||
"licenses": "Lizenzen",
|
||||
"live_edit_mode": "Live-Bearbeitungsmodus",
|
||||
"loading": "Lädt...",
|
||||
"loser": "Verlierer:in",
|
||||
"lowest_score": "Niedrigste Punkte",
|
||||
"match_in_progress": "Spiel läuft...",
|
||||
@@ -134,6 +146,11 @@
|
||||
"save_changes": "Änderungen speichern",
|
||||
"search_for_groups": "Nach Gruppen suchen",
|
||||
"search_for_players": "Nach Spieler:innen suchen",
|
||||
"select_a_classifier": "Klassifikator auswählen",
|
||||
"select_a_game": "Spielvorlage auswählen",
|
||||
"select_a_group": "Gruppe auswählen",
|
||||
"select_a_scope": "Bereich auswählen",
|
||||
"select_a_timeframe": "Zeitraum auswählen",
|
||||
"select_loser": "Verlierer:in wählen",
|
||||
"select_winner": "Gewinner:in wählen",
|
||||
"select_winners": "Gewinner:innen wählen",
|
||||
@@ -142,6 +159,18 @@
|
||||
"settings": "Einstellungen",
|
||||
"single_loser": "Ein:e Verlierer:in",
|
||||
"single_winner": "Ein:e Gewinner:in",
|
||||
"statistic_scope_all_players": "Alle Spieler:innen",
|
||||
"statistic_scope_selected_games": "Ausgewählte Spielvorlagen",
|
||||
"statistic_scope_selected_groups": "Ausgewählte Gruppen",
|
||||
"statistic_scope_timeframe": "Zeitraum",
|
||||
"statistic_type_average_score": "Durchschnittliche Punktzahl",
|
||||
"statistic_type_best_score": "Beste Punktzahl",
|
||||
"statistic_type_total_losses": "Niederlagen insgesamt",
|
||||
"statistic_type_total_matches": "Spiele insgesamt",
|
||||
"statistic_type_total_score": "Punktzahl insgesamt",
|
||||
"statistic_type_total_wins": "Siege insgesamt",
|
||||
"statistic_type_winrate": "Siegquote",
|
||||
"statistic_type_worst_score": "Schlechteste Punktzahl",
|
||||
"statistics": "Statistiken",
|
||||
"stats": "Statistiken",
|
||||
"successfully_added_player": "Spieler:in {playerName} erfolgreich hinzugefügt",
|
||||
@@ -149,6 +178,12 @@
|
||||
"there_is_no_group_matching_your_search": "Es gibt keine Gruppe, die deiner Suche entspricht",
|
||||
"this_cannot_be_undone": "Dies kann nicht rückgängig gemacht werden.",
|
||||
"tie": "Unentschieden",
|
||||
"timeframe_all_time": "Gesamter Zeitraum",
|
||||
"timeframe_last_180_days": "Letzte 180 Tage",
|
||||
"timeframe_last_30_days": "Letzte 30 Tage",
|
||||
"timeframe_last_7_days": "Letzte 7 Tage",
|
||||
"timeframe_last_90_days": "Letzte 90 Tage",
|
||||
"timeframe_last_year": "Letztes Jahr",
|
||||
"today_at": "Heute um",
|
||||
"undo": "Rückgängig",
|
||||
"unknown_exception": "Unbekannter Fehler (siehe Konsole)",
|
||||
|
||||
@@ -26,6 +26,17 @@
|
||||
"create_match": "Create match",
|
||||
"create_new_group": "Create new group",
|
||||
"create_new_match": "Create new match",
|
||||
"create_statistic": "Create statistic",
|
||||
"create_statistic_classifier_subtitle": "Select which key metric you want to display",
|
||||
"create_statistic_classifier_title": "Classifier",
|
||||
"create_statistic_games_subtitle": "Select the filtered games",
|
||||
"create_statistic_games_title": "Games",
|
||||
"create_statistic_groups_subtitle": "Select the filtered groups",
|
||||
"create_statistic_groups_title": "Groups",
|
||||
"create_statistic_scope_subtitle": "Select the main filter for your statistic. This will determine which data is used to calculate the selected classifier.",
|
||||
"create_statistic_scope_title": "Scope",
|
||||
"create_statistic_timeframe_subtitle": "Select a timeframe for which the data will be filtered. Only matches that ended within the selected timeframe will be included in the statistic.",
|
||||
"create_statistic_timeframe_title": "Timeframe",
|
||||
"created_on": "Created on",
|
||||
"data": "Data",
|
||||
"data_successfully_deleted": "Data successfully deleted",
|
||||
@@ -82,6 +93,7 @@
|
||||
"legal_notice": "Legal Notice",
|
||||
"licenses": "Licenses",
|
||||
"live_edit_mode": "Live Edit Mode",
|
||||
"loading": "Loading...",
|
||||
"loser": "Loser",
|
||||
"lowest_score": "Lowest Score",
|
||||
"match_in_progress": "Match in progress...",
|
||||
@@ -139,10 +151,27 @@
|
||||
"selected_players": "Selected players",
|
||||
"set_name": "Set name",
|
||||
"settings": "Settings",
|
||||
"select_a_classifier": "Select a classifier",
|
||||
"select_a_game": "Select a game",
|
||||
"select_a_group": "Select a group",
|
||||
"select_a_scope": "Select a scope",
|
||||
"select_a_timeframe": "Select a timeframe",
|
||||
"single_loser": "Single Loser",
|
||||
"single_winner": "Single Winner",
|
||||
"statistics": "Statistics",
|
||||
"stats": "Stats",
|
||||
"statistic_scope_all_players": "All players",
|
||||
"statistic_scope_selected_games": "Selected games",
|
||||
"statistic_scope_selected_groups": "Selected groups",
|
||||
"statistic_scope_timeframe": "Timeframe",
|
||||
"statistic_type_average_score": "Average score",
|
||||
"statistic_type_best_score": "Best score",
|
||||
"statistic_type_total_losses": "Total losses",
|
||||
"statistic_type_total_matches": "Total matches",
|
||||
"statistic_type_total_score": "Total score",
|
||||
"statistic_type_total_wins": "Total wins",
|
||||
"statistic_type_winrate": "Winrate",
|
||||
"statistic_type_worst_score": "Worst score",
|
||||
"successfully_added_player": "Successfully added player {playerName}",
|
||||
"@successfully_added_player": {
|
||||
"description": "Success message when adding a player",
|
||||
@@ -157,6 +186,12 @@
|
||||
"there_is_no_group_matching_your_search": "There is no group matching your search",
|
||||
"this_cannot_be_undone": "This can't be undone.",
|
||||
"tie": "Tie",
|
||||
"timeframe_all_time": "All time",
|
||||
"timeframe_last_180_days": "Last 180 days",
|
||||
"timeframe_last_30_days": "Last 30 days",
|
||||
"timeframe_last_7_days": "Last 7 days",
|
||||
"timeframe_last_90_days": "Last 90 days",
|
||||
"timeframe_last_year": "Last year",
|
||||
"today_at": "Today at",
|
||||
"undo": "Undo",
|
||||
"unknown_exception": "Unknown Exception (see console)",
|
||||
|
||||
@@ -254,6 +254,72 @@ abstract class AppLocalizations {
|
||||
/// **'Create new match'**
|
||||
String get create_new_match;
|
||||
|
||||
/// No description provided for @create_statistic.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Create statistic'**
|
||||
String get create_statistic;
|
||||
|
||||
/// No description provided for @create_statistic_classifier_subtitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Select which key metric you want to display'**
|
||||
String get create_statistic_classifier_subtitle;
|
||||
|
||||
/// No description provided for @create_statistic_classifier_title.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Classifier'**
|
||||
String get create_statistic_classifier_title;
|
||||
|
||||
/// No description provided for @create_statistic_games_subtitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Select the filtered games'**
|
||||
String get create_statistic_games_subtitle;
|
||||
|
||||
/// No description provided for @create_statistic_games_title.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Games'**
|
||||
String get create_statistic_games_title;
|
||||
|
||||
/// No description provided for @create_statistic_groups_subtitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Select the filtered groups'**
|
||||
String get create_statistic_groups_subtitle;
|
||||
|
||||
/// No description provided for @create_statistic_groups_title.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Groups'**
|
||||
String get create_statistic_groups_title;
|
||||
|
||||
/// No description provided for @create_statistic_scope_subtitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Select the main filter for your statistic. This will determine which data is used to calculate the selected classifier.'**
|
||||
String get create_statistic_scope_subtitle;
|
||||
|
||||
/// No description provided for @create_statistic_scope_title.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Scope'**
|
||||
String get create_statistic_scope_title;
|
||||
|
||||
/// No description provided for @create_statistic_timeframe_subtitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Select a timeframe for which the data will be filtered. Only matches that ended within the selected timeframe will be included in the statistic.'**
|
||||
String get create_statistic_timeframe_subtitle;
|
||||
|
||||
/// No description provided for @create_statistic_timeframe_title.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Timeframe'**
|
||||
String get create_statistic_timeframe_title;
|
||||
|
||||
/// No description provided for @created_on.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
@@ -548,6 +614,12 @@ abstract class AppLocalizations {
|
||||
/// **'Live Edit Mode'**
|
||||
String get live_edit_mode;
|
||||
|
||||
/// No description provided for @loading.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Loading...'**
|
||||
String get loading;
|
||||
|
||||
/// No description provided for @loser.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
@@ -890,6 +962,36 @@ abstract class AppLocalizations {
|
||||
/// **'Settings'**
|
||||
String get settings;
|
||||
|
||||
/// No description provided for @select_a_classifier.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Select a classifier'**
|
||||
String get select_a_classifier;
|
||||
|
||||
/// No description provided for @select_a_game.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Select a game'**
|
||||
String get select_a_game;
|
||||
|
||||
/// No description provided for @select_a_group.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Select a group'**
|
||||
String get select_a_group;
|
||||
|
||||
/// No description provided for @select_a_scope.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Select a scope'**
|
||||
String get select_a_scope;
|
||||
|
||||
/// No description provided for @select_a_timeframe.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Select a timeframe'**
|
||||
String get select_a_timeframe;
|
||||
|
||||
/// No description provided for @single_loser.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
@@ -914,6 +1016,78 @@ abstract class AppLocalizations {
|
||||
/// **'Stats'**
|
||||
String get stats;
|
||||
|
||||
/// No description provided for @statistic_scope_all_players.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'All players'**
|
||||
String get statistic_scope_all_players;
|
||||
|
||||
/// No description provided for @statistic_scope_selected_games.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Selected games'**
|
||||
String get statistic_scope_selected_games;
|
||||
|
||||
/// No description provided for @statistic_scope_selected_groups.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Selected groups'**
|
||||
String get statistic_scope_selected_groups;
|
||||
|
||||
/// No description provided for @statistic_scope_timeframe.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Timeframe'**
|
||||
String get statistic_scope_timeframe;
|
||||
|
||||
/// No description provided for @statistic_type_average_score.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Average score'**
|
||||
String get statistic_type_average_score;
|
||||
|
||||
/// No description provided for @statistic_type_best_score.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Best score'**
|
||||
String get statistic_type_best_score;
|
||||
|
||||
/// No description provided for @statistic_type_total_losses.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Total losses'**
|
||||
String get statistic_type_total_losses;
|
||||
|
||||
/// No description provided for @statistic_type_total_matches.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Total matches'**
|
||||
String get statistic_type_total_matches;
|
||||
|
||||
/// No description provided for @statistic_type_total_score.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Total score'**
|
||||
String get statistic_type_total_score;
|
||||
|
||||
/// No description provided for @statistic_type_total_wins.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Total wins'**
|
||||
String get statistic_type_total_wins;
|
||||
|
||||
/// No description provided for @statistic_type_winrate.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Winrate'**
|
||||
String get statistic_type_winrate;
|
||||
|
||||
/// No description provided for @statistic_type_worst_score.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Worst score'**
|
||||
String get statistic_type_worst_score;
|
||||
|
||||
/// Success message when adding a player
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
@@ -944,6 +1118,42 @@ abstract class AppLocalizations {
|
||||
/// **'Tie'**
|
||||
String get tie;
|
||||
|
||||
/// No description provided for @timeframe_all_time.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'All time'**
|
||||
String get timeframe_all_time;
|
||||
|
||||
/// No description provided for @timeframe_last_180_days.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Last 180 days'**
|
||||
String get timeframe_last_180_days;
|
||||
|
||||
/// No description provided for @timeframe_last_30_days.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Last 30 days'**
|
||||
String get timeframe_last_30_days;
|
||||
|
||||
/// No description provided for @timeframe_last_7_days.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Last 7 days'**
|
||||
String get timeframe_last_7_days;
|
||||
|
||||
/// No description provided for @timeframe_last_90_days.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Last 90 days'**
|
||||
String get timeframe_last_90_days;
|
||||
|
||||
/// No description provided for @timeframe_last_year.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Last year'**
|
||||
String get timeframe_last_year;
|
||||
|
||||
/// No description provided for @today_at.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
||||
@@ -88,6 +88,44 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||
@override
|
||||
String get create_new_match => 'Neues Spiel erstellen';
|
||||
|
||||
@override
|
||||
String get create_statistic => 'Statistik erstellen';
|
||||
|
||||
@override
|
||||
String get create_statistic_classifier_subtitle =>
|
||||
'Wähle die anzuzeigende Hauptmetrik aus';
|
||||
|
||||
@override
|
||||
String get create_statistic_classifier_title => 'Klassifikator';
|
||||
|
||||
@override
|
||||
String get create_statistic_games_subtitle =>
|
||||
'Wähle die gefilterten Spielvorlagen';
|
||||
|
||||
@override
|
||||
String get create_statistic_games_title => 'Spielvorlagen';
|
||||
|
||||
@override
|
||||
String get create_statistic_groups_subtitle =>
|
||||
'Wähle die gefilterten Gruppen';
|
||||
|
||||
@override
|
||||
String get create_statistic_groups_title => 'Gruppen';
|
||||
|
||||
@override
|
||||
String get create_statistic_scope_subtitle =>
|
||||
'Wähle den Hauptfilter für deine Statistik. Er bestimmt, welche Daten zur Berechnung des Klassifikators verwendet werden.';
|
||||
|
||||
@override
|
||||
String get create_statistic_scope_title => 'Bereich';
|
||||
|
||||
@override
|
||||
String get create_statistic_timeframe_subtitle =>
|
||||
'Wähle einen Zeitraum, nach dem die Daten gefiltert werden. Nur Spiele, die innerhalb des Zeitraums beendet wurden, fließen in die Statistik ein.';
|
||||
|
||||
@override
|
||||
String get create_statistic_timeframe_title => 'Zeitraum';
|
||||
|
||||
@override
|
||||
String get created_on => 'Erstellt am';
|
||||
|
||||
@@ -249,6 +287,9 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||
@override
|
||||
String get live_edit_mode => 'Live-Bearbeitungsmodus';
|
||||
|
||||
@override
|
||||
String get loading => 'Lädt...';
|
||||
|
||||
@override
|
||||
String get loser => 'Verlierer:in';
|
||||
|
||||
@@ -426,6 +467,21 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||
@override
|
||||
String get settings => 'Einstellungen';
|
||||
|
||||
@override
|
||||
String get select_a_classifier => 'Klassifikator auswählen';
|
||||
|
||||
@override
|
||||
String get select_a_game => 'Spielvorlage auswählen';
|
||||
|
||||
@override
|
||||
String get select_a_group => 'Gruppe auswählen';
|
||||
|
||||
@override
|
||||
String get select_a_scope => 'Bereich auswählen';
|
||||
|
||||
@override
|
||||
String get select_a_timeframe => 'Zeitraum auswählen';
|
||||
|
||||
@override
|
||||
String get single_loser => 'Ein:e Verlierer:in';
|
||||
|
||||
@@ -438,6 +494,42 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||
@override
|
||||
String get stats => 'Statistiken';
|
||||
|
||||
@override
|
||||
String get statistic_scope_all_players => 'Alle Spieler:innen';
|
||||
|
||||
@override
|
||||
String get statistic_scope_selected_games => 'Ausgewählte Spielvorlagen';
|
||||
|
||||
@override
|
||||
String get statistic_scope_selected_groups => 'Ausgewählte Gruppen';
|
||||
|
||||
@override
|
||||
String get statistic_scope_timeframe => 'Zeitraum';
|
||||
|
||||
@override
|
||||
String get statistic_type_average_score => 'Durchschnittliche Punktzahl';
|
||||
|
||||
@override
|
||||
String get statistic_type_best_score => 'Beste Punktzahl';
|
||||
|
||||
@override
|
||||
String get statistic_type_total_losses => 'Niederlagen insgesamt';
|
||||
|
||||
@override
|
||||
String get statistic_type_total_matches => 'Spiele insgesamt';
|
||||
|
||||
@override
|
||||
String get statistic_type_total_score => 'Punktzahl insgesamt';
|
||||
|
||||
@override
|
||||
String get statistic_type_total_wins => 'Siege insgesamt';
|
||||
|
||||
@override
|
||||
String get statistic_type_winrate => 'Siegquote';
|
||||
|
||||
@override
|
||||
String get statistic_type_worst_score => 'Schlechteste Punktzahl';
|
||||
|
||||
@override
|
||||
String successfully_added_player(String playerName) {
|
||||
return 'Spieler:in $playerName erfolgreich hinzugefügt';
|
||||
@@ -458,6 +550,24 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||
@override
|
||||
String get tie => 'Unentschieden';
|
||||
|
||||
@override
|
||||
String get timeframe_all_time => 'Gesamter Zeitraum';
|
||||
|
||||
@override
|
||||
String get timeframe_last_180_days => 'Letzte 180 Tage';
|
||||
|
||||
@override
|
||||
String get timeframe_last_30_days => 'Letzte 30 Tage';
|
||||
|
||||
@override
|
||||
String get timeframe_last_7_days => 'Letzte 7 Tage';
|
||||
|
||||
@override
|
||||
String get timeframe_last_90_days => 'Letzte 90 Tage';
|
||||
|
||||
@override
|
||||
String get timeframe_last_year => 'Letztes Jahr';
|
||||
|
||||
@override
|
||||
String get today_at => 'Heute um';
|
||||
|
||||
|
||||
@@ -88,6 +88,42 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
@override
|
||||
String get create_new_match => 'Create new match';
|
||||
|
||||
@override
|
||||
String get create_statistic => 'Create statistic';
|
||||
|
||||
@override
|
||||
String get create_statistic_classifier_subtitle =>
|
||||
'Select which key metric you want to display';
|
||||
|
||||
@override
|
||||
String get create_statistic_classifier_title => 'Classifier';
|
||||
|
||||
@override
|
||||
String get create_statistic_games_subtitle => 'Select the filtered games';
|
||||
|
||||
@override
|
||||
String get create_statistic_games_title => 'Games';
|
||||
|
||||
@override
|
||||
String get create_statistic_groups_subtitle => 'Select the filtered groups';
|
||||
|
||||
@override
|
||||
String get create_statistic_groups_title => 'Groups';
|
||||
|
||||
@override
|
||||
String get create_statistic_scope_subtitle =>
|
||||
'Select the main filter for your statistic. This will determine which data is used to calculate the selected classifier.';
|
||||
|
||||
@override
|
||||
String get create_statistic_scope_title => 'Scope';
|
||||
|
||||
@override
|
||||
String get create_statistic_timeframe_subtitle =>
|
||||
'Select a timeframe for which the data will be filtered. Only matches that ended within the selected timeframe will be included in the statistic.';
|
||||
|
||||
@override
|
||||
String get create_statistic_timeframe_title => 'Timeframe';
|
||||
|
||||
@override
|
||||
String get created_on => 'Created on';
|
||||
|
||||
@@ -249,6 +285,9 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
@override
|
||||
String get live_edit_mode => 'Live Edit Mode';
|
||||
|
||||
@override
|
||||
String get loading => 'Loading...';
|
||||
|
||||
@override
|
||||
String get loser => 'Loser';
|
||||
|
||||
@@ -426,6 +465,21 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
@override
|
||||
String get settings => 'Settings';
|
||||
|
||||
@override
|
||||
String get select_a_classifier => 'Select a classifier';
|
||||
|
||||
@override
|
||||
String get select_a_game => 'Select a game';
|
||||
|
||||
@override
|
||||
String get select_a_group => 'Select a group';
|
||||
|
||||
@override
|
||||
String get select_a_scope => 'Select a scope';
|
||||
|
||||
@override
|
||||
String get select_a_timeframe => 'Select a timeframe';
|
||||
|
||||
@override
|
||||
String get single_loser => 'Single Loser';
|
||||
|
||||
@@ -438,6 +492,42 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
@override
|
||||
String get stats => 'Stats';
|
||||
|
||||
@override
|
||||
String get statistic_scope_all_players => 'All players';
|
||||
|
||||
@override
|
||||
String get statistic_scope_selected_games => 'Selected games';
|
||||
|
||||
@override
|
||||
String get statistic_scope_selected_groups => 'Selected groups';
|
||||
|
||||
@override
|
||||
String get statistic_scope_timeframe => 'Timeframe';
|
||||
|
||||
@override
|
||||
String get statistic_type_average_score => 'Average score';
|
||||
|
||||
@override
|
||||
String get statistic_type_best_score => 'Best score';
|
||||
|
||||
@override
|
||||
String get statistic_type_total_losses => 'Total losses';
|
||||
|
||||
@override
|
||||
String get statistic_type_total_matches => 'Total matches';
|
||||
|
||||
@override
|
||||
String get statistic_type_total_score => 'Total score';
|
||||
|
||||
@override
|
||||
String get statistic_type_total_wins => 'Total wins';
|
||||
|
||||
@override
|
||||
String get statistic_type_winrate => 'Winrate';
|
||||
|
||||
@override
|
||||
String get statistic_type_worst_score => 'Worst score';
|
||||
|
||||
@override
|
||||
String successfully_added_player(String playerName) {
|
||||
return 'Successfully added player $playerName';
|
||||
@@ -457,6 +547,24 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
@override
|
||||
String get tie => 'Tie';
|
||||
|
||||
@override
|
||||
String get timeframe_all_time => 'All time';
|
||||
|
||||
@override
|
||||
String get timeframe_last_180_days => 'Last 180 days';
|
||||
|
||||
@override
|
||||
String get timeframe_last_30_days => 'Last 30 days';
|
||||
|
||||
@override
|
||||
String get timeframe_last_7_days => 'Last 7 days';
|
||||
|
||||
@override
|
||||
String get timeframe_last_90_days => 'Last 90 days';
|
||||
|
||||
@override
|
||||
String get timeframe_last_year => 'Last year';
|
||||
|
||||
@override
|
||||
String get today_at => 'Today at';
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import 'package:tallee/l10n/generated/app_localizations.dart';
|
||||
import 'package:tallee/presentation/views/main_menu/group_view/group_view.dart';
|
||||
import 'package:tallee/presentation/views/main_menu/match_view/match_view.dart';
|
||||
import 'package:tallee/presentation/views/main_menu/settings_view/settings_view.dart';
|
||||
import 'package:tallee/presentation/views/main_menu/statistics_view.dart';
|
||||
import 'package:tallee/presentation/views/main_menu/statistics_view/statistics_view.dart';
|
||||
import 'package:tallee/presentation/widgets/buttons/haptic_icon_button.dart';
|
||||
import 'package:tallee/presentation/widgets/navbar_item.dart';
|
||||
|
||||
|
||||
@@ -0,0 +1,635 @@
|
||||
import 'package:animated_custom_dropdown/custom_dropdown.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tallee/core/common.dart';
|
||||
import 'package:tallee/core/constants.dart';
|
||||
import 'package:tallee/core/custom_theme.dart';
|
||||
import 'package:tallee/core/enums.dart';
|
||||
import 'package:tallee/data/db/database.dart';
|
||||
import 'package:tallee/data/models/game.dart';
|
||||
import 'package:tallee/data/models/group.dart';
|
||||
import 'package:tallee/data/models/player.dart';
|
||||
import 'package:tallee/data/models/statistic.dart';
|
||||
import 'package:tallee/l10n/generated/app_localizations.dart';
|
||||
import 'package:tallee/presentation/widgets/buttons/animated_dialog_button.dart';
|
||||
|
||||
class CreateStatisticView extends StatefulWidget {
|
||||
const CreateStatisticView({super.key, required this.onStatisticCreated});
|
||||
|
||||
final void Function() onStatisticCreated;
|
||||
|
||||
@override
|
||||
State<CreateStatisticView> createState() => _CreateStatisticViewState();
|
||||
}
|
||||
|
||||
class _CreateStatisticViewState extends State<CreateStatisticView> {
|
||||
bool isLoading = false;
|
||||
|
||||
/* Data loaded from the database */
|
||||
List<Player> players = [];
|
||||
List<Game> games = [];
|
||||
List<Group> groups = [];
|
||||
|
||||
/* User selections */
|
||||
StatisticType? selectedType;
|
||||
List<StatisticScope> selectedScope = [];
|
||||
List<Game> selectedGames = [];
|
||||
List<Player> selectedPlayers = [];
|
||||
List<Group> selectedGroups = [];
|
||||
Timeframe? selectedTimeframe;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
loadAllData();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var loc = AppLocalizations.of(context);
|
||||
|
||||
return ScaffoldMessenger(
|
||||
child: Scaffold(
|
||||
appBar: AppBar(title: Text(loc.create_statistic)),
|
||||
body: Stack(
|
||||
alignment: AlignmentDirectional.center,
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.of(context).padding.bottom + 80,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Classifier title
|
||||
Padding(
|
||||
padding: const EdgeInsetsGeometry.only(left: 24),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
loc.create_statistic_classifier_title,
|
||||
textAlign: TextAlign.start,
|
||||
style: const TextStyle(
|
||||
color: CustomTheme.textColor,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
loc.create_statistic_classifier_subtitle,
|
||||
textAlign: TextAlign.start,
|
||||
style: const TextStyle(
|
||||
color: CustomTheme.textColor,
|
||||
fontSize: 12,
|
||||
),
|
||||
softWrap: true,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Classifier selection
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8,
|
||||
horizontal: 16,
|
||||
),
|
||||
child: CustomDropdown<StatisticType>(
|
||||
closedHeaderPadding: const EdgeInsets.symmetric(
|
||||
vertical: 16,
|
||||
horizontal: 16,
|
||||
),
|
||||
listItemBuilder:
|
||||
(context, item, isSelected, onItemSelect) => Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
translateStatisticTypeToString(item, context),
|
||||
style: itemStyle,
|
||||
),
|
||||
if (isSelected)
|
||||
const Icon(
|
||||
Icons.check,
|
||||
color: CustomTheme.textColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
headerBuilder: (context, selectedType, enabled) => Text(
|
||||
translateStatisticTypeToString(selectedType, context),
|
||||
style: headerStyle,
|
||||
),
|
||||
hintText: loc.select_a_classifier,
|
||||
items: StatisticType.values,
|
||||
decoration: decoration,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
selectedType = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 10),
|
||||
|
||||
// Scope title
|
||||
Padding(
|
||||
padding: const EdgeInsetsGeometry.only(left: 24),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
loc.create_statistic_scope_title,
|
||||
textAlign: TextAlign.start,
|
||||
style: const TextStyle(
|
||||
color: CustomTheme.textColor,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
loc.create_statistic_scope_subtitle,
|
||||
textAlign: TextAlign.start,
|
||||
style: const TextStyle(
|
||||
color: CustomTheme.textColor,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Scope selection
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8,
|
||||
horizontal: 16,
|
||||
),
|
||||
child: CustomDropdown<StatisticScope>.multiSelect(
|
||||
closedHeaderPadding: const EdgeInsets.symmetric(
|
||||
vertical: 16,
|
||||
horizontal: 16,
|
||||
),
|
||||
hintText: loc.select_a_scope,
|
||||
items: StatisticScope.values,
|
||||
decoration: decoration,
|
||||
listItemBuilder:
|
||||
(context, scope, isSelected, onItemSelect) => Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
translateScopeToString(scope, context),
|
||||
style: itemStyle,
|
||||
),
|
||||
if (isSelected)
|
||||
const Icon(
|
||||
Icons.check,
|
||||
color: CustomTheme.textColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
headerListBuilder: (context, selectedItems, enabled) =>
|
||||
Text(
|
||||
selectedItems
|
||||
.map((s) => translateScopeToString(s, context))
|
||||
.join(', '),
|
||||
style: headerStyle,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
onListChanged: (List<StatisticScope> values) {
|
||||
setState(() {
|
||||
selectedScope = values;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
if (selectedScope.contains(StatisticScope.selectedGames)) ...[
|
||||
const SizedBox(height: 10),
|
||||
|
||||
// games title
|
||||
Padding(
|
||||
padding: const EdgeInsetsGeometry.only(left: 24),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
loc.create_statistic_games_title,
|
||||
textAlign: TextAlign.start,
|
||||
style: const TextStyle(
|
||||
color: CustomTheme.textColor,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
loc.create_statistic_games_subtitle,
|
||||
textAlign: TextAlign.start,
|
||||
style: const TextStyle(
|
||||
color: CustomTheme.textColor,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// game selection
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8,
|
||||
horizontal: 16,
|
||||
),
|
||||
child: CustomDropdown<Game>.multiSelect(
|
||||
enabled: !isLoading,
|
||||
disabledDecoration: disabledDecoration,
|
||||
closedHeaderPadding: const EdgeInsets.symmetric(
|
||||
vertical: 16,
|
||||
horizontal: 16,
|
||||
),
|
||||
hintText: isLoading ? loc.loading : loc.select_a_game,
|
||||
items: games,
|
||||
decoration: decoration,
|
||||
listItemBuilder:
|
||||
(context, item, isSelected, onItemSelect) => Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
// Name
|
||||
Text(item.name, style: itemStyle),
|
||||
const SizedBox(width: 12),
|
||||
|
||||
// Ruleset
|
||||
Text(
|
||||
translateRulesetToString(
|
||||
item.ruleset,
|
||||
context,
|
||||
),
|
||||
style: hintStyle.copyWith(fontSize: 12),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
// Check icon
|
||||
if (isSelected)
|
||||
const Icon(
|
||||
Icons.check,
|
||||
color: CustomTheme.textColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
headerListBuilder: (context, selectedItems, enabled) =>
|
||||
Text(
|
||||
selectedItems.map((g) => g.name).join(', '),
|
||||
style: const TextStyle(
|
||||
color: CustomTheme.textColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
onListChanged: (List<Game> values) {
|
||||
setState(() {
|
||||
selectedGames = values;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
if (selectedScope.contains(
|
||||
StatisticScope.selectedGroups,
|
||||
)) ...[
|
||||
const SizedBox(height: 10),
|
||||
|
||||
// groups title
|
||||
Padding(
|
||||
padding: const EdgeInsetsGeometry.only(left: 24),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
loc.create_statistic_groups_title,
|
||||
textAlign: TextAlign.start,
|
||||
style: const TextStyle(
|
||||
color: CustomTheme.textColor,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
loc.create_statistic_groups_subtitle,
|
||||
textAlign: TextAlign.start,
|
||||
style: const TextStyle(
|
||||
color: CustomTheme.textColor,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// groups selection
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8,
|
||||
horizontal: 16,
|
||||
),
|
||||
child: CustomDropdown<Group>.multiSelect(
|
||||
enabled: !isLoading,
|
||||
disabledDecoration: disabledDecoration,
|
||||
closedHeaderPadding: const EdgeInsets.symmetric(
|
||||
vertical: 16,
|
||||
horizontal: 16,
|
||||
),
|
||||
hintText: isLoading ? loc.loading : loc.select_a_group,
|
||||
items: groups,
|
||||
decoration: decoration,
|
||||
listItemBuilder:
|
||||
(context, item, isSelected, onItemSelect) => Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
// Name
|
||||
Text(item.name, style: itemStyle),
|
||||
const SizedBox(width: 12),
|
||||
|
||||
// Ruleset
|
||||
Text(
|
||||
' ${item.members.length.toString()} ${loc.members}',
|
||||
style: hintStyle.copyWith(fontSize: 12),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (isSelected)
|
||||
const Icon(
|
||||
Icons.check,
|
||||
color: CustomTheme.textColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
headerListBuilder: (context, selectedItems, enabled) =>
|
||||
Text(
|
||||
selectedItems.map((g) => g.name).join(', '),
|
||||
style: headerStyle,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
onListChanged: (List<Group> groups) {
|
||||
setState(() {
|
||||
selectedGroups = groups;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
if (selectedScope.contains(StatisticScope.timeframe)) ...[
|
||||
const SizedBox(height: 10),
|
||||
|
||||
// timeframe title
|
||||
Padding(
|
||||
padding: const EdgeInsetsGeometry.only(left: 24),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
loc.create_statistic_timeframe_title,
|
||||
textAlign: TextAlign.start,
|
||||
style: const TextStyle(
|
||||
color: CustomTheme.textColor,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
loc.create_statistic_timeframe_subtitle,
|
||||
textAlign: TextAlign.start,
|
||||
style: const TextStyle(
|
||||
color: CustomTheme.textColor,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// groups selection
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8,
|
||||
horizontal: 16,
|
||||
),
|
||||
child: CustomDropdown<Timeframe>(
|
||||
enabled: !isLoading,
|
||||
excludeSelected: false,
|
||||
disabledDecoration: disabledDecoration,
|
||||
closedHeaderPadding: const EdgeInsets.symmetric(
|
||||
vertical: 16,
|
||||
horizontal: 16,
|
||||
),
|
||||
hintText: isLoading
|
||||
? loc.loading
|
||||
: loc.select_a_timeframe,
|
||||
items: Timeframe.values,
|
||||
decoration: decoration,
|
||||
listItemBuilder:
|
||||
(context, timeframe, isSelected, onItemSelect) =>
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
translateTimeframeToString(
|
||||
timeframe,
|
||||
context,
|
||||
),
|
||||
style: itemStyle,
|
||||
),
|
||||
if (isSelected)
|
||||
const Icon(
|
||||
Icons.check,
|
||||
color: CustomTheme.textColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
headerBuilder: (context, selectedTimeframe, enabled) =>
|
||||
Text(
|
||||
translateTimeframeToString(
|
||||
selectedTimeframe,
|
||||
context,
|
||||
),
|
||||
style: headerStyle,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
onChanged: (Timeframe? timeframe) {
|
||||
setState(() {
|
||||
selectedTimeframe = timeframe;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Create statistic button
|
||||
Positioned(
|
||||
bottom: MediaQuery.of(context).padding.bottom,
|
||||
child: AnimatedDialogButton(
|
||||
buttonConstraints: const BoxConstraints(minWidth: 350),
|
||||
buttonText: loc.create_statistic,
|
||||
onPressed: selectedType != null && selectedScope.isNotEmpty
|
||||
? () => submitStatistic()
|
||||
: null,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
CustomDropdownDecoration get decoration => CustomDropdownDecoration(
|
||||
listItemDecoration: const ListItemDecoration(
|
||||
selectedIconBorder: BorderSide(color: CustomTheme.primaryColor, width: 1),
|
||||
selectedIconColor: CustomTheme.primaryColor,
|
||||
highlightColor: CustomTheme.secondaryColor,
|
||||
splashColor: Colors.transparent,
|
||||
selectedColor: CustomTheme.onBoxColor,
|
||||
),
|
||||
listItemStyle: itemStyle,
|
||||
headerStyle: headerStyle,
|
||||
hintStyle: hintStyle,
|
||||
closedFillColor: CustomTheme.boxColor,
|
||||
closedBorder: Border.all(color: CustomTheme.boxBorderColor, width: 1),
|
||||
expandedFillColor: CustomTheme.boxColor,
|
||||
expandedBorder: Border.all(color: CustomTheme.boxBorderColor, width: 1),
|
||||
);
|
||||
|
||||
CustomDropdownDisabledDecoration get disabledDecoration =>
|
||||
CustomDropdownDisabledDecoration(
|
||||
fillColor: CustomTheme.boxColor.withAlpha(125),
|
||||
border: Border.all(
|
||||
color: CustomTheme.boxBorderColor.withAlpha(125),
|
||||
width: 1,
|
||||
),
|
||||
headerStyle: disabledHeaderStyle,
|
||||
hintStyle: disabledHintStyle,
|
||||
);
|
||||
|
||||
TextStyle get headerStyle => const TextStyle(
|
||||
color: CustomTheme.textColor,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
);
|
||||
|
||||
TextStyle get itemStyle =>
|
||||
const TextStyle(color: CustomTheme.textColor, fontSize: 14);
|
||||
|
||||
TextStyle get hintStyle =>
|
||||
const TextStyle(color: CustomTheme.hintColor, fontSize: 14);
|
||||
|
||||
TextStyle get disabledHeaderStyle => const TextStyle(
|
||||
color: CustomTheme.hintColor,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
);
|
||||
|
||||
TextStyle get disabledHintStyle =>
|
||||
const TextStyle(color: CustomTheme.hintColor, fontSize: 14);
|
||||
|
||||
Future<void> loadAllData() async {
|
||||
isLoading = true;
|
||||
final db = Provider.of<AppDatabase>(context, listen: false);
|
||||
|
||||
Future.wait([
|
||||
db.playerDao.getAllPlayers(),
|
||||
db.groupDao.getAllGroups(),
|
||||
db.gameDao.getAllGames(),
|
||||
Future.delayed(Constants.MINIMUM_SKELETON_DURATION),
|
||||
])
|
||||
.then((results) async {
|
||||
players = results[0];
|
||||
groups = results[1];
|
||||
games = results[2];
|
||||
isLoading = false;
|
||||
})
|
||||
.catchError((error) {
|
||||
print('Error loading data: $error');
|
||||
});
|
||||
}
|
||||
|
||||
void submitStatistic() {
|
||||
final newStatistic = Statistic(
|
||||
type: selectedType!,
|
||||
scopes: selectedScope,
|
||||
timeframe: selectedTimeframe,
|
||||
selectedGroups: selectedGroups,
|
||||
selectedGames: selectedGames,
|
||||
);
|
||||
// final db = Provider.of<AppDatabase>(context, listen: false);
|
||||
// db.statisticDao.addStatistic(newStatistic);
|
||||
Navigator.of(context).pop(newStatistic);
|
||||
}
|
||||
}
|
||||
|
||||
String translateTimeframeToString(Timeframe timeframe, BuildContext context) {
|
||||
final loc = AppLocalizations.of(context);
|
||||
switch (timeframe) {
|
||||
case Timeframe.last7Days:
|
||||
return loc.timeframe_last_7_days;
|
||||
case Timeframe.last30Days:
|
||||
return loc.timeframe_last_30_days;
|
||||
case Timeframe.last90Days:
|
||||
return loc.timeframe_last_90_days;
|
||||
case Timeframe.last180Days:
|
||||
return loc.timeframe_last_180_days;
|
||||
case Timeframe.lastYear:
|
||||
return loc.timeframe_last_year;
|
||||
case Timeframe.allTime:
|
||||
return loc.timeframe_all_time;
|
||||
}
|
||||
}
|
||||
|
||||
String translateScopeToString(StatisticScope scope, BuildContext context) {
|
||||
final loc = AppLocalizations.of(context);
|
||||
switch (scope) {
|
||||
case StatisticScope.allPlayers:
|
||||
return loc.statistic_scope_all_players;
|
||||
case StatisticScope.selectedGroups:
|
||||
return loc.statistic_scope_selected_groups;
|
||||
case StatisticScope.selectedGames:
|
||||
return loc.statistic_scope_selected_games;
|
||||
case StatisticScope.timeframe:
|
||||
return loc.statistic_scope_timeframe;
|
||||
}
|
||||
}
|
||||
|
||||
String translateStatisticTypeToString(
|
||||
StatisticType type,
|
||||
BuildContext context,
|
||||
) {
|
||||
final loc = AppLocalizations.of(context);
|
||||
switch (type) {
|
||||
case StatisticType.totalMatches:
|
||||
return loc.statistic_type_total_matches;
|
||||
case StatisticType.totalWins:
|
||||
return loc.statistic_type_total_wins;
|
||||
case StatisticType.totalScore:
|
||||
return loc.statistic_type_total_score;
|
||||
case StatisticType.totalLosses:
|
||||
return loc.statistic_type_total_losses;
|
||||
case StatisticType.averageScore:
|
||||
return loc.statistic_type_average_score;
|
||||
case StatisticType.bestScore:
|
||||
return loc.statistic_type_best_score;
|
||||
case StatisticType.worstScore:
|
||||
return loc.statistic_type_worst_score;
|
||||
case StatisticType.winrate:
|
||||
return loc.statistic_type_winrate;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,14 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tallee/core/adaptive_page_route.dart';
|
||||
import 'package:tallee/core/constants.dart';
|
||||
import 'package:tallee/data/db/database.dart';
|
||||
import 'package:tallee/data/models/match.dart';
|
||||
import 'package:tallee/data/models/player.dart';
|
||||
import 'package:tallee/l10n/generated/app_localizations.dart';
|
||||
import 'package:tallee/presentation/views/main_menu/statistics_view/create_statistic_view.dart';
|
||||
import 'package:tallee/presentation/widgets/app_skeleton.dart';
|
||||
import 'package:tallee/presentation/widgets/buttons/main_menu_button.dart';
|
||||
import 'package:tallee/presentation/widgets/tiles/quick_info_tile.dart';
|
||||
import 'package:tallee/presentation/widgets/tiles/statistics_tile.dart';
|
||||
import 'package:tallee/presentation/widgets/top_centered_message.dart';
|
||||
@@ -47,85 +50,107 @@ class _StatisticsViewState extends State<StatisticsView> {
|
||||
final loc = AppLocalizations.of(context);
|
||||
return LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints constraints) {
|
||||
return SingleChildScrollView(
|
||||
child: AppSkeleton(
|
||||
enabled: isLoading,
|
||||
fixLayoutBuilder: true,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(minWidth: constraints.maxWidth),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
return Stack(
|
||||
alignment: AlignmentDirectional.center,
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
child: AppSkeleton(
|
||||
enabled: isLoading,
|
||||
fixLayoutBuilder: true,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(minWidth: constraints.maxWidth),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
QuickInfoTile(
|
||||
width: constraints.maxWidth * 0.45,
|
||||
height: constraints.maxHeight * 0.13,
|
||||
title: loc.matches,
|
||||
icon: Icons.groups_rounded,
|
||||
value: matchCount,
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
QuickInfoTile(
|
||||
width: constraints.maxWidth * 0.45,
|
||||
height: constraints.maxHeight * 0.13,
|
||||
title: loc.matches,
|
||||
icon: Icons.groups_rounded,
|
||||
value: matchCount,
|
||||
),
|
||||
SizedBox(width: constraints.maxWidth * 0.05),
|
||||
QuickInfoTile(
|
||||
width: constraints.maxWidth * 0.45,
|
||||
height: constraints.maxHeight * 0.13,
|
||||
title: loc.groups,
|
||||
icon: Icons.groups_rounded,
|
||||
value: groupCount,
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(width: constraints.maxWidth * 0.05),
|
||||
QuickInfoTile(
|
||||
width: constraints.maxWidth * 0.45,
|
||||
height: constraints.maxHeight * 0.13,
|
||||
title: loc.groups,
|
||||
icon: Icons.groups_rounded,
|
||||
value: groupCount,
|
||||
SizedBox(height: constraints.maxHeight * 0.02),
|
||||
Visibility(
|
||||
visible:
|
||||
winCounts.isEmpty &&
|
||||
matchCounts.isEmpty &&
|
||||
winRates.isEmpty,
|
||||
replacement: Column(
|
||||
children: [
|
||||
StatisticsTile(
|
||||
icon: Icons.sports_score,
|
||||
title: loc.wins,
|
||||
width: constraints.maxWidth * 0.95,
|
||||
values: winCounts,
|
||||
itemCount: 3,
|
||||
barColor: Colors.green,
|
||||
),
|
||||
SizedBox(height: constraints.maxHeight * 0.02),
|
||||
StatisticsTile(
|
||||
icon: Icons.percent,
|
||||
title: loc.winrate,
|
||||
width: constraints.maxWidth * 0.95,
|
||||
values: winRates,
|
||||
itemCount: 5,
|
||||
barColor: Colors.orange[700]!,
|
||||
),
|
||||
SizedBox(height: constraints.maxHeight * 0.02),
|
||||
StatisticsTile(
|
||||
icon: Icons.casino,
|
||||
title: loc.amount_of_matches,
|
||||
width: constraints.maxWidth * 0.95,
|
||||
values: matchCounts,
|
||||
itemCount: 10,
|
||||
barColor: Colors.blue,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: TopCenteredMessage(
|
||||
icon: Icons.info,
|
||||
title: loc.info,
|
||||
message: AppLocalizations.of(
|
||||
context,
|
||||
).no_statistics_available,
|
||||
),
|
||||
),
|
||||
SizedBox(height: MediaQuery.paddingOf(context).bottom),
|
||||
],
|
||||
),
|
||||
SizedBox(height: constraints.maxHeight * 0.02),
|
||||
Visibility(
|
||||
visible:
|
||||
winCounts.isEmpty &&
|
||||
matchCounts.isEmpty &&
|
||||
winRates.isEmpty,
|
||||
replacement: Column(
|
||||
children: [
|
||||
StatisticsTile(
|
||||
icon: Icons.sports_score,
|
||||
title: loc.wins,
|
||||
width: constraints.maxWidth * 0.95,
|
||||
values: winCounts,
|
||||
itemCount: 3,
|
||||
barColor: Colors.green,
|
||||
),
|
||||
SizedBox(height: constraints.maxHeight * 0.02),
|
||||
StatisticsTile(
|
||||
icon: Icons.percent,
|
||||
title: loc.winrate,
|
||||
width: constraints.maxWidth * 0.95,
|
||||
values: winRates,
|
||||
itemCount: 5,
|
||||
barColor: Colors.orange[700]!,
|
||||
),
|
||||
SizedBox(height: constraints.maxHeight * 0.02),
|
||||
StatisticsTile(
|
||||
icon: Icons.casino,
|
||||
title: loc.amount_of_matches,
|
||||
width: constraints.maxWidth * 0.95,
|
||||
values: matchCounts,
|
||||
itemCount: 10,
|
||||
barColor: Colors.blue,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: TopCenteredMessage(
|
||||
icon: Icons.info,
|
||||
title: loc.info,
|
||||
message: AppLocalizations.of(
|
||||
context,
|
||||
).no_statistics_available,
|
||||
),
|
||||
),
|
||||
SizedBox(height: MediaQuery.paddingOf(context).bottom),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 20,
|
||||
child: MainMenuButton(
|
||||
text: loc.create_statistic,
|
||||
icon: Icons.bar_chart,
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
adaptivePageRoute(
|
||||
builder: (context) => CreateStatisticView(
|
||||
onStatisticCreated: loadStatisticData,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
Reference in New Issue
Block a user