diff --git a/lib/l10n/arb/app_de.arb b/lib/l10n/arb/app_de.arb index 5492bab..7bc117f 100644 --- a/lib/l10n/arb/app_de.arb +++ b/lib/l10n/arb/app_de.arb @@ -132,6 +132,7 @@ "statistics": "Statistiken", "stats": "Statistiken", "successfully_added_player": "Spieler:in {playerName} erfolgreich hinzugefügt", + "teams": "Teams", "there_are_no_games_matching_your_search": "Es gibt keine Spielvorlagen, die deiner Suche entspricht", "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.", diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index 7fb944b..48d4eec 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -141,6 +141,7 @@ } } }, + "teams": "Teams", "there_are_no_games_matching_your_search": "There are no games matching your search", "there_is_no_group_matching_your_search": "There is no group matching your search", "this_cannot_be_undone": "This can't be undone.", diff --git a/lib/l10n/generated/app_localizations.dart b/lib/l10n/generated/app_localizations.dart index bfdb659..f60a19d 100644 --- a/lib/l10n/generated/app_localizations.dart +++ b/lib/l10n/generated/app_localizations.dart @@ -842,6 +842,12 @@ abstract class AppLocalizations { /// **'Successfully added player {playerName}'** String successfully_added_player(String playerName); + /// No description provided for @teams. + /// + /// In en, this message translates to: + /// **'Teams'** + String get teams; + /// No description provided for @there_are_no_games_matching_your_search. /// /// In en, this message translates to: diff --git a/lib/l10n/generated/app_localizations_de.dart b/lib/l10n/generated/app_localizations_de.dart index 8567ba0..1480887 100644 --- a/lib/l10n/generated/app_localizations_de.dart +++ b/lib/l10n/generated/app_localizations_de.dart @@ -404,6 +404,9 @@ class AppLocalizationsDe extends AppLocalizations { return 'Spieler:in $playerName erfolgreich hinzugefügt'; } + @override + String get teams => 'Teams'; + @override String get there_are_no_games_matching_your_search => 'Es gibt keine Spielvorlagen, die deiner Suche entspricht'; diff --git a/lib/l10n/generated/app_localizations_en.dart b/lib/l10n/generated/app_localizations_en.dart index 04e68b4..738bb19 100644 --- a/lib/l10n/generated/app_localizations_en.dart +++ b/lib/l10n/generated/app_localizations_en.dart @@ -404,6 +404,9 @@ class AppLocalizationsEn extends AppLocalizations { return 'Successfully added player $playerName'; } + @override + String get teams => 'Teams'; + @override String get there_are_no_games_matching_your_search => 'There are no games matching your search'; diff --git a/lib/presentation/views/main_menu/match_view/match_detail_view.dart b/lib/presentation/views/main_menu/match_view/match_detail_view.dart index 86c26c6..90619dd 100644 --- a/lib/presentation/views/main_menu/match_view/match_detail_view.dart +++ b/lib/presentation/views/main_menu/match_view/match_detail_view.dart @@ -12,6 +12,7 @@ import 'package:tallee/l10n/generated/app_localizations.dart'; import 'package:tallee/presentation/views/main_menu/match_view/create_match/create_match_view.dart'; import 'package:tallee/presentation/views/main_menu/match_view/match_result_view.dart'; import 'package:tallee/presentation/widgets/buttons/main_menu_button.dart'; +import 'package:tallee/presentation/widgets/cards/team_card.dart'; import 'package:tallee/presentation/widgets/colored_icon_container.dart'; import 'package:tallee/presentation/widgets/dialog/custom_alert_dialog.dart'; import 'package:tallee/presentation/widgets/dialog/custom_dialog_action.dart'; @@ -153,25 +154,43 @@ class _MatchDetailViewState extends State { const SizedBox(height: 20), ], - // Players - InfoTile( - title: loc.players, - icon: Icons.people, - horizontalAlignment: CrossAxisAlignment.start, - content: Wrap( - alignment: WrapAlignment.start, - crossAxisAlignment: WrapCrossAlignment.start, - spacing: 12, - runSpacing: 8, - children: match.players.map((player) { - return TextIconTile( - text: player.name, - suffixText: getNameCountText(player), - iconEnabled: false, - ); - }).toList(), + if (match.isTeamMatch) ...[ + // Teams + InfoTile( + title: loc.teams, + icon: Icons.scoreboard, + horizontalAlignment: CrossAxisAlignment.start, + content: Wrap( + alignment: WrapAlignment.start, + crossAxisAlignment: WrapCrossAlignment.start, + spacing: 12, + runSpacing: 8, + children: match.teams!.map((team) { + return TeamCard(team: team); + }).toList(), + ), ), - ), + ] else ...[ + // Players + InfoTile( + title: loc.players, + icon: Icons.people, + horizontalAlignment: CrossAxisAlignment.start, + content: Wrap( + alignment: WrapAlignment.start, + crossAxisAlignment: WrapCrossAlignment.start, + spacing: 12, + runSpacing: 8, + children: match.players.map((player) { + return TextIconTile( + text: player.name, + suffixText: getNameCountText(player), + iconEnabled: false, + ); + }).toList(), + ), + ), + ], const SizedBox(height: 15), // Game diff --git a/lib/presentation/views/main_menu/match_view/match_result_view.dart b/lib/presentation/views/main_menu/match_view/match_result_view.dart index 296a9ef..27a1e39 100644 --- a/lib/presentation/views/main_menu/match_view/match_result_view.dart +++ b/lib/presentation/views/main_menu/match_view/match_result_view.dart @@ -59,7 +59,6 @@ class _MatchResultViewState extends State { ruleset = widget.match.game.ruleset; canSave = !rulesetSupportsScoreEntry(); isTeamMatch = widget.match.isTeamMatch; - print(widget.match.teams); if (isTeamMatch) { initializeAsTeamMatch(); @@ -290,12 +289,12 @@ class _MatchResultViewState extends State { Future _handleWinner() async { if (isTeamMatch) { if (_selectedTeam == null) { - return await db.teamDao.setWinnerTeam( + return await db.teamDao.removeWinnerTeam( matchId: widget.match.id, teamId: _selectedTeam!.id, ); } else { - return await db.teamDao.setLoserTeam( + return await db.teamDao.setWinnerTeam( matchId: widget.match.id, teamId: _selectedTeam!.id, ); diff --git a/lib/presentation/widgets/cards/team_card.dart b/lib/presentation/widgets/cards/team_card.dart new file mode 100644 index 0000000..43ef842 --- /dev/null +++ b/lib/presentation/widgets/cards/team_card.dart @@ -0,0 +1,104 @@ +import 'package:flutter/material.dart'; +import 'package:tallee/core/common.dart'; +import 'package:tallee/core/custom_theme.dart'; +import 'package:tallee/data/models/team.dart'; +import 'package:tallee/presentation/widgets/tiles/text_icon_tile.dart'; + +class TeamCard extends StatelessWidget { + const TeamCard({ + super.key, + required this.team, + this.compact = false, + this.width = double.infinity, + }); + + final Team team; + + final bool compact; + + final double width; + + @override + Widget build(BuildContext context) { + final teamColor = getColorFromGameColor(team.color); + + if (compact) { + return Container( + width: width, + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + decoration: BoxDecoration( + color: teamColor.withAlpha(50), + borderRadius: BorderRadius.circular(10), + border: Border.all(color: teamColor, width: 2), + ), + child: Row( + children: [ + Expanded( + child: Text( + team.name, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w700, + color: Colors.white, + ), + overflow: TextOverflow.ellipsis, + ), + ), + const SizedBox(width: 8), + Container( + width: 1, + height: 14, + color: Colors.white.withValues(alpha: 0.35), + ), + const SizedBox(width: 8), + const Icon(Icons.people_alt_rounded, size: 14, color: Colors.white), + const SizedBox(width: 4), + Text( + '${team.members.length}', + style: const TextStyle( + fontSize: 13, + fontWeight: FontWeight.w600, + color: Colors.white, + ), + ), + ], + ), + ); + } else { + return Container( + width: width, + padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12), + decoration: BoxDecoration( + color: teamColor.withAlpha(50), + borderRadius: BorderRadius.circular(8), + border: Border.all(color: teamColor, width: 2), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + spacing: 6, + children: [ + Text( + team.name, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, + color: CustomTheme.textColor, + ), + ), + Wrap( + spacing: 6, + runSpacing: 6, + children: team.members.map((player) { + return TextIconTile( + text: player.name, + suffixText: getNameCountText(player), + iconEnabled: false, + ); + }).toList(), + ), + ], + ), + ); + } + } +} diff --git a/lib/presentation/widgets/tiles/match_tile.dart b/lib/presentation/widgets/tiles/match_tile.dart index 8337c59..a9ffeb3 100644 --- a/lib/presentation/widgets/tiles/match_tile.dart +++ b/lib/presentation/widgets/tiles/match_tile.dart @@ -7,6 +7,7 @@ import 'package:tallee/core/custom_theme.dart'; import 'package:tallee/core/enums.dart'; import 'package:tallee/data/models/match.dart'; import 'package:tallee/l10n/generated/app_localizations.dart'; +import 'package:tallee/presentation/widgets/cards/team_card.dart'; import 'package:tallee/presentation/widgets/game_label.dart'; import 'package:tallee/presentation/widgets/tiles/text_icon_tile.dart'; @@ -244,56 +245,29 @@ class _MatchTileState extends State { ), ), const SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - for (var team in match.teams!) ...[ - Container( - width: double.infinity, - padding: const EdgeInsets.symmetric( - vertical: 6, - horizontal: 12, - ), - decoration: BoxDecoration( - color: getColorFromGameColor( - team.color, - ).withValues(alpha: 0.1), - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: getColorFromGameColor( - team.color, - ).withValues(alpha: 0.3), - width: 1, - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - team.name, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: CustomTheme.textColor, - ), - ), - Wrap( - spacing: 6, - runSpacing: 6, - children: team.members.map((player) { - return TextIconTile( - text: player.name, - suffixText: getNameCountText(player), - iconEnabled: false, - ); - }).toList(), - ), - ], - ), - ), - const SizedBox(height: 12), - ], - ], + LayoutBuilder( + builder: (context, constraints) { + final useSingleColumn = match.teams!.any( + (team) => team.name.length > 14, + ); + + const spacing = 8.0; + final itemWidth = useSingleColumn + ? constraints.maxWidth + : (constraints.maxWidth - spacing) / 2; + + return Wrap( + spacing: spacing, + runSpacing: spacing, + children: match.teams!.map((team) { + return TeamCard( + team: team, + compact: true, + width: itemWidth, + ); + }).toList(), + ); + }, ), const SizedBox(height: 12), ] else if (players.isNotEmpty && widget.compact == false) ...[ diff --git a/pubspec.yaml b/pubspec.yaml index 33dc417..595d1d7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: tallee description: "Tracking App for Card Games" publish_to: 'none' -version: 0.0.30+287 +version: 0.0.30+294 environment: sdk: ^3.8.1