From f6156e51146738082195972bf97eab8639911dbb Mon Sep 17 00:00:00 2001 From: Farid-Efrei <128361230+Farid-Efrei@users.noreply.github.com> Date: Thu, 6 Nov 2025 11:26:33 +0100 Subject: [PATCH 1/2] =?UTF-8?q?Bug:=20Corrections=20des=20bugs=20des=20ass?= =?UTF-8?q?ignations=20et=20de=20l'UPDATE=20des=20t=C3=A2ches.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widgets/assign_users_dialog.dart | 87 ++++++++++++++++++- .../presentation/widgets/task_modal.dart | 11 ++- 2 files changed, 95 insertions(+), 3 deletions(-) diff --git a/lib/features/tasks/presentation/widgets/assign_users_dialog.dart b/lib/features/tasks/presentation/widgets/assign_users_dialog.dart index c6054de..9e16017 100644 --- a/lib/features/tasks/presentation/widgets/assign_users_dialog.dart +++ b/lib/features/tasks/presentation/widgets/assign_users_dialog.dart @@ -26,10 +26,17 @@ class _AssignUsersDialogState extends State late AnimationController _animationController; late Animation _fadeAnimation; late Animation _slideAnimation; + + // Sauvegarder l'état initial pour permettre l'annulation + late List _initialAssignedUsers; @override void initState() { super.initState(); + + // Sauvegarder l'état initial des assignations + _initialAssignedUsers = List.from(widget.task.assignedTo); + _loadUsers(); // Animations d'entrée @@ -96,12 +103,79 @@ class _AssignUsersDialogState extends State }); } + /// Annule toutes les modifications et restaure l'état initial + Future _cancelChanges() async { + try { + final provider = context.read(); + final currentTask = provider.allTasks.firstWhere((t) => t.id == widget.task.id); + final currentAssignedUsers = currentTask.assignedTo; + + // Trouver les utilisateurs à retirer (qui ont été ajoutés) + final usersToRemove = currentAssignedUsers + .where((userId) => !_initialAssignedUsers.contains(userId)) + .toList(); + + // Trouver les utilisateurs à rajouter (qui ont été retirés) + final usersToAdd = _initialAssignedUsers + .where((userId) => !currentAssignedUsers.contains(userId)) + .toList(); + + // Effectuer les modifications pour restaurer l'état initial + for (final userId in usersToRemove) { + await provider.unassignUserFromTask(widget.task.id, userId); + } + + for (final userId in usersToAdd) { + await provider.assignUserToTask(widget.task.id, userId); + } + + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Row( + children: [ + const Icon(Icons.undo, color: Colors.white), + const SizedBox(width: 12), + const Expanded( + child: Text( + 'Modifications annulées', + style: TextStyle(fontWeight: FontWeight.w600), + ), + ), + ], + ), + backgroundColor: AppColors.getOnSurface(context).withOpacity(0.8), + duration: const Duration(seconds: 2), + behavior: SnackBarBehavior.floating, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ), + ); + + // Fermer le dialog après avoir annulé + Navigator.of(context).pop(); + } + } catch (e) { + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Erreur lors de l\'annulation: $e'), + backgroundColor: AppColors.error, + ), + ); + } + } + } + Future _toggleUserAssignment(String userId, bool isAssigned) async { try { final provider = context.read(); if (isAssigned) { + // L'utilisateur EST déjà assigné → on le RETIRE await provider.unassignUserFromTask(widget.task.id, userId); } else { + // L'utilisateur N'EST PAS assigné → on l'AJOUTE await provider.assignUserToTask(widget.task.id, userId); } @@ -562,6 +636,17 @@ class _AssignUsersDialogState extends State ), ), ), + // Bouton Annuler - Restaure l'état initial + TextButton( + onPressed: _cancelChanges, + style: TextButton.styleFrom( + foregroundColor: AppColors.getOnSurface(context).withOpacity(0.7), + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12), + ), + child: const Text('Annuler'), + ), + const SizedBox(width: 8), + // Bouton Modifier - Ferme le dialog (changements déjà appliqués) ElevatedButton( onPressed: () => Navigator.of(context).pop(), style: ElevatedButton.styleFrom( @@ -572,7 +657,7 @@ class _AssignUsersDialogState extends State borderRadius: BorderRadius.circular(12), ), ), - child: const Text('Terminé'), + child: const Text('Modifier'), ), ], ), diff --git a/lib/features/tasks/presentation/widgets/task_modal.dart b/lib/features/tasks/presentation/widgets/task_modal.dart index bf925e9..4d77180 100644 --- a/lib/features/tasks/presentation/widgets/task_modal.dart +++ b/lib/features/tasks/presentation/widgets/task_modal.dart @@ -99,8 +99,14 @@ class _TaskModalState extends State { } if (_isEditing) { - // Modifier la tâche existante - final updatedTask = widget.task!.copyWith( + // Récupérer la tâche actuelle depuis le provider pour avoir les assignations à jour + final currentTask = taskProvider.allTasks.firstWhere( + (t) => t.id == widget.task!.id, + orElse: () => widget.task!, + ); + + // Modifier la tâche existante en gardant les assignations actuelles + final updatedTask = currentTask.copyWith( title: _titleController.text.trim(), description: _descriptionController.text.trim(), priority: _selectedPriority, @@ -108,6 +114,7 @@ class _TaskModalState extends State { tags: _selectedTags, ); print('📝 TaskModal - Modification tâche: ${updatedTask.id}'); + print(' - assignedTo conservé: ${updatedTask.assignedTo}'); taskProvider.updateTask(updatedTask); } else { // Créer une nouvelle tâche avec ownerId et ownerName From d4849896b335e30bf7d8ad93ac67e280f4a1b141 Mon Sep 17 00:00:00 2001 From: Farid-Efrei <128361230+Farid-Efrei@users.noreply.github.com> Date: Thu, 6 Nov 2025 11:29:28 +0100 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20Corriger=20l'annulation=20des=20assi?= =?UTF-8?q?gnations=20lors=20de=20la=20modification=20de=20t=C3=A2che?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Récupérer la tâche actuelle depuis le provider pour préserver les assignations - Ajouter méthode _cancelChanges dans assign_users_dialog pour annuler les modifications - Les assignations faites en temps réel sont maintenant conservées lors de la sauvegarde --- .../presentation/widgets/assign_users_dialog.dart | 12 +++++++----- .../tasks/presentation/widgets/task_modal.dart | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/features/tasks/presentation/widgets/assign_users_dialog.dart b/lib/features/tasks/presentation/widgets/assign_users_dialog.dart index 9e16017..5c538d1 100644 --- a/lib/features/tasks/presentation/widgets/assign_users_dialog.dart +++ b/lib/features/tasks/presentation/widgets/assign_users_dialog.dart @@ -26,17 +26,17 @@ class _AssignUsersDialogState extends State late AnimationController _animationController; late Animation _fadeAnimation; late Animation _slideAnimation; - + // Sauvegarder l'état initial pour permettre l'annulation late List _initialAssignedUsers; @override void initState() { super.initState(); - + // Sauvegarder l'état initial des assignations _initialAssignedUsers = List.from(widget.task.assignedTo); - + _loadUsers(); // Animations d'entrée @@ -107,7 +107,9 @@ class _AssignUsersDialogState extends State Future _cancelChanges() async { try { final provider = context.read(); - final currentTask = provider.allTasks.firstWhere((t) => t.id == widget.task.id); + final currentTask = provider.allTasks.firstWhere( + (t) => t.id == widget.task.id, + ); final currentAssignedUsers = currentTask.assignedTo; // Trouver les utilisateurs à retirer (qui ont été ajoutés) @@ -152,7 +154,7 @@ class _AssignUsersDialogState extends State ), ), ); - + // Fermer le dialog après avoir annulé Navigator.of(context).pop(); } diff --git a/lib/features/tasks/presentation/widgets/task_modal.dart b/lib/features/tasks/presentation/widgets/task_modal.dart index 4d77180..683f336 100644 --- a/lib/features/tasks/presentation/widgets/task_modal.dart +++ b/lib/features/tasks/presentation/widgets/task_modal.dart @@ -104,7 +104,7 @@ class _TaskModalState extends State { (t) => t.id == widget.task!.id, orElse: () => widget.task!, ); - + // Modifier la tâche existante en gardant les assignations actuelles final updatedTask = currentTask.copyWith( title: _titleController.text.trim(),