class PantryItem { final int id; final int productId; final String productName; final String? canonicalName; final String? category; final int? categoryId; final String? categoryPath; final String? location; const PantryItem({ required this.id, required this.productId, required this.productName, this.canonicalName, this.category, this.categoryId, this.categoryPath, this.location, }); String get displayName { if (canonicalName != null && canonicalName!.trim().isNotEmpty) { return canonicalName!; } return productName; } String? get l1CategoryOrNull { final path = categoryPath?.trim(); if (path != null && path.isNotEmpty) { return path.split('>').first.trim(); } if (category != null && category!.trim().isNotEmpty) { return category!.trim(); } return null; } factory PantryItem.fromJson(Map json) { final product = json['product'] as Map? ?? {}; return PantryItem( id: (json['id'] as num).toInt(), productId: (json['productId'] as num).toInt(), productName: (product['name'] ?? '').toString(), canonicalName: product['canonicalName']?.toString(), category: product['category']?.toString(), categoryId: (product['categoryId'] as num?)?.toInt(), categoryPath: _buildCategoryPath(product['categoryRef']), location: json['location']?.toString(), ); } 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.add(name); } current = current['parent']; } if (names.isEmpty) return null; return names.reversed.join(' > '); } }