class AdminProduct { final int id; final String name; final String? canonicalName; final String? normalizedName; final int? ownerId; final bool? isPrivate; final int? categoryId; final String? categoryPath; final bool? isActive; final String? status; final DateTime? deletedAt; const AdminProduct({ required this.id, required this.name, this.canonicalName, this.normalizedName, this.ownerId, this.isPrivate, this.categoryId, this.categoryPath, this.isActive, this.status, this.deletedAt, }); 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(), ownerId: ((json['owner'] as Map?)?['id'] as num?)?.toInt(), isPrivate: json['isPrivate'] as bool?, categoryId: (json['categoryId'] as num?)?.toInt(), categoryPath: names.isEmpty ? null : names.join(' > '), isActive: json['isActive'] as bool?, status: json['status']?.toString(), deletedAt: json['deletedAt'] == null ? null : DateTime.tryParse(json['deletedAt'].toString()), ); } }