import 'macro_profile.dart'; import 'recipe_ingredient.dart'; /// Immutable recipe imported from the web (schema.org/JSON-LD or /// OpenGraph fallback) or saved manually. /// /// Pure Dart (no framework imports) so the entity can be shared by the /// scraper use case, the drift-backed repository, and the Riverpod /// presentation layer without leaking infrastructure concerns into the /// domain. class Recipe { const Recipe({ required this.id, required this.title, required this.sourceUrl, this.imageUrl, this.description, this.prepTimeMinutes = 0, this.cookTimeMinutes = 0, this.servings = 1, this.ingredients = const [], this.instructions = const [], required this.macrosPerServing, }); /// UUID primary key assigned when the recipe is first materialized. final String id; /// Human-readable recipe title (`name` / `og:title`). final String title; /// URL the recipe was imported from; also used to de-duplicate re-imports. final String sourceUrl; /// Representative image URL (`image` / `og:image`), if any. final String? imageUrl; /// Optional summary (`description` / `og:description`). final String? description; /// Preparation time in minutes (`prepTime`, ISO-8601 duration decoded); /// `0` when unknown. final int prepTimeMinutes; /// Cook time in minutes (`cookTime`); `0` when unknown. final int cookTimeMinutes; /// Yield parsed from `recipeYield` (defaults to 4 when unparsable). final int servings; /// Parsed ingredient lines (raw text preserved). final List ingredients; /// Instruction steps with `HowToStep` / `HowToSection` wrappers flattened. final List instructions; /// Nutrition facts per serving (`nutrition` block). final MacroProfile macrosPerServing; /// Total active time (prep + cook) in minutes. int get totalMinutes => prepTimeMinutes + cookTimeMinutes; Recipe copyWith({ String? id, String? title, String? sourceUrl, String? imageUrl, String? description, int? prepTimeMinutes, int? cookTimeMinutes, int? servings, List? ingredients, List? instructions, MacroProfile? macrosPerServing, }) => Recipe( id: id ?? this.id, title: title ?? this.title, sourceUrl: sourceUrl ?? this.sourceUrl, imageUrl: imageUrl ?? this.imageUrl, description: description ?? this.description, prepTimeMinutes: prepTimeMinutes ?? this.prepTimeMinutes, cookTimeMinutes: cookTimeMinutes ?? this.cookTimeMinutes, servings: servings ?? this.servings, ingredients: ingredients ?? this.ingredients, instructions: instructions ?? this.instructions, macrosPerServing: macrosPerServing ?? this.macrosPerServing, ); @override String toString() => 'Recipe($id, "$title", ' '${macrosPerServing.proteinGrams}g protein/serving)'; }