## 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
193 lines
5.7 KiB
Dart
193 lines
5.7 KiB
Dart
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';
|
|
}
|
|
}
|
|
}
|