class InventoryItem { final int id; final int productId; final String productName; final String? productCanonicalName; final String? categoryPath; final double quantity; final String unit; final String? location; final String? brand; final String? purchaseDate; final String? bestBeforeDate; final bool opened; final String? comment; const InventoryItem({ required this.id, required this.productId, required this.productName, this.productCanonicalName, this.categoryPath, required this.quantity, required this.unit, this.location, this.brand, this.purchaseDate, this.bestBeforeDate, required this.opened, this.comment, }); String get displayName { if (productCanonicalName != null && productCanonicalName!.trim().isNotEmpty) { return productCanonicalName!; } return productName; } String get l1Category { final path = categoryPath?.trim(); if (path == null || path.isEmpty) return 'Ovrigt'; return path.split('>').first.trim(); } factory InventoryItem.fromJson(Map json) { final product = (json['product'] as Map?) ?? const {}; return InventoryItem( id: json['id'] as int, productId: json['productId'] as int, productName: product['name'] as String? ?? '', productCanonicalName: product['canonicalName'] as String?, categoryPath: _buildCategoryPath(product['categoryRef']), quantity: double.tryParse(json['quantity']?.toString() ?? '0') ?? 0, unit: json['unit'] as String? ?? '', location: json['location'] as String?, brand: json['brand'] as String?, purchaseDate: json['purchaseDate'] as String?, bestBeforeDate: json['bestBeforeDate'] as String?, opened: json['opened'] as bool? ?? false, comment: json['comment'] as String?, ); } 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(' > '); } }