From 809e3ca7d7b4f9727194dd1d42a2f15f8de0dbc7 Mon Sep 17 00:00:00 2001 From: "Christopher C. Wells" Date: Sat, 17 Apr 2021 20:31:52 -0700 Subject: [PATCH] Add support for recording recipe volume (WIP) This offers no practical value yet -- ultimately it will be used to support volume-based servings for recipes with a total volume set. --- app/Http/Controllers/RecipeController.php | 1 + app/Http/Requests/UpdateRecipeRequest.php | 3 +- app/JsonApi/Schemas/RecipeSchema.php | 2 ++ app/Models/Recipe.php | 15 +++++++++ database/Factories/RecipeFactory.php | 4 ++- ...2020_12_21_215932_create_recipes_table.php | 1 + ...021_04_17_200123_add_volume_to_recipes.php | 32 +++++++++++++++++++ resources/views/recipes/edit.blade.php | 16 ++++++++-- 8 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 database/migrations/2021_04_17_200123_add_volume_to_recipes.php diff --git a/app/Http/Controllers/RecipeController.php b/app/Http/Controllers/RecipeController.php index a7108da..a0dde29 100644 --- a/app/Http/Controllers/RecipeController.php +++ b/app/Http/Controllers/RecipeController.php @@ -201,6 +201,7 @@ class RecipeController extends Controller 'description_delta' => $input['description_delta'], 'servings' => (int) $input['servings'], 'weight' => $input['weight'], + 'volume' => Number::floatFromString($input['volume']), 'time_prep' => (int) $input['time_prep'], 'time_cook' => (int) $input['time_cook'], 'source' => $input['source'], diff --git a/app/Http/Requests/UpdateRecipeRequest.php b/app/Http/Requests/UpdateRecipeRequest.php index dc1e0dd..49f3357 100644 --- a/app/Http/Requests/UpdateRecipeRequest.php +++ b/app/Http/Requests/UpdateRecipeRequest.php @@ -24,7 +24,8 @@ class UpdateRecipeRequest extends FormRequest 'servings' => ['required', 'numeric'], 'time_prep' => ['nullable', 'numeric'], 'time_cook' => ['nullable', 'numeric'], - 'weight' => ['nullable', 'numeric'], + 'weight' => ['nullable', 'numeric', 'min:0'], + 'volume' => ['nullable', new StringIsPositiveDecimalOrFraction], 'source' => ['nullable', 'string'], 'ingredients.amount' => ['required', 'array', new ArrayNotEmpty], 'ingredients.amount.*' => ['required_with:ingredients.id.*', 'nullable', new StringIsPositiveDecimalOrFraction], diff --git a/app/JsonApi/Schemas/RecipeSchema.php b/app/JsonApi/Schemas/RecipeSchema.php index b45b80e..a57b27d 100644 --- a/app/JsonApi/Schemas/RecipeSchema.php +++ b/app/JsonApi/Schemas/RecipeSchema.php @@ -36,6 +36,8 @@ class RecipeSchema extends SchemaProvider 'servings' => $resource->servings, 'weight' => $resource->weight, 'serving_weight' => $resource->serving_weight, + 'volume' => $resource->volume, + 'volumeFormatted' => $resource->volume_formatted, 'units_supported' => $resource->units_supported->pluck('label'), 'caloriesPerServing' => $resource->caloriesPerServing(), 'carbohydratesPerServing' => $resource->carbohydratesPerServing(), diff --git a/app/Models/Recipe.php b/app/Models/Recipe.php index 309d2b5..e31e271 100644 --- a/app/Models/Recipe.php +++ b/app/Models/Recipe.php @@ -7,6 +7,7 @@ use App\Models\Traits\Ingredient; use App\Models\Traits\Journalable; use App\Models\Traits\Sluggable; use App\Models\Traits\Taggable; +use App\Support\Number; use App\Support\Nutrients; use ElasticScoutDriverPlus\QueryDsl; use Illuminate\Database\Eloquent\Factories\HasFactory; @@ -104,6 +105,7 @@ final class Recipe extends Model implements HasMedia 'source', 'servings', 'weight', + 'volume', ]; /** @@ -114,6 +116,7 @@ final class Recipe extends Model implements HasMedia 'time_prep' => 'int', 'time_cook' => 'int', 'weight' => 'float', + 'volume' => 'float', ]; /** @@ -133,6 +136,7 @@ final class Recipe extends Model implements HasMedia */ protected $appends = [ 'serving_weight', + 'volume_formatted', 'time_total', 'units_supported' ]; @@ -169,6 +173,17 @@ final class Recipe extends Model implements HasMedia return round($this->weight / $this->servings); } + /** + * Get the volume as a formatted string (e.g. 0.5 = 1/2). + */ + public function getVolumeFormattedAttribute(): ?string { + $result = null; + if (!empty($this->volume)) { + $result = Number::rationalStringFromFloat($this->volume); + } + return $result; + } + /** * Get the ingredients list (ingredient amounts and separators). */ diff --git a/database/Factories/RecipeFactory.php b/database/Factories/RecipeFactory.php index 95dea44..bcef573 100644 --- a/database/Factories/RecipeFactory.php +++ b/database/Factories/RecipeFactory.php @@ -23,6 +23,7 @@ class RecipeFactory extends Factory public function definition(): array { $description = htmlspecialchars($this->faker->realText(500)); + $volumes = [1/4, 1/3, 1/2, 2/3, 3/4, 1, 1 + 1/2, 1 + 3/4, 2, 2 + 1/2, 3, 3 + 1/2, 4, 5]; return [ 'name' => Words::randomWords(Arr::random(['npan', 'npn', 'anpn'])), 'description' => "

{$description}

", @@ -31,7 +32,8 @@ class RecipeFactory extends Factory 'time_cook' => $this->faker->numberBetween(0, 90), 'source' => $this->faker->optional()->url, 'servings' => $this->faker->numberBetween(1, 10), - 'weight' => $this->faker->randomFloat(1, 60, 2000), + 'weight' => $this->faker->optional()->randomFloat(1, 60, 2000), + 'volume' => $this->faker->optional()->randomElement($volumes), 'tags' => Words::randomWords(Arr::random(['a', 'aa', 'aaa']), TRUE), ]; } diff --git a/database/migrations/2020_12_21_215932_create_recipes_table.php b/database/migrations/2020_12_21_215932_create_recipes_table.php index 7e7884f..43b827c 100644 --- a/database/migrations/2020_12_21_215932_create_recipes_table.php +++ b/database/migrations/2020_12_21_215932_create_recipes_table.php @@ -24,6 +24,7 @@ class CreateRecipesTable extends Migration $table->string('source')->nullable(); $table->unsignedInteger('servings'); $table->unsignedFloat('weight')->nullable(); + //$table->decimal('volume', 10, 8)->unsigned()->nullable(); $table->timestamps(); }); } diff --git a/database/migrations/2021_04_17_200123_add_volume_to_recipes.php b/database/migrations/2021_04_17_200123_add_volume_to_recipes.php new file mode 100644 index 0000000..8bbeb32 --- /dev/null +++ b/database/migrations/2021_04_17_200123_add_volume_to_recipes.php @@ -0,0 +1,32 @@ +decimal('volume', 10, 8)->unsigned()->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('recipes', function (Blueprint $table) { + $table->dropColumn('volume'); + }); + } +} diff --git a/resources/views/recipes/edit.blade.php b/resources/views/recipes/edit.blade.php index b078b0e..ed45adc 100644 --- a/resources/views/recipes/edit.blade.php +++ b/resources/views/recipes/edit.blade.php @@ -33,7 +33,7 @@
- +
+ +
+ + + +
+
- +
- +