Add support for selecting multiple winners and update localization
This commit is contained in:
@@ -120,6 +120,7 @@
|
|||||||
"search_for_groups": "Nach Gruppen suchen",
|
"search_for_groups": "Nach Gruppen suchen",
|
||||||
"search_for_players": "Nach Spieler:innen suchen",
|
"search_for_players": "Nach Spieler:innen suchen",
|
||||||
"select_winner": "Gewinner:in wählen",
|
"select_winner": "Gewinner:in wählen",
|
||||||
|
"select_winners": "Gewinner:innen wählen",
|
||||||
"select_loser": "Verlierer:in wählen",
|
"select_loser": "Verlierer:in wählen",
|
||||||
"selected_players": "Ausgewählte Spieler:innen",
|
"selected_players": "Ausgewählte Spieler:innen",
|
||||||
"settings": "Einstellungen",
|
"settings": "Einstellungen",
|
||||||
|
|||||||
@@ -120,6 +120,7 @@
|
|||||||
"search_for_groups": "Search for groups",
|
"search_for_groups": "Search for groups",
|
||||||
"search_for_players": "Search for players",
|
"search_for_players": "Search for players",
|
||||||
"select_winner": "Select Winner",
|
"select_winner": "Select Winner",
|
||||||
|
"select_winners": "Select Winners",
|
||||||
"select_loser": "Select Loser",
|
"select_loser": "Select Loser",
|
||||||
"selected_players": "Selected players",
|
"selected_players": "Selected players",
|
||||||
"settings": "Settings",
|
"settings": "Settings",
|
||||||
|
|||||||
@@ -770,6 +770,12 @@ abstract class AppLocalizations {
|
|||||||
/// **'Select Winner'**
|
/// **'Select Winner'**
|
||||||
String get select_winner;
|
String get select_winner;
|
||||||
|
|
||||||
|
/// No description provided for @select_winners.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Select Winners'**
|
||||||
|
String get select_winners;
|
||||||
|
|
||||||
/// No description provided for @select_loser.
|
/// No description provided for @select_loser.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|||||||
@@ -366,6 +366,9 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get select_winner => 'Gewinner:in wählen';
|
String get select_winner => 'Gewinner:in wählen';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get select_winners => 'Gewinner:innen wählen';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get select_loser => 'Verlierer:in wählen';
|
String get select_loser => 'Verlierer:in wählen';
|
||||||
|
|
||||||
|
|||||||
@@ -366,6 +366,9 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get select_winner => 'Select Winner';
|
String get select_winner => 'Select Winner';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get select_winners => 'Select Winners';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get select_loser => 'Select Loser';
|
String get select_loser => 'Select Loser';
|
||||||
|
|
||||||
|
|||||||
@@ -269,6 +269,7 @@ class _MatchDetailViewState extends State<MatchDetailView> {
|
|||||||
|
|
||||||
/// Returns the widget to be displayed in the result [InfoTile]
|
/// Returns the widget to be displayed in the result [InfoTile]
|
||||||
Widget getResultWidget(AppLocalizations loc) {
|
Widget getResultWidget(AppLocalizations loc) {
|
||||||
|
///TODO: add support for multiple winners
|
||||||
if (isSingleRowResult()) {
|
if (isSingleRowResult()) {
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import 'package:tallee/data/models/player.dart';
|
|||||||
import 'package:tallee/data/models/score_entry.dart';
|
import 'package:tallee/data/models/score_entry.dart';
|
||||||
import 'package:tallee/l10n/generated/app_localizations.dart';
|
import 'package:tallee/l10n/generated/app_localizations.dart';
|
||||||
import 'package:tallee/presentation/widgets/buttons/custom_width_button.dart';
|
import 'package:tallee/presentation/widgets/buttons/custom_width_button.dart';
|
||||||
|
import 'package:tallee/presentation/widgets/tiles/match_result_view/custom_checkbox_list_tile.dart';
|
||||||
import 'package:tallee/presentation/widgets/tiles/match_result_view/custom_radio_list_tile.dart';
|
import 'package:tallee/presentation/widgets/tiles/match_result_view/custom_radio_list_tile.dart';
|
||||||
import 'package:tallee/presentation/widgets/tiles/match_result_view/live_edit_list_tile.dart';
|
import 'package:tallee/presentation/widgets/tiles/match_result_view/live_edit_list_tile.dart';
|
||||||
import 'package:tallee/presentation/widgets/tiles/match_result_view/score_list_tile.dart';
|
import 'package:tallee/presentation/widgets/tiles/match_result_view/score_list_tile.dart';
|
||||||
@@ -45,9 +46,12 @@ class _MatchResultViewState extends State<MatchResultView> {
|
|||||||
/// Flag to indicate if the save button should be enabled
|
/// Flag to indicate if the save button should be enabled
|
||||||
late bool canSave;
|
late bool canSave;
|
||||||
|
|
||||||
/// Currently selected winner player
|
/// Currently selected winner player (single winner)
|
||||||
Player? _selectedPlayer;
|
Player? _selectedPlayer;
|
||||||
|
|
||||||
|
/// Currently selected winners (multiple winners)
|
||||||
|
Set<String> _selectedWinners = {};
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
db = Provider.of<AppDatabase>(context, listen: false);
|
db = Provider.of<AppDatabase>(context, listen: false);
|
||||||
@@ -80,7 +84,10 @@ class _MatchResultViewState extends State<MatchResultView> {
|
|||||||
final scoreB = widget.match.scores[b.id]?.score ?? 0;
|
final scoreB = widget.match.scores[b.id]?.score ?? 0;
|
||||||
return scoreB.compareTo(scoreA);
|
return scoreB.compareTo(scoreA);
|
||||||
});
|
});
|
||||||
|
} else if (rulesetSupportsMultipleWinners()) {
|
||||||
|
//TODO: Implement winners pre filling
|
||||||
}
|
}
|
||||||
|
;
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -319,6 +326,36 @@ class _MatchResultViewState extends State<MatchResultView> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// Show multiple winner selection
|
||||||
|
if (rulesetSupportsMultipleWinners())
|
||||||
|
Expanded(
|
||||||
|
child: ListView.builder(
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
itemCount: allPlayers.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return CustomCheckboxListTile(
|
||||||
|
text: allPlayers[index].name,
|
||||||
|
value: _selectedWinners.contains(
|
||||||
|
allPlayers[index].id,
|
||||||
|
),
|
||||||
|
onChanged: (bool value) {
|
||||||
|
setState(() {
|
||||||
|
if (value) {
|
||||||
|
_selectedWinners.add(
|
||||||
|
allPlayers[index].id,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
_selectedWinners.remove(
|
||||||
|
allPlayers[index].id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -382,6 +419,8 @@ class _MatchResultViewState extends State<MatchResultView> {
|
|||||||
await _handleScores();
|
await _handleScores();
|
||||||
} else if (ruleset == Ruleset.placement) {
|
} else if (ruleset == Ruleset.placement) {
|
||||||
await _handlePlacement();
|
await _handlePlacement();
|
||||||
|
} else if (ruleset == Ruleset.multipleWinners) {
|
||||||
|
await _handleWinners();
|
||||||
}
|
}
|
||||||
|
|
||||||
widget.onWinnerChanged?.call();
|
widget.onWinnerChanged?.call();
|
||||||
@@ -399,6 +438,12 @@ class _MatchResultViewState extends State<MatchResultView> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handles saving the winners to the database.
|
||||||
|
Future<bool> _handleWinners() async {
|
||||||
|
//TODO: Implement winner handling
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// Handles saving or removing the loser in the database.
|
/// Handles saving or removing the loser in the database.
|
||||||
Future<bool> _handleLoser() async {
|
Future<bool> _handleLoser() async {
|
||||||
if (_selectedPlayer == null) {
|
if (_selectedPlayer == null) {
|
||||||
@@ -443,6 +488,8 @@ class _MatchResultViewState extends State<MatchResultView> {
|
|||||||
return loc.select_loser;
|
return loc.select_loser;
|
||||||
case Ruleset.placement:
|
case Ruleset.placement:
|
||||||
return loc.drag_to_set_placement;
|
return loc.drag_to_set_placement;
|
||||||
|
case Ruleset.multipleWinners:
|
||||||
|
return loc.select_winners;
|
||||||
default:
|
default:
|
||||||
return loc.enter_points;
|
return loc.enter_points;
|
||||||
}
|
}
|
||||||
@@ -459,4 +506,8 @@ class _MatchResultViewState extends State<MatchResultView> {
|
|||||||
bool rulesetSupportsPlacement() {
|
bool rulesetSupportsPlacement() {
|
||||||
return ruleset == Ruleset.placement;
|
return ruleset == Ruleset.placement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool rulesetSupportsMultipleWinners() {
|
||||||
|
return ruleset == Ruleset.multipleWinners;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:tallee/core/custom_theme.dart';
|
||||||
|
|
||||||
|
class CustomCheckboxListTile extends StatelessWidget {
|
||||||
|
const CustomCheckboxListTile({
|
||||||
|
super.key,
|
||||||
|
required this.text,
|
||||||
|
required this.value,
|
||||||
|
required this.onChanged,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String text;
|
||||||
|
final bool value;
|
||||||
|
final ValueChanged<bool> onChanged;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () => onChanged(!value),
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 5, vertical: 5),
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 2),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: CustomTheme.boxColor,
|
||||||
|
border: Border.all(color: CustomTheme.boxBorderColor),
|
||||||
|
borderRadius: CustomTheme.standardBorderRadiusAll,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Checkbox(
|
||||||
|
value: value,
|
||||||
|
onChanged: (bool? v) {
|
||||||
|
if (v == null) return;
|
||||||
|
onChanged(v);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
text,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user