class AdminProduct { final int id; final String name; final String? canonicalName; final String? normalizedName; final int? categoryId; final String? categoryPath; const AdminProduct({ required this.id, required this.name, this.canonicalName, this.normalizedName, this.categoryId, this.categoryPath, }); String get displayName => canonicalName != null && canonicalName!.trim().isNotEmpty ? canonicalName! : name; factory AdminProduct.fromJson(Map json) { final categoryRef = json['categoryRef']; final names = []; dynamic current = categoryRef; while (current is Map) { final name = current['name']?.toString().trim(); if (name != null && name.isNotEmpty) { names.insert(0, name); } current = current['parent']; } return AdminProduct( id: (json['id'] as num).toInt(), name: (json['name'] ?? '').toString(), canonicalName: json['canonicalName']?.toString(), normalizedName: json['normalizedName']?.toString(), categoryId: (json['categoryId'] as num?)?.toInt(), categoryPath: names.isEmpty ? null : names.join(' > '), ); } }