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_players": "Nach Spieler:innen suchen",
|
||||
"select_winner": "Gewinner:in wählen",
|
||||
"select_winners": "Gewinner:innen wählen",
|
||||
"select_loser": "Verlierer:in wählen",
|
||||
"selected_players": "Ausgewählte Spieler:innen",
|
||||
"settings": "Einstellungen",
|
||||
|
||||
@@ -120,6 +120,7 @@
|
||||
"search_for_groups": "Search for groups",
|
||||
"search_for_players": "Search for players",
|
||||
"select_winner": "Select Winner",
|
||||
"select_winners": "Select Winners",
|
||||
"select_loser": "Select Loser",
|
||||
"selected_players": "Selected players",
|
||||
"settings": "Settings",
|
||||
|
||||
@@ -770,6 +770,12 @@ abstract class AppLocalizations {
|
||||
/// **'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.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
||||
@@ -366,6 +366,9 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||
@override
|
||||
String get select_winner => 'Gewinner:in wählen';
|
||||
|
||||
@override
|
||||
String get select_winners => 'Gewinner:innen wählen';
|
||||
|
||||
@override
|
||||
String get select_loser => 'Verlierer:in wählen';
|
||||
|
||||
|
||||
@@ -366,6 +366,9 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
@override
|
||||
String get select_winner => 'Select Winner';
|
||||
|
||||
@override
|
||||
String get select_winners => 'Select Winners';
|
||||
|
||||
@override
|
||||
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]
|
||||
Widget getResultWidget(AppLocalizations loc) {
|
||||
///TODO: add support for multiple winners
|
||||
if (isSingleRowResult()) {
|
||||
return Row(
|
||||
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/l10n/generated/app_localizations.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/live_edit_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
|
||||
late bool canSave;
|
||||
|
||||
/// Currently selected winner player
|
||||
/// Currently selected winner player (single winner)
|
||||
Player? _selectedPlayer;
|
||||
|
||||
/// Currently selected winners (multiple winners)
|
||||
Set<String> _selectedWinners = {};
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
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;
|
||||
return scoreB.compareTo(scoreA);
|
||||
});
|
||||
} else if (rulesetSupportsMultipleWinners()) {
|
||||
//TODO: Implement winners pre filling
|
||||
}
|
||||
;
|
||||
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();
|
||||
} else if (ruleset == Ruleset.placement) {
|
||||
await _handlePlacement();
|
||||
} else if (ruleset == Ruleset.multipleWinners) {
|
||||
await _handleWinners();
|
||||
}
|
||||
|
||||
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.
|
||||
Future<bool> _handleLoser() async {
|
||||
if (_selectedPlayer == null) {
|
||||
@@ -443,6 +488,8 @@ class _MatchResultViewState extends State<MatchResultView> {
|
||||
return loc.select_loser;
|
||||
case Ruleset.placement:
|
||||
return loc.drag_to_set_placement;
|
||||
case Ruleset.multipleWinners:
|
||||
return loc.select_winners;
|
||||
default:
|
||||
return loc.enter_points;
|
||||
}
|
||||
@@ -459,4 +506,8 @@ class _MatchResultViewState extends State<MatchResultView> {
|
||||
bool rulesetSupportsPlacement() {
|
||||
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