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