fix(chat): Correction race condition + Implémentation TODOs
## Corrections Critiques ### Race Condition - Statuts de Messages - Fix : Les icônes de statut (✓, ✓✓, ✓✓ bleu) ne s'affichaient pas - Cause : WebSocket delivery confirmations arrivaient avant messages locaux - Solution : Pattern Optimistic UI dans chat_bloc.dart - Création message temporaire immédiate - Ajout à la liste AVANT requête HTTP - Remplacement par message serveur à la réponse - Fichier : lib/presentation/state_management/chat_bloc.dart ## Implémentation TODOs (13/21) ### Social (social_header_widget.dart) - ✅ Copier lien du post dans presse-papiers - ✅ Partage natif via Share.share() - ✅ Dialogue de signalement avec 5 raisons ### Partage (share_post_dialog.dart) - ✅ Interface sélection d'amis avec checkboxes - ✅ Partage externe via Share API ### Média (media_upload_service.dart) - ✅ Parsing JSON réponse backend - ✅ Méthode deleteMedia() pour suppression - ✅ Génération miniature vidéo ### Posts (create_post_dialog.dart, edit_post_dialog.dart) - ✅ Extraction URL depuis uploads - ✅ Documentation chargement médias ### Chat (conversations_screen.dart) - ✅ Navigation vers notifications - ✅ ConversationSearchDelegate pour recherche ## Nouveaux Fichiers ### Configuration - build-prod.ps1 : Script build production avec dart-define - lib/core/constants/env_config.dart : Gestion environnements ### Documentation - TODOS_IMPLEMENTED.md : Documentation complète TODOs ## Améliorations ### Architecture - Refactoring injection de dépendances - Amélioration routing et navigation - Optimisation providers (UserProvider, FriendsProvider) ### UI/UX - Amélioration thème et couleurs - Optimisation animations - Meilleure gestion erreurs ### Services - Configuration API avec env_config - Amélioration datasources (events, users) - Optimisation modèles de données
This commit is contained in:
192
lib/data/models/reservation_model.dart
Normal file
192
lib/data/models/reservation_model.dart
Normal file
@@ -0,0 +1,192 @@
|
||||
import '../../domain/entities/reservation.dart';
|
||||
|
||||
/// Modèle de données pour les réservations (Data Transfer Object).
|
||||
///
|
||||
/// Cette classe est responsable de la sérialisation/désérialisation
|
||||
/// avec l'API backend et convertit vers/depuis l'entité de domaine Reservation.
|
||||
class ReservationModel {
|
||||
ReservationModel({
|
||||
required this.id,
|
||||
required this.userId,
|
||||
required this.userFullName,
|
||||
required this.eventId,
|
||||
required this.eventTitle,
|
||||
required this.reservationDate,
|
||||
required this.numberOfPeople,
|
||||
required this.status,
|
||||
this.establishmentId,
|
||||
this.establishmentName,
|
||||
this.notes,
|
||||
this.createdAt,
|
||||
});
|
||||
|
||||
/// Factory pour créer un [ReservationModel] à partir d'un JSON.
|
||||
factory ReservationModel.fromJson(Map<String, dynamic> json) {
|
||||
return ReservationModel(
|
||||
id: _parseId(json, 'id', ''),
|
||||
userId: _parseId(json, 'userId', ''),
|
||||
userFullName: _parseString(json, 'userFullName', ''),
|
||||
eventId: _parseId(json, 'eventId', ''),
|
||||
eventTitle: _parseString(json, 'eventTitle', ''),
|
||||
reservationDate: _parseTimestamp(json['reservationDate']),
|
||||
numberOfPeople: _parseInt(json, 'numberOfPeople'),
|
||||
status: _parseStatus(json['status'] as String?),
|
||||
establishmentId: json['establishmentId'] as String?,
|
||||
establishmentName: json['establishmentName'] as String?,
|
||||
notes: json['notes'] as String?,
|
||||
createdAt: json['createdAt'] != null
|
||||
? _parseTimestamp(json['createdAt'])
|
||||
: null,
|
||||
);
|
||||
}
|
||||
|
||||
/// Crée un [ReservationModel] depuis une entité de domaine [Reservation].
|
||||
factory ReservationModel.fromEntity(Reservation reservation) {
|
||||
return ReservationModel(
|
||||
id: reservation.id,
|
||||
userId: reservation.userId,
|
||||
userFullName: reservation.userFullName,
|
||||
eventId: reservation.eventId,
|
||||
eventTitle: reservation.eventTitle,
|
||||
reservationDate: reservation.reservationDate,
|
||||
numberOfPeople: reservation.numberOfPeople,
|
||||
status: reservation.status,
|
||||
establishmentId: reservation.establishmentId,
|
||||
establishmentName: reservation.establishmentName,
|
||||
notes: reservation.notes,
|
||||
createdAt: reservation.createdAt,
|
||||
);
|
||||
}
|
||||
|
||||
final String id;
|
||||
final String userId;
|
||||
final String userFullName;
|
||||
final String eventId;
|
||||
final String eventTitle;
|
||||
final DateTime reservationDate;
|
||||
final int numberOfPeople;
|
||||
final ReservationStatus status;
|
||||
final String? establishmentId;
|
||||
final String? establishmentName;
|
||||
final String? notes;
|
||||
final DateTime? createdAt;
|
||||
|
||||
/// Convertit ce modèle en JSON pour l'envoi vers l'API.
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'userId': userId,
|
||||
'userFullName': userFullName,
|
||||
'eventId': eventId,
|
||||
'eventTitle': eventTitle,
|
||||
'reservationDate': reservationDate.toIso8601String(),
|
||||
'numberOfPeople': numberOfPeople,
|
||||
'status': _statusToString(status),
|
||||
if (establishmentId != null) 'establishmentId': establishmentId,
|
||||
if (establishmentName != null) 'establishmentName': establishmentName,
|
||||
if (notes != null) 'notes': notes,
|
||||
if (createdAt != null) 'createdAt': createdAt!.toIso8601String(),
|
||||
};
|
||||
}
|
||||
|
||||
/// Convertit ce modèle vers une entité de domaine [Reservation].
|
||||
Reservation toEntity() {
|
||||
return Reservation(
|
||||
id: id,
|
||||
userId: userId,
|
||||
userFullName: userFullName,
|
||||
eventId: eventId,
|
||||
eventTitle: eventTitle,
|
||||
reservationDate: reservationDate,
|
||||
numberOfPeople: numberOfPeople,
|
||||
status: status,
|
||||
establishmentId: establishmentId,
|
||||
establishmentName: establishmentName,
|
||||
notes: notes,
|
||||
createdAt: createdAt,
|
||||
);
|
||||
}
|
||||
|
||||
/// Parse une valeur string depuis le JSON avec valeur par défaut.
|
||||
static String _parseString(
|
||||
Map<String, dynamic> json,
|
||||
String key,
|
||||
String defaultValue,
|
||||
) {
|
||||
return json[key] as String? ?? defaultValue;
|
||||
}
|
||||
|
||||
/// Parse une valeur int depuis le JSON avec valeur par défaut 1.
|
||||
static int _parseInt(Map<String, dynamic> json, String key) {
|
||||
return json[key] as int? ?? 1;
|
||||
}
|
||||
|
||||
/// Parse un timestamp depuis le JSON.
|
||||
static DateTime _parseTimestamp(dynamic timestamp) {
|
||||
if (timestamp == null) return DateTime.now();
|
||||
|
||||
if (timestamp is String) {
|
||||
try {
|
||||
return DateTime.parse(timestamp);
|
||||
} catch (e) {
|
||||
return DateTime.now();
|
||||
}
|
||||
}
|
||||
|
||||
if (timestamp is int) {
|
||||
return DateTime.fromMillisecondsSinceEpoch(timestamp);
|
||||
}
|
||||
|
||||
return DateTime.now();
|
||||
}
|
||||
|
||||
/// Parse un ID (UUID) depuis le JSON.
|
||||
static String _parseId(
|
||||
Map<String, dynamic> json,
|
||||
String key,
|
||||
String defaultValue,
|
||||
) {
|
||||
final value = json[key];
|
||||
if (value == null) return defaultValue;
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
/// Parse le statut de réservation depuis le JSON.
|
||||
static ReservationStatus _parseStatus(String? status) {
|
||||
if (status == null) return ReservationStatus.pending;
|
||||
|
||||
switch (status.toLowerCase()) {
|
||||
case 'pending':
|
||||
case 'en attente':
|
||||
return ReservationStatus.pending;
|
||||
case 'confirmed':
|
||||
case 'confirmé':
|
||||
case 'confirmée':
|
||||
return ReservationStatus.confirmed;
|
||||
case 'cancelled':
|
||||
case 'annulé':
|
||||
case 'annulée':
|
||||
return ReservationStatus.cancelled;
|
||||
case 'completed':
|
||||
case 'terminé':
|
||||
case 'terminée':
|
||||
return ReservationStatus.completed;
|
||||
default:
|
||||
return ReservationStatus.pending;
|
||||
}
|
||||
}
|
||||
|
||||
/// Convertit le statut en string pour l'API.
|
||||
static String _statusToString(ReservationStatus status) {
|
||||
switch (status) {
|
||||
case ReservationStatus.pending:
|
||||
return 'pending';
|
||||
case ReservationStatus.confirmed:
|
||||
return 'confirmed';
|
||||
case ReservationStatus.cancelled:
|
||||
return 'cancelled';
|
||||
case ReservationStatus.completed:
|
||||
return 'completed';
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user