diff --git a/app/Http/Controllers/FoodController.php b/app/Http/Controllers/FoodController.php index 4f93ea6..74a9f41 100644 --- a/app/Http/Controllers/FoodController.php +++ b/app/Http/Controllers/FoodController.php @@ -3,6 +3,8 @@ namespace App\Http\Controllers; use App\Models\Food; +use App\Rules\StringIsDecimalOrFraction; +use App\Support\Number; use App\Support\Nutrients; use Illuminate\Contracts\View\View; use Illuminate\Http\RedirectResponse; @@ -70,7 +72,7 @@ class FoodController extends Controller 'name' => 'required|string', 'detail' => 'nullable|string', 'brand' => 'nullable|string', - 'serving_size' => 'required|numeric', + 'serving_size' => ['required', new StringIsDecimalOrFraction], 'serving_unit' => 'nullable|string', 'serving_weight' => 'required|numeric', 'calories' => 'nullable|numeric', @@ -80,6 +82,7 @@ class FoodController extends Controller 'carbohydrates' => 'nullable|numeric', 'protein' => 'nullable|numeric', ]); + $attributes['serving_size'] = Number::floatFromString($attributes['serving_size']); $food->fill(array_filter($attributes))->save(); return redirect(route('foods.show', $food)) ->with('message', 'Changes saved!'); diff --git a/app/Http/Controllers/JournalEntryController.php b/app/Http/Controllers/JournalEntryController.php index 93dd2c5..3fd44cf 100644 --- a/app/Http/Controllers/JournalEntryController.php +++ b/app/Http/Controllers/JournalEntryController.php @@ -9,6 +9,8 @@ use App\Models\Food; use App\Models\JournalEntry; use App\Models\Recipe; use App\Rules\ArrayNotEmpty; +use App\Rules\StringIsDecimalOrFraction; +use App\Support\Number; use App\Support\Nutrients; use Illuminate\Contracts\View\View; use Illuminate\Http\RedirectResponse; @@ -82,7 +84,7 @@ class JournalEntryController extends Controller 'date' => 'required|date', 'meal' => 'required|string', 'amounts' => ['required', 'array', new ArrayNotEmpty], - 'amounts.*' => 'required_with:foods.*,recipes.*|nullable|numeric|min:0', + 'amounts.*' => ['required_with:foods.*,recipes.*', 'nullable', new StringIsDecimalOrFraction], 'units' => ['required', 'array', new ArrayNotEmpty], 'units.*' => 'nullable|string', 'foods' => 'required|array', @@ -119,7 +121,7 @@ class JournalEntryController extends Controller $food = $foods->get($id); $nutrient_multiplier = Nutrients::calculateFoodNutrientMultiplier( $food, - $input['amounts'][$key], + Number::floatFromString($input['amounts'][$key]), $input['units'][$key], ); foreach ($nutrients as $nutrient => $amount) { @@ -134,7 +136,7 @@ class JournalEntryController extends Controller foreach ($recipes_selected as $key => $id) { $recipe = $recipes->get($id); foreach ($nutrients as $nutrient => $amount) { - $nutrients[$nutrient] += $recipe->{"{$nutrient}PerServing"}() * $input['amounts'][$key]; + $nutrients[$nutrient] += $recipe->{"{$nutrient}PerServing"}() * Number::floatFromString($input['amounts'][$key]); } $summary[] = "{$input['amounts'][$key]} {$input['units'][$key]} {$recipe->name}"; } diff --git a/app/Http/Controllers/RecipeController.php b/app/Http/Controllers/RecipeController.php index db5c691..e56309c 100644 --- a/app/Http/Controllers/RecipeController.php +++ b/app/Http/Controllers/RecipeController.php @@ -7,6 +7,8 @@ use App\Models\FoodAmount; use App\Models\Recipe; use App\Models\RecipeStep; use App\Rules\ArrayNotEmpty; +use App\Rules\StringIsDecimalOrFraction; +use App\Support\Number; use Illuminate\Contracts\View\View; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; @@ -63,7 +65,7 @@ class RecipeController extends Controller 'description' => 'nullable|string', 'servings' => 'required|numeric', 'foods_amount' => ['required', 'array', new ArrayNotEmpty], - 'foods_amount.*' => 'required_with:foods.*|nullable|numeric|min:0', + 'foods_amount.*' => ['required_with:foods.*', 'nullable', new StringIsDecimalOrFraction], 'foods_unit' => ['required', 'array'], 'foods_unit.*' => 'nullable|string', 'foods' => ['required', 'array', new ArrayNotEmpty], @@ -88,7 +90,7 @@ class RecipeController extends Controller $weight = 0; foreach (array_filter($input['foods_amount']) as $key => $amount) { $food_amounts[$key] = new FoodAmount([ - 'amount' => (float) $amount, + 'amount' => Number::floatFromString($amount), 'unit' => $input['foods_unit'][$key], 'weight' => $weight++, ]); diff --git a/app/Rules/StringIsDecimalOrFraction.php b/app/Rules/StringIsDecimalOrFraction.php new file mode 100644 index 0000000..ba27a33 --- /dev/null +++ b/app/Rules/StringIsDecimalOrFraction.php @@ -0,0 +1,38 @@ +toFloat(); + } + return $result; + } + + /** + * Get a string faction representation of a float. + * + * @todo Handle repeating values like 1/3, 2/3, etc. + * + * @see https://rosettacode.org/wiki/Convert_decimal_number_to_rational#PHP + * + * @param float $value + * Value to convert to string fraction. + * @return string + * String fraction. + */ + public static function fractionStringFromFloat(float $value): string { + $fraction = (string) Fraction::fromFloat($value); + if ($fraction === '33333333/100000000') { + $fraction = '1/3'; + } + elseif ($fraction === '66666667/100000000') { + $fraction = '2/3'; + } + return $fraction; + } +} diff --git a/composer.json b/composer.json index 38f67e0..cbac5de 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,8 @@ "fruitcake/laravel-cors": "^2.0", "guzzlehttp/guzzle": "^7.0.1", "laravel/framework": "^8.12", - "laravel/tinker": "^2.5" + "laravel/tinker": "^2.5", + "phospr/fraction": "^1.2" }, "require-dev": { "barryvdh/laravel-ide-helper": "^2.9", diff --git a/composer.lock b/composer.lock index c84e615..a391417 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6798cd035bece9ee986d5e3a59036303", + "content-hash": "7054301f9158e201ddff5b37f41a1c5a", "packages": [ { "name": "asm89/stack-cors", @@ -1829,6 +1829,49 @@ }, "time": "2020-11-07T02:01:34+00:00" }, + { + "name": "phospr/fraction", + "version": "v1.2.1", + "source": { + "type": "git", + "url": "https://github.com/phospr/fraction.git", + "reference": "3f195b920bca0ba4eac8575e397af283782c699d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phospr/fraction/zipball/3f195b920bca0ba4eac8575e397af283782c699d", + "reference": "3f195b920bca0ba4eac8575e397af283782c699d", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "4.0.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "Phospr\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tom Haskins-Vaughan", + "email": "tom@tomhv.uk" + } + ], + "description": "A composer-installable fractions library", + "support": { + "issues": "https://github.com/phospr/fraction/issues", + "source": "https://github.com/phospr/fraction/tree/master" + }, + "time": "2016-12-21T15:33:12+00:00" + }, { "name": "phpoption/phpoption", "version": "1.7.5", diff --git a/resources/views/foods/edit.blade.php b/resources/views/foods/edit.blade.php index c395047..c98a3a1 100644 --- a/resources/views/foods/edit.blade.php +++ b/resources/views/foods/edit.blade.php @@ -72,11 +72,10 @@ + :value="old('serving_size', \App\Support\Number::fractionStringFromFloat($food->serving_size))"/> diff --git a/resources/views/foods/index.blade.php b/resources/views/foods/index.blade.php index bdb7728..16061bc 100644 --- a/resources/views/foods/index.blade.php +++ b/resources/views/foods/index.blade.php @@ -33,7 +33,7 @@ @endif
- Serving size {{ $food->serving_size }} + Serving size {{ \App\Support\Number::fractionStringFromFloat($food->serving_size) }} {{ $food->serving_unit }} ({{ $food->serving_weight }}g)
diff --git a/resources/views/journal-entries/create.blade.php b/resources/views/journal-entries/create.blade.php index 5d0c858..6519955 100644 --- a/resources/views/journal-entries/create.blade.php +++ b/resources/views/journal-entries/create.blade.php @@ -60,11 +60,10 @@ @for ($i = 0; $i < 10; $i++)
- + :value="old('amounts.' . $i)" />
Ingredients @for($i = 0; $i < 20; $i++)
- + size="5" + :value="old('foods_amount.' . $i)" /> diff --git a/resources/views/recipes/show.blade.php b/resources/views/recipes/show.blade.php index f67e404..c193bba 100644 --- a/resources/views/recipes/show.blade.php +++ b/resources/views/recipes/show.blade.php @@ -13,7 +13,7 @@

Ingredients

@foreach($recipe->foodAmounts as $ia)
-
{{ $ia->amount }}
+
{{ \App\Support\Number::fractionStringFromFloat($ia->amount) }}
@if($ia->unit)
{{ $ia->unit }}
@endif
{{ $ia->food->name }}