From 9a2afbfd3b67f49d08a7dcd2c3810fb3f8171049 Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Sun, 19 Apr 2026 22:49:21 +0200 Subject: [PATCH] Added ui implementation --- lib/core/common.dart | 8 +++++ .../group_view/group_detail_view.dart | 2 ++ .../match_view/match_detail_view.dart | 1 + .../widgets/player_selection.dart | 3 ++ .../widgets/tiles/group_tile.dart | 7 ++++- .../widgets/tiles/match_tile.dart | 6 +++- .../widgets/tiles/text_icon_list_tile.dart | 29 +++++++++++++++---- .../widgets/tiles/text_icon_tile.dart | 27 +++++++++++++++-- 8 files changed, 73 insertions(+), 10 deletions(-) diff --git a/lib/core/common.dart b/lib/core/common.dart index 20b0225..399872c 100644 --- a/lib/core/common.dart +++ b/lib/core/common.dart @@ -1,6 +1,7 @@ import 'package:flutter/cupertino.dart'; import 'package:tallee/core/enums.dart'; import 'package:tallee/data/models/match.dart'; +import 'package:tallee/data/models/player.dart'; import 'package:tallee/l10n/generated/app_localizations.dart'; /// Translates a [Ruleset] enum value to its corresponding localized string. @@ -43,3 +44,10 @@ String getExtraPlayerCount(Match match) { } return ' + ${count.toString()}'; } + +String getNameCountText(Player player) { + if (player.nameCount >= 1) { + return ' #${player.nameCount}'; + } + return ''; +} diff --git a/lib/presentation/views/main_menu/group_view/group_detail_view.dart b/lib/presentation/views/main_menu/group_view/group_detail_view.dart index 1ef89ef..0847ee5 100644 --- a/lib/presentation/views/main_menu/group_view/group_detail_view.dart +++ b/lib/presentation/views/main_menu/group_view/group_detail_view.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import 'package:tallee/core/adaptive_page_route.dart'; +import 'package:tallee/core/common.dart'; import 'package:tallee/core/custom_theme.dart'; import 'package:tallee/data/db/database.dart'; import 'package:tallee/data/models/group.dart'; @@ -153,6 +154,7 @@ class _GroupDetailViewState extends State { children: _group.members.map((member) { return TextIconTile( text: member.name, + suffixText: getNameCountText(member), iconEnabled: false, ); }).toList(), 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 fc53aa8..6671196 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 @@ -161,6 +161,7 @@ class _MatchDetailViewState extends State { children: match.players.map((player) { return TextIconTile( text: player.name, + suffixText: getNameCountText(player), iconEnabled: false, ); }).toList(), diff --git a/lib/presentation/widgets/player_selection.dart b/lib/presentation/widgets/player_selection.dart index 6d8769d..31bf942 100644 --- a/lib/presentation/widgets/player_selection.dart +++ b/lib/presentation/widgets/player_selection.dart @@ -1,5 +1,6 @@ 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/data/db/database.dart'; @@ -140,6 +141,7 @@ class _PlayerSelectionState extends State { padding: const EdgeInsets.only(right: 8.0), child: TextIconTile( text: player.name, + suffixText: getNameCountText(player), onIconTap: () { setState(() { // Removes the player from the selection and notifies the parent. @@ -193,6 +195,7 @@ class _PlayerSelectionState extends State { itemBuilder: (BuildContext context, int index) { return TextIconListTile( text: suggestedPlayers[index].name, + suffixText: getNameCountText(suggestedPlayers[index]), onPressed: () { setState(() { // If the player is not already selected diff --git a/lib/presentation/widgets/tiles/group_tile.dart b/lib/presentation/widgets/tiles/group_tile.dart index b62f3ce..f4ace65 100644 --- a/lib/presentation/widgets/tiles/group_tile.dart +++ b/lib/presentation/widgets/tiles/group_tile.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:tallee/core/common.dart'; import 'package:tallee/core/custom_theme.dart'; import 'package:tallee/data/models/group.dart'; import 'package:tallee/presentation/widgets/tiles/text_icon_tile.dart'; @@ -81,7 +82,11 @@ class _GroupTileState extends State { for (var member in [ ...widget.group.members, ]..sort((a, b) => a.name.compareTo(b.name))) - TextIconTile(text: member.name, iconEnabled: false), + TextIconTile( + text: member.name, + suffixText: getNameCountText(member), + iconEnabled: false, + ), ], ), const SizedBox(height: 2.5), diff --git a/lib/presentation/widgets/tiles/match_tile.dart b/lib/presentation/widgets/tiles/match_tile.dart index 39f9cdf..eaf6a4f 100644 --- a/lib/presentation/widgets/tiles/match_tile.dart +++ b/lib/presentation/widgets/tiles/match_tile.dart @@ -203,7 +203,11 @@ class _MatchTileState extends State { spacing: 6, runSpacing: 6, children: players.map((player) { - return TextIconTile(text: player.name, iconEnabled: false); + return TextIconTile( + text: player.name, + suffixText: getNameCountText(player), + iconEnabled: false, + ); }).toList(), ), ], diff --git a/lib/presentation/widgets/tiles/text_icon_list_tile.dart b/lib/presentation/widgets/tiles/text_icon_list_tile.dart index 2b29d41..a31f2ae 100644 --- a/lib/presentation/widgets/tiles/text_icon_list_tile.dart +++ b/lib/presentation/widgets/tiles/text_icon_list_tile.dart @@ -9,6 +9,7 @@ class TextIconListTile extends StatelessWidget { const TextIconListTile({ super.key, required this.text, + this.suffixText = '', this.iconEnabled = true, this.onPressed, }); @@ -16,6 +17,9 @@ class TextIconListTile extends StatelessWidget { /// The text to display in the tile. final String text; + /// An optional suffix text to display after the main text. + final String suffixText; + /// A boolean to determine if the icon should be displayed. final bool iconEnabled; @@ -35,12 +39,27 @@ class TextIconListTile extends StatelessWidget { Flexible( child: Container( padding: const EdgeInsets.symmetric(vertical: 12.5), - child: Text( - text, + child: RichText( overflow: TextOverflow.ellipsis, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, + text: TextSpan( + style: DefaultTextStyle.of(context).style, + children: [ + TextSpan( + text: text, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + ), + ), + TextSpan( + text: suffixText, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: CustomTheme.textColor.withAlpha(100), + ), + ), + ], ), ), ), diff --git a/lib/presentation/widgets/tiles/text_icon_tile.dart b/lib/presentation/widgets/tiles/text_icon_tile.dart index f98e0a7..541b6ae 100644 --- a/lib/presentation/widgets/tiles/text_icon_tile.dart +++ b/lib/presentation/widgets/tiles/text_icon_tile.dart @@ -9,6 +9,7 @@ class TextIconTile extends StatelessWidget { const TextIconTile({ super.key, required this.text, + this.suffixText = '', this.iconEnabled = true, this.onIconTap, }); @@ -16,6 +17,8 @@ class TextIconTile extends StatelessWidget { /// The text to display in the tile. final String text; + final String suffixText; + /// A boolean to determine if the icon should be displayed. final bool iconEnabled; @@ -36,10 +39,28 @@ class TextIconTile extends StatelessWidget { children: [ if (iconEnabled) const SizedBox(width: 3), Flexible( - child: Text( - text, + child: RichText( overflow: TextOverflow.ellipsis, - style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), + text: TextSpan( + style: DefaultTextStyle.of(context).style, + children: [ + TextSpan( + text: text, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + ), + ), + TextSpan( + text: suffixText, + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.w500, + color: CustomTheme.textColor.withAlpha(120), + ), + ), + ], + ), ), ), if (iconEnabled) ...[