Refactoring

This commit is contained in:
DahoudG
2024-09-02 21:16:31 +00:00
parent ef72a81b64
commit 04f240b521
5 changed files with 145 additions and 42 deletions

View File

@@ -1,5 +1,5 @@
class Urls { class Urls {
static const String baseUrl = 'http://192.168.1.14:8085'; static const String baseUrl = 'http://192.168.0.145:8085';
// static const String login = baseUrl + 'auth/login'; // static const String login = baseUrl + 'auth/login';
static const String eventsUrl = '$baseUrl/events'; static const String eventsUrl = '$baseUrl/events';
// Ajoute d'autres URLs ici // Ajoute d'autres URLs ici

View File

@@ -168,4 +168,29 @@ class EventRemoteDataSource {
throw ServerExceptionWithMessage('Une erreur est survenue lors de la fermeture de l\'événement.'); throw ServerExceptionWithMessage('Une erreur est survenue lors de la fermeture de l\'événement.');
} }
} }
/// Rouvrir un événement.
Future<void> reopenEvent(String eventId) async {
print('Réouverture de l\'événement avec l\'ID: $eventId');
final response = await client.post(
Uri.parse('${Urls.eventsUrl}/$eventId/reopen'),
headers: {'Content-Type': 'application/json'},
);
print('Statut de la réponse: ${response.statusCode}');
if (response.statusCode == 200) {
print('Événement rouvert avec succès');
} else if (response.statusCode == 400) {
// Si le serveur retourne une erreur 400, vérifiez le corps du message
final responseBody = json.decode(response.body);
final errorMessage = responseBody['message'] ?? 'Erreur inconnue';
print('Erreur lors de la réouverture de l\'événement: $errorMessage');
throw ServerExceptionWithMessage(errorMessage);
} else {
print('Erreur lors de la réouverture de l\'événement: ${response.body}');
throw ServerExceptionWithMessage('Une erreur est survenue lors de la réouverture de l\'événement.');
}
}
} }

View File

@@ -1,18 +1,21 @@
import 'package:afterwork/data/models/user_model.dart'; import 'package:afterwork/data/models/user_model.dart';
/// Modèle de données représentant un événement. /// Modèle de données représentant un événement.
/// Cette classe encapsule toutes les propriétés d'un événement, y compris
/// le titre, la description, la date, la localisation, la catégorie, les liens,
/// l'image, le créateur, les participants et le statut de l'événement.
class EventModel { class EventModel {
final String id; final String id; // Identifiant unique de l'événement
final String title; final String title; // Titre de l'événement
final String description; final String description; // Description de l'événement
final String date; final String date; // Date de l'événement
final String location; final String location; // Localisation de l'événement
final String category; final String category; // Catégorie de l'événement
final String link; final String link; // Lien associé à l'événement
final String? imageUrl; final String? imageUrl; // URL de l'image de l'événement (optionnel)
final UserModel creator; final UserModel creator; // Créateur de l'événement
final List<UserModel> participants; final List<UserModel> participants; // Liste des participants à l'événement
final String status; final String status; // Statut de l'événement (e.g., "OPEN", "CLOSED")
/// Constructeur pour initialiser toutes les propriétés de l'événement. /// Constructeur pour initialiser toutes les propriétés de l'événement.
EventModel({ EventModel({
@@ -31,6 +34,9 @@ class EventModel {
/// Convertit un objet JSON en `EventModel`. /// Convertit un objet JSON en `EventModel`.
factory EventModel.fromJson(Map<String, dynamic> json) { factory EventModel.fromJson(Map<String, dynamic> json) {
// Log de la conversion depuis JSON
print('Conversion de l\'objet JSON en EventModel: ${json['id']}');
return EventModel( return EventModel(
id: json['id'], id: json['id'],
title: json['title'], title: json['title'],
@@ -52,6 +58,9 @@ class EventModel {
/// Convertit un `EventModel` en objet JSON. /// Convertit un `EventModel` en objet JSON.
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
// Log de la conversion en JSON
print('Conversion de l\'EventModel en objet JSON: $id');
return { return {
'id': id, 'id': id,
'title': title, 'title': title,
@@ -63,6 +72,7 @@ class EventModel {
'imageUrl': imageUrl, 'imageUrl': imageUrl,
'creator': creator.toJson(), 'creator': creator.toJson(),
'participants': participants.map((user) => user.toJson()).toList(), 'participants': participants.map((user) => user.toJson()).toList(),
'status': status,
}; };
} }
} }

View File

@@ -4,7 +4,7 @@ import 'package:afterwork/data/datasources/event_remote_data_source.dart';
/// Widget pour afficher une carte d'événement. /// Widget pour afficher une carte d'événement.
/// Cette classe est utilisée pour afficher les détails d'un événement, /// Cette classe est utilisée pour afficher les détails d'un événement,
/// incluant son titre, sa description, son image, et des actions possibles /// incluant son titre, sa description, son image, et des actions possibles
/// telles que réagir, commenter, partager, participer, et fermer l'événement. /// telles que réagir, commenter, partager, participer, et fermer ou rouvrir l'événement.
class EventCard extends StatelessWidget { class EventCard extends StatelessWidget {
// Identifiant unique de l'événement // Identifiant unique de l'événement
final String eventId; final String eventId;
@@ -50,6 +50,8 @@ class EventCard extends StatelessWidget {
final VoidCallback onMoreOptions; final VoidCallback onMoreOptions;
// Callback pour fermer l'événement // Callback pour fermer l'événement
final VoidCallback onCloseEvent; final VoidCallback onCloseEvent;
// Callback pour rouvrir l'événement
final VoidCallback onReopenEvent;
const EventCard({ const EventCard({
Key? key, Key? key,
@@ -75,6 +77,7 @@ class EventCard extends StatelessWidget {
required this.onParticipate, required this.onParticipate,
required this.onMoreOptions, required this.onMoreOptions,
required this.onCloseEvent, required this.onCloseEvent,
required this.onReopenEvent,
}) : super(key: key); }) : super(key: key);
@override @override
@@ -87,11 +90,19 @@ class EventCard extends StatelessWidget {
duration: const Duration(milliseconds: 300), duration: const Duration(milliseconds: 300),
child: Dismissible( child: Dismissible(
key: ValueKey(eventId), key: ValueKey(eventId),
direction: DismissDirection.startToEnd, direction: eventStatus == 'CLOSED'
? DismissDirection.endToStart // Permet de rouvrir avec un swipe à gauche
: DismissDirection.startToEnd, // Permet de fermer avec un swipe à droite
onDismissed: (direction) { onDismissed: (direction) {
if (direction == DismissDirection.startToEnd) {
// Log du déclenchement de la fermeture de l'événement // Log du déclenchement de la fermeture de l'événement
print('Tentative de fermeture de l\'événement $eventId'); print('Tentative de fermeture de l\'événement $eventId');
onCloseEvent(); onCloseEvent();
} else if (direction == DismissDirection.endToStart && eventStatus == 'CLOSED') {
// Log du déclenchement de la réouverture de l'événement
print('Tentative de réouverture de l\'événement $eventId');
onReopenEvent();
}
}, },
background: Container( background: Container(
color: Colors.red, color: Colors.red,
@@ -99,6 +110,12 @@ class EventCard extends StatelessWidget {
padding: const EdgeInsets.only(left: 20.0), padding: const EdgeInsets.only(left: 20.0),
child: const Icon(Icons.delete, color: Colors.white), child: const Icon(Icons.delete, color: Colors.white),
), ),
secondaryBackground: Container(
color: Colors.green,
alignment: Alignment.centerRight,
padding: const EdgeInsets.only(right: 20.0),
child: const Icon(Icons.replay, color: Colors.white),
),
child: Stack( child: Stack(
children: [ children: [
Card( Card(
@@ -114,7 +131,7 @@ class EventCard extends StatelessWidget {
children: [ children: [
_buildHeader(context), _buildHeader(context),
const SizedBox(height: 10), const SizedBox(height: 10),
_buildEventCategory(), // Affichage de la catégorie de l'événement _buildEventCategory(),
const SizedBox(height: 5), const SizedBox(height: 5),
_buildEventDetails(), _buildEventDetails(),
const SizedBox(height: 10), const SizedBox(height: 10),
@@ -271,11 +288,11 @@ class EventCard extends StatelessWidget {
print('Affichage des interactions pour l\'événement $eventId'); print('Affichage des interactions pour l\'événement $eventId');
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 0.0), // Réduire le padding vertical padding: const EdgeInsets.symmetric(vertical: 4.0), // Réduire le padding vertical
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround, // Utiliser spaceAround pour réduire l'espace mainAxisAlignment: MainAxisAlignment.spaceAround, // Utiliser spaceAround pour réduire l'espace
children: [ children: [
Flexible( Expanded(
child: _buildIconButton( child: _buildIconButton(
icon: Icons.thumb_up_alt_outlined, icon: Icons.thumb_up_alt_outlined,
label: 'Réagir', label: 'Réagir',
@@ -287,7 +304,7 @@ class EventCard extends StatelessWidget {
}, },
), ),
), ),
Flexible( Expanded(
child: _buildIconButton( child: _buildIconButton(
icon: Icons.comment_outlined, icon: Icons.comment_outlined,
label: 'Commenter', label: 'Commenter',
@@ -299,7 +316,7 @@ class EventCard extends StatelessWidget {
}, },
), ),
), ),
Flexible( Expanded(
child: _buildIconButton( child: _buildIconButton(
icon: Icons.share_outlined, icon: Icons.share_outlined,
label: 'Partager', label: 'Partager',
@@ -327,8 +344,7 @@ class EventCard extends StatelessWidget {
// Log de la construction du bouton d'interaction // Log de la construction du bouton d'interaction
print('Construction du bouton $label pour l\'événement $eventId'); print('Construction du bouton $label pour l\'événement $eventId');
return Expanded( return TextButton.icon(
child: TextButton.icon(
onPressed: onPressed, onPressed: onPressed,
icon: Icon(icon, color: const Color(0xFF1DBF73), size: 20), icon: Icon(icon, color: const Color(0xFF1DBF73), size: 20),
label: Text( label: Text(
@@ -336,19 +352,25 @@ class EventCard extends StatelessWidget {
style: const TextStyle(color: Colors.white70, fontSize: 12), style: const TextStyle(color: Colors.white70, fontSize: 12),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
),
); );
} }
/// Bouton pour participer à l'événement. /// Bouton pour participer à l'événement.
/// Cette méthode construit un bouton qui permet de participer à l'événement. /// Cette méthode construit un bouton qui permet de participer à l'événement.
/// Si l'événement est fermé, le bouton est désactivé. /// Si l'événement est fermé, le bouton est caché.
Widget _buildParticipateButton() { Widget _buildParticipateButton() {
// Log de la construction du bouton "Participer" // Log de la construction du bouton "Participer"
print('Construction du bouton "Participer" pour l\'événement $eventId avec statut $eventStatus'); print('Construction du bouton "Participer" pour l\'événement $eventId avec statut $eventStatus');
// Si l'événement est fermé, ne rien retourner (pas de bouton)
if (eventStatus == 'CLOSED') {
print('L\'événement $eventId est fermé, le bouton "Participer" est caché.');
return SizedBox.shrink(); // Retourne un widget vide pour ne pas occuper d'espace
}
// Sinon, retourner le bouton "Participer"
return ElevatedButton( return ElevatedButton(
onPressed: eventStatus == 'CLOSED' ? null : onParticipate, // Désactiver si l'événement est fermé onPressed: onParticipate,
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF1DBF73), backgroundColor: const Color(0xFF1DBF73),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
@@ -357,9 +379,9 @@ class EventCard extends StatelessWidget {
padding: const EdgeInsets.symmetric(vertical: 12.0), padding: const EdgeInsets.symmetric(vertical: 12.0),
minimumSize: const Size(double.infinity, 40), minimumSize: const Size(double.infinity, 40),
), ),
child: Text( child: const Text(
eventStatus == 'CLOSED' ? 'Événement fermé' : 'Participer', 'Participer',
style: const TextStyle(color: Colors.white), style: TextStyle(color: Colors.white),
), ),
); );
} }

View File

@@ -29,6 +29,7 @@ class _EventScreenState extends State<EventScreen> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
// Récupérer la liste des événements à partir de la source de données distante
_eventsFuture = widget.eventRemoteDataSource.getAllEvents(); _eventsFuture = widget.eventRemoteDataSource.getAllEvents();
} }
@@ -59,7 +60,6 @@ class _EventScreenState extends State<EventScreen> {
); );
if (eventData != null) { if (eventData != null) {
// Appeler l'API pour créer un nouvel événement.
try { try {
print('Tentative de création d\'un nouvel événement par l\'utilisateur ${widget.userId}'); print('Tentative de création d\'un nouvel événement par l\'utilisateur ${widget.userId}');
await widget.eventRemoteDataSource.createEvent(eventData as EventModel); await widget.eventRemoteDataSource.createEvent(eventData as EventModel);
@@ -104,7 +104,7 @@ class _EventScreenState extends State<EventScreen> {
print('Affichage de l\'événement ${event.id}'); print('Affichage de l\'événement ${event.id}');
return EventCard( return EventCard(
key: ValueKey(event.id), // Pour une gestion correcte du Key dans l'animation key: ValueKey(event.id),
eventRemoteDataSource: widget.eventRemoteDataSource, eventRemoteDataSource: widget.eventRemoteDataSource,
userId: widget.userId, userId: widget.userId,
eventId: event.id, eventId: event.id,
@@ -117,7 +117,7 @@ class _EventScreenState extends State<EventScreen> {
eventTitle: event.title, eventTitle: event.title,
eventDescription: event.description, eventDescription: event.description,
eventImageUrl: event.imageUrl ?? 'lib/assets/images/placeholder.png', eventImageUrl: event.imageUrl ?? 'lib/assets/images/placeholder.png',
eventStatus: event.status, // Ajouter le statut de l'événement ici eventStatus: event.status,
reactionsCount: 120, // Exemple de valeur reactionsCount: 120, // Exemple de valeur
commentsCount: 45, // Exemple de valeur commentsCount: 45, // Exemple de valeur
sharesCount: 30, // Exemple de valeur sharesCount: 30, // Exemple de valeur
@@ -137,6 +137,7 @@ class _EventScreenState extends State<EventScreen> {
onMoreOptions: () { onMoreOptions: () {
print('Affichage des options pour l\'événement ${event.id}'); print('Affichage des options pour l\'événement ${event.id}');
}, },
onReopenEvent: () => _onReopenEvent(context, event.id, index),
); );
}, },
); );
@@ -150,18 +151,21 @@ class _EventScreenState extends State<EventScreen> {
void _onCloseEvent(BuildContext context, String eventId, int index) async { void _onCloseEvent(BuildContext context, String eventId, int index) async {
try { try {
print('Tentative de fermeture de l\'événement $eventId'); print('Tentative de fermeture de l\'événement $eventId');
// Appeler l'API pour fermer l'événement
await widget.eventRemoteDataSource.closeEvent(eventId); await widget.eventRemoteDataSource.closeEvent(eventId);
print('Événement fermé avec succès'); print('Événement fermé avec succès');
// Montrer un message de succès // Montrer un message de succès AVANT de supprimer l'événement de la liste
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('L\'événement a été fermé avec succès.')), const SnackBar(content: Text('L\'événement a été fermé avec succès.')),
); );
// Actualiser la liste des événements après fermeture avec un effet de fondu // Supprimez l'événement de la liste après avoir affiché le SnackBar
setState(() { setState(() {
_eventsFuture.then((events) { _eventsFuture = _eventsFuture.then((events) {
events.removeAt(index); events.removeAt(index);
return events;
}); });
}); });
} catch (e) { } catch (e) {
@@ -171,4 +175,46 @@ class _EventScreenState extends State<EventScreen> {
); );
} }
} }
/// Logique pour rouvrir un événement
void _onReopenEvent(BuildContext context, String eventId, int index) async {
try {
print('Tentative de réouverture de l\'événement $eventId');
await widget.eventRemoteDataSource.reopenEvent(eventId);
print('Événement rouvert avec succès');
// Montrer un message de succès
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('L\'événement a été rouvert avec succès.')),
);
// Mettre à jour le statut de l'événement dans la liste des événements
setState(() {
_eventsFuture = _eventsFuture.then((events) {
final updatedEvent = EventModel(
id: events[index].id,
title: events[index].title,
description: events[index].description,
date: events[index].date,
location: events[index].location,
category: events[index].category,
link: events[index].link,
imageUrl: events[index].imageUrl,
creator: events[index].creator,
participants: events[index].participants,
status: 'OPEN', // Mettre à jour le statut à 'OPEN'
);
// Remplacer l'événement dans la liste
events[index] = updatedEvent;
return events;
});
});
} catch (e) {
print('Erreur lors de la réouverture de l\'événement: $e');
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Erreur lors de la réouverture de l\'événement : $e')),
);
}
}
} }