// Models/product.dart - Version corrigée pour gérer les Blobs import 'dart:typed_data'; import 'dart:convert'; class Product { final int? id; final String name; final double price; final String? image; final String category; final int stock; final String? description; String? qrCode; final String? reference; final int? pointDeVenteId; final String? marque; final String? ram; final String? memoireInterne; final String? imei; Product({ this.id, required this.name, required this.price, this.image, required this.category, this.stock = 0, this.description, this.qrCode, this.reference, this.pointDeVenteId, this.marque, this.ram, this.memoireInterne, this.imei, }); bool isStockDefined() { return stock > 0; } // Méthode helper pour convertir de façon sécurisée static String? _convertImageFromMap(dynamic imageValue) { if (imageValue == null) { return null; } // Si c'est déjà une String, on la retourne if (imageValue is String) { return imageValue; } // Le driver mysql1 peut retourner un Blob même pour TEXT // Essayer de le convertir en String try { if (imageValue is Uint8List) { // Convertir les bytes en String UTF-8 return utf8.decode(imageValue); } if (imageValue is List) { // Convertir les bytes en String UTF-8 return utf8.decode(imageValue); } // Dernier recours : toString() return imageValue.toString(); } catch (e) { print("Erreur conversion image: $e, type: ${imageValue.runtimeType}"); return null; } } factory Product.fromMap(Map map) => Product( id: map['id'] as int?, name: map['name'] as String, price: (map['price'] as num).toDouble(), // Conversion sécurisée image: _convertImageFromMap(map['image']), // Utilisation de la méthode helper category: map['category'] as String, stock: (map['stock'] as int?) ?? 0, // Valeur par défaut description: map['description'] as String?, qrCode: map['qrCode'] as String?, reference: map['reference'] as String?, pointDeVenteId: map['point_de_vente_id'] as int?, marque: map['marque'] as String?, ram: map['ram'] as String?, memoireInterne: map['memoire_interne'] as String?, imei: map['imei'] as String?, ); Map toMap() => { 'id': id, 'name': name, 'price': price, 'image': image, 'category': category, 'stock': stock, 'description': description, 'qrCode': qrCode, 'reference': reference, 'point_de_vente_id': pointDeVenteId, 'marque': marque, 'ram': ram, 'memoire_interne': memoireInterne, 'imei': imei, }; // Méthode pour obtenir l'image comme base64 si nécessaire String? getImageAsBase64() { if (image == null) return null; // Si l'image est déjà en base64, la retourner if (image!.startsWith('data:') || image!.length > 100) { return image; } // Sinon, c'est probablement un chemin de fichier return image; } // Méthode pour vérifier si l'image est un base64 bool get isImageBase64 { if (image == null) return false; return image!.startsWith('data:') || (image!.length > 100 && !image!.contains('/') && !image!.contains('\\')); } // Copie avec modification Product copyWith({ int? id, String? name, double? price, String? image, String? category, int? stock, String? description, String? qrCode, String? reference, int? pointDeVenteId, String? marque, String? ram, String? memoireInterne, String? imei, }) { return Product( id: id ?? this.id, name: name ?? this.name, price: price ?? this.price, image: image ?? this.image, category: category ?? this.category, stock: stock ?? this.stock, description: description ?? this.description, qrCode: qrCode ?? this.qrCode, reference: reference ?? this.reference, pointDeVenteId: pointDeVenteId ?? this.pointDeVenteId, marque: marque ?? this.marque, ram: ram ?? this.ram, memoireInterne: memoireInterne ?? this.memoireInterne, imei: imei ?? this.imei, ); } }