Bearbeiten und Löschen von Gruppen #148

Merged
sneeex merged 20 commits from feature/118-bearbeiten-und-löschen-von-gruppen into development 2026-03-09 20:30:38 +00:00
5 changed files with 26 additions and 20 deletions
Showing only changes of commit 23d00c64ab - Show all commits

View File

@@ -3,6 +3,7 @@ import 'package:tallee/data/db/database.dart';
import 'package:tallee/data/db/tables/group_table.dart'; import 'package:tallee/data/db/tables/group_table.dart';
import 'package:tallee/data/db/tables/player_group_table.dart'; import 'package:tallee/data/db/tables/player_group_table.dart';
import 'package:tallee/data/dto/group.dart'; import 'package:tallee/data/dto/group.dart';
import 'package:tallee/data/dto/match.dart';
import 'package:tallee/data/dto/player.dart'; import 'package:tallee/data/dto/player.dart';
part 'group_dao.g.dart'; part 'group_dao.g.dart';
@@ -171,6 +172,12 @@ class GroupDao extends DatabaseAccessor<AppDatabase> with _$GroupDaoMixin {
}); });
} }
/// Retrieves all matches associated with the given [groupId].
Future<List<Match>> getGroupMatches({required String groupId}) async {
final matches = await db.matchDao.getAllMatches();
return matches.where((match) => match.group?.id == groupId).toList();
}
/// Deletes the group with the given [id] from the database. /// Deletes the group with the given [id] from the database.
/// Returns `true` if more than 0 rows were affected, otherwise `false`. /// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> deleteGroup({required String groupId}) async { Future<bool> deleteGroup({required String groupId}) async {

View File

@@ -338,10 +338,10 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
return rowsAffected > 0; return rowsAffected > 0;
} }
/// Entfernt die Gruppen-Verknüpfung des Matches mit der gegebenen [matchId]. /// Removes the group association of the match with the given [matchId].
/// Setzt die groupId auf null. /// Sets the groupId to null.
/// Gibt `true` zurück, wenn mehr als 0 Zeilen betroffen waren, ansonsten `false`. /// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> deleteMatchGroup({required String matchId}) async { Future<bool> removeMatchGroup({required String matchId}) async {
final query = update(matchTable)..where((g) => g.id.equals(matchId)); final query = update(matchTable)..where((g) => g.id.equals(matchId));
final rowsAffected = await query.write( final rowsAffected = await query.write(
const MatchTableCompanion(groupId: Value(null)), const MatchTableCompanion(groupId: Value(null)),

View File

@@ -190,11 +190,16 @@ class _CreateGroupViewState extends State<CreateGroupView> {
return (success, updatedGroup); return (success, updatedGroup);
} }
/// Removes the group association from matches that no longer belong to the edited group.
///
/// After updating the group's members, matches that were previously linked to
/// this group but don't have any of the newly selected players are considered
/// obsolete. For each such match, the group association is removed by setting
/// its [groupId] to null.
Future<void> deleteObsoleteMatchGroupRelations() async { Future<void> deleteObsoleteMatchGroupRelations() async {
final matches = await db.matchDao.getAllMatches(); final groupMatches = await db.groupDao.getGroupMatches(
final groupMatches = matches groupId: widget.groupToEdit!.id,
.where((match) => match.group?.id == widget.groupToEdit!.id) );
.toList();
final selectedPlayerIds = selectedPlayers.map((p) => p.id).toSet(); final selectedPlayerIds = selectedPlayers.map((p) => p.id).toSet();
final relationshipsToDelete = groupMatches.where((match) { final relationshipsToDelete = groupMatches.where((match) {
@@ -204,7 +209,7 @@ class _CreateGroupViewState extends State<CreateGroupView> {
}).toList(); }).toList();
for (var match in relationshipsToDelete) { for (var match in relationshipsToDelete) {
await db.matchDao.deleteMatchGroup(matchId: match.id); await db.matchDao.removeMatchGroup(matchId: match.id);
} }
} }

View File

@@ -194,7 +194,6 @@ class _GroupDetailViewState extends State<GroupDetailView> {
return CreateGroupView( return CreateGroupView(
groupToEdit: _group, groupToEdit: _group,
onMembersChanged: () { onMembersChanged: () {
isLoading = true;
_loadStatistics(); _loadStatistics();
sneeex marked this conversation as resolved
Review

Warum wird isLoading nicht in _loadStatistics auf true gesetzt?

Warum wird `isLoading` nicht in `_loadStatistics` auf true gesetzt?
Review

weil du's so gemacht hast großer

weil du's so gemacht hast großer
Review

Setzt es mal in der Methode anfangs auf true, so ists z.B. auch im GroupView

Setzt es mal in der Methode anfangs auf true, so ists z.B. auch im `GroupView`
}, },
); );
@@ -248,10 +247,8 @@ class _GroupDetailViewState extends State<GroupDetailView> {
/// Loads statistics for this group /// Loads statistics for this group
Future<void> _loadStatistics() async { Future<void> _loadStatistics() async {
final matches = await db.matchDao.getAllMatches(); isLoading = true;
final groupMatches = matches final groupMatches = await db.groupDao.getGroupMatches(groupId: _group.id);
.where((match) => match.group?.id == _group.id)
.toList();
setState(() { setState(() {
totalMatches = groupMatches.length; totalMatches = groupMatches.length;

View File

@@ -308,13 +308,12 @@ void main() {
expect(fetchedMatch.winner!.id, testPlayer5.id); expect(fetchedMatch.winner!.id, testPlayer5.id);
}); });
// Tests for removeMatchGroup
test( test(
sneeex marked this conversation as resolved
Review

Unnötiger Kommentar

Unnötiger Kommentar
'removeMatchGroup removes group from match with existing group', 'removeMatchGroup removes group from match with existing group',
() async { () async {
await database.matchDao.addMatch(match: testMatch1); await database.matchDao.addMatch(match: testMatch1);
final removed = await database.matchDao.deleteMatchGroup( final removed = await database.matchDao.removeMatchGroup(
matchId: testMatch1.id, matchId: testMatch1.id,
); );
expect(removed, isTrue); expect(removed, isTrue);
@@ -323,7 +322,6 @@ void main() {
matchId: testMatch1.id, matchId: testMatch1.id,
); );
expect(updatedMatch.group, null); expect(updatedMatch.group, null);
// Andere Felder bleiben unverändert
expect(updatedMatch.game.id, testMatch1.game.id); expect(updatedMatch.game.id, testMatch1.game.id);
expect(updatedMatch.name, testMatch1.name); expect(updatedMatch.name, testMatch1.name);
sneeex marked this conversation as resolved
Review

Unnötiger Kommentar & auf deutsch

Unnötiger Kommentar & auf deutsch
expect(updatedMatch.notes, testMatch1.notes); expect(updatedMatch.notes, testMatch1.notes);
@@ -335,10 +333,9 @@ void main() {
() async { () async {
await database.matchDao.addMatch(match: testMatchOnlyPlayers); await database.matchDao.addMatch(match: testMatchOnlyPlayers);
final removed = await database.matchDao.deleteMatchGroup( final removed = await database.matchDao.removeMatchGroup(
matchId: testMatchOnlyPlayers.id, matchId: testMatchOnlyPlayers.id,
); );
// Update sollte trotzdem eine Zeile betreffen
expect(removed, isTrue); expect(removed, isTrue);
final updatedMatch = await database.matchDao.getMatchById( final updatedMatch = await database.matchDao.getMatchById(
sneeex marked this conversation as resolved
Review

Unnötiger Kommentar & auf deutsch

Unnötiger Kommentar & auf deutsch
@@ -349,7 +346,7 @@ void main() {
); );
test('removeMatchGroup on non-existing match returns false', () async { test('removeMatchGroup on non-existing match returns false', () async {
final removed = await database.matchDao.deleteMatchGroup( final removed = await database.matchDao.removeMatchGroup(
matchId: 'non-existing-id', matchId: 'non-existing-id',
); );
expect(removed, isFalse); expect(removed, isFalse);