class PendingProduct { final int id; final String name; final String? canonicalName; final DateTime? createdAt; final int? ownerId; final int? categoryId; final String? categoryPath; final String? ownerUsername; const PendingProduct({ required this.id, required this.name, this.canonicalName, this.createdAt, this.ownerId, this.categoryId, this.categoryPath, this.ownerUsername, }); String get displayName => canonicalName != null && canonicalName!.trim().isNotEmpty ? canonicalName! : name; factory PendingProduct.fromJson(Map json) { final categoryRef = json['categoryRef']; final owner = json['owner']; final parts = []; if (categoryRef is Map) { final parent = categoryRef['parent']; if (parent is Map) { final parentName = parent['name']?.toString(); if (parentName != null && parentName.trim().isNotEmpty) { parts.add(parentName.trim()); } } final name = categoryRef['name']?.toString(); if (name != null && name.trim().isNotEmpty) { parts.add(name.trim()); } } return PendingProduct( id: (json['id'] as num).toInt(), name: (json['name'] ?? '').toString(), canonicalName: json['canonicalName']?.toString(), createdAt: json['createdAt'] == null ? null : DateTime.tryParse(json['createdAt'].toString()), ownerId: (owner is Map) ? (owner['id'] as num?)?.toInt() : null, categoryId: (json['categoryId'] as num?)?.toInt(), categoryPath: parts.isEmpty ? null : parts.join(' > '), ownerUsername: owner is Map ? owner['username']?.toString() : null, ); } }