From e761fb14741c924973ca721d0cf47ffefc4f3c31 Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Thu, 21 May 2026 17:51:15 +0200 Subject: [PATCH] Inserted custom tiles, comments --- lib/l10n/arb/app_de.arb | 1 + lib/l10n/arb/app_en.arb | 1 + .../create_teams/manage_members_view.dart | 231 ++++++++++-------- 3 files changed, 127 insertions(+), 106 deletions(-) diff --git a/lib/l10n/arb/app_de.arb b/lib/l10n/arb/app_de.arb index f97b827..de579ff 100644 --- a/lib/l10n/arb/app_de.arb +++ b/lib/l10n/arb/app_de.arb @@ -86,6 +86,7 @@ "match_name": "Spieltitel", "match_profile": "Spielprofil", "matches": "Spiele", + "member": "Mitglied", "members": "Mitglieder", "most_points": "Höchste Punkte", "multiple_winners": "Mehrere Gewinner:innen", diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index 79883fa..b77797c 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -86,6 +86,7 @@ "match_name": "Match name", "match_profile": "Match Profile", "matches": "Matches", + "member": "Member", "members": "Members", "most_points": "Most Points", "multiple_winners": "Multiple Winners", diff --git a/lib/presentation/views/main_menu/match_view/create_match/create_teams/manage_members_view.dart b/lib/presentation/views/main_menu/match_view/create_match/create_teams/manage_members_view.dart index befd38e..49ba9fd 100644 --- a/lib/presentation/views/main_menu/match_view/create_match/create_teams/manage_members_view.dart +++ b/lib/presentation/views/main_menu/match_view/create_match/create_teams/manage_members_view.dart @@ -2,6 +2,7 @@ import 'dart:core' hide Match; import 'dart:math'; import 'package:flutter/material.dart'; +import 'package:flutter_numeric_text/flutter_numeric_text.dart'; import 'package:fluttericon/rpg_awesome_icons.dart'; import 'package:provider/provider.dart'; import 'package:tallee/core/common.dart'; @@ -117,24 +118,58 @@ class _ManageMembersViewState extends State { ); } - void submitMatch() async { - await db.matchDao.addMatch(match: widget.match); - if (mounted) { - Navigator.pushAndRemoveUntil( - context, - MaterialPageRoute( - builder: (_) => MatchResultView( - match: widget.match, - onWinnerChanged: widget.onWinnerChanged, - ), - ), - (route) => route.isFirst, - ); - } - } + Widget buildTeamTile({required Team team}) { + final color = getColorFromGameColor(team.color); + final loc = AppLocalizations.of(context); + final length = team.members.length; + final memberText = length == 1 ? loc.member : loc.members; - bool get allTeamsHaveMembers { - return teams.every((team) => team.members.isNotEmpty); + return Padding( + key: ValueKey(team.id), + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12), + child: Row( + children: [ + // Color circle + Container( + width: 14, + height: 14, + decoration: BoxDecoration(color: color, shape: BoxShape.circle), + ), + + const SizedBox(width: 10), + + // Team name + Expanded( + child: Text( + team.name, + style: const TextStyle( + color: CustomTheme.textColor, + fontSize: 17, + fontWeight: FontWeight.bold, + ), + overflow: TextOverflow.ellipsis, + ), + ), + + // Member length + SizedBox( + width: 150, + child: NumericText( + '$length $memberText', + duration: const Duration(milliseconds: 200), + maxLines: 1, + textAlign: TextAlign.end, + overflow: TextOverflow.ellipsis, + style: const TextStyle( + color: CustomTheme.hintColor, + fontSize: 14, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + ); } // Iterates through all teams and redistributes players randomly and @@ -158,6 +193,63 @@ class _ManageMembersViewState extends State { } } + /// Handles moving a member from one team to another + void onReorder(int oldIndex, int newIndex) { + final sourceTeamIndex = teamIndexForFlat(oldIndex); + final sourceMemberIndex = memberIndexForFlat(oldIndex, sourceTeamIndex); + + // Headers themselves can't be reordered. + if (sourceMemberIndex == -1) return; + + // When moving down, the target index is shifted by 1 + // because the item is removed first. + var targetIndex = newIndex; + if (newIndex > oldIndex) targetIndex -= 1; + targetIndex = targetIndex.clamp(0, allItemsCount - 1); + + // Resolve target location based on the item currently at targetIndex + // before the move. + int destTeamIndex; + int insertPositionInTeam; + + if (targetIndex >= allItemsCount - 1 && newIndex >= allItemsCount) { + // Dropped at the very end, append to the last team. + destTeamIndex = teams.length - 1; + insertPositionInTeam = teams[destTeamIndex].members.length; + } else { + destTeamIndex = teamIndexForFlat(targetIndex); + final anchorMemberIndex = memberIndexForFlat(targetIndex, destTeamIndex); + + if (anchorMemberIndex == -1) { + // Dropped right before a header, append to the previous team. + destTeamIndex = destTeamIndex - 1; + if (destTeamIndex < 0) { + // Dropped above the very first header, stay in team 0 at top. + destTeamIndex = 0; + insertPositionInTeam = 0; + } else { + insertPositionInTeam = teams[destTeamIndex].members.length; + } + } else { + insertPositionInTeam = anchorMemberIndex; + } + } + + setState(() { + final sourceMembers = teams[sourceTeamIndex].members; + final player = sourceMembers.removeAt(sourceMemberIndex); + + // Adjust insert index if removed from before the insert point in the + // same team. + if (sourceTeamIndex == destTeamIndex && + insertPositionInTeam > sourceMembers.length) { + insertPositionInTeam = sourceMembers.length; + } + + teams[destTeamIndex].members.insert(insertPositionInTeam, player); + }); + } + /// Total players + teams length int get allItemsCount { var count = 0; @@ -191,96 +283,23 @@ class _ManageMembersViewState extends State { return localIndex == 0 ? -1 : localIndex - 1; } - void onReorder(int oldIndex, int newIndex) { - final sourceTeamIndex = teamIndexForFlat(oldIndex); - final sourceMemberIndex = memberIndexForFlat(oldIndex, sourceTeamIndex); + bool get allTeamsHaveMembers => + teams.every((team) => team.members.isNotEmpty); - // Headers themselves can't be reordered. - if (sourceMemberIndex == -1) return; - - // Flutter convention: when moving down, the target index is shifted by 1 - // because the item is removed first. - var targetIndex = newIndex; - if (newIndex > oldIndex) targetIndex -= 1; - targetIndex = targetIndex.clamp(0, allItemsCount - 1); - - // Resolve target location based on the item currently at [targetIndex] - // *before* the move. - int destTeamIndex; - int insertPositionInTeam; - - if (targetIndex >= allItemsCount - 1 && newIndex >= allItemsCount) { - // Dropped at the very end -> append to the last team. - destTeamIndex = teams.length - 1; - insertPositionInTeam = teams[destTeamIndex].members.length; - } else { - destTeamIndex = teamIndexForFlat(targetIndex); - final anchorMemberIndex = memberIndexForFlat(targetIndex, destTeamIndex); - - if (anchorMemberIndex == -1) { - // Dropped right before a header -> append to the previous team. - destTeamIndex = destTeamIndex - 1; - if (destTeamIndex < 0) { - // Dropped above the very first header -> stay in team 0 at top. - destTeamIndex = 0; - insertPositionInTeam = 0; - } else { - insertPositionInTeam = teams[destTeamIndex].members.length; - } - } else { - insertPositionInTeam = anchorMemberIndex; - } + void submitMatch() async { + final match = widget.match.copyWith(teams: teams); + await db.matchDao.addMatch(match: match); + if (mounted) { + Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute( + builder: (_) => MatchResultView( + match: match, + onWinnerChanged: widget.onWinnerChanged, + ), + ), + (route) => route.isFirst, + ); } - - setState(() { - final sourceMembers = teams[sourceTeamIndex].members; - final player = sourceMembers.removeAt(sourceMemberIndex); - - // Adjust insert index if we removed from before the insert point in the - // same team. - if (sourceTeamIndex == destTeamIndex && - insertPositionInTeam > sourceMembers.length) { - insertPositionInTeam = sourceMembers.length; - } - - teams[destTeamIndex].members.insert(insertPositionInTeam, player); - }); - } - - Widget buildTeamTile({required Team team}) { - final color = getColorFromGameColor(team.color); - return Padding( - key: ValueKey('header_${team.id}'), - padding: const EdgeInsets.fromLTRB(12, 16, 12, 8), - child: Row( - children: [ - Container( - width: 14, - height: 14, - decoration: BoxDecoration(color: color, shape: BoxShape.circle), - ), - const SizedBox(width: 10), - Expanded( - child: Text( - team.name, - style: const TextStyle( - color: CustomTheme.textColor, - fontSize: 17, - fontWeight: FontWeight.bold, - ), - overflow: TextOverflow.ellipsis, - ), - ), - Text( - '${team.members.length}', - style: const TextStyle( - color: CustomTheme.hintColor, - fontSize: 14, - fontWeight: FontWeight.w600, - ), - ), - ], - ), - ); } }