mirror of https://github.com/kcal-app/kcal.git
Filter supported units in ingredient picker
This commit is contained in:
parent
0ba768d7dc
commit
edbcd877c2
|
@ -82,7 +82,7 @@ class JournalEntryController extends Controller
|
|||
) {
|
||||
continue;
|
||||
}
|
||||
$ingredients[] = [
|
||||
$ingredients[$key] = [
|
||||
'date' => $old['date'][$key],
|
||||
'meal' => $old['meal'][$key],
|
||||
'amount' => $amount,
|
||||
|
@ -91,6 +91,18 @@ class JournalEntryController extends Controller
|
|||
'type' => $old['type'][$key],
|
||||
'name' => $old['name'][$key],
|
||||
];
|
||||
|
||||
// Add supported units for the ingredient.
|
||||
$ingredient = NULL;
|
||||
if ($ingredients[$key]['type'] === Food::class) {
|
||||
$ingredient = Food::whereId($ingredients[$key]['id'])->first();
|
||||
}
|
||||
elseif ($ingredients[$key]['type'] === Recipe::class) {
|
||||
$ingredient = Recipe::whereId($ingredients[$key]['id'])->first();
|
||||
}
|
||||
if ($ingredient) {
|
||||
$ingredients[$key]['units'] = $ingredient->units_supported;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ class FoodSchema extends SchemaProvider
|
|||
'servingUnit' => $resource->serving_unit,
|
||||
'servingUnitFormatted' => $resource->serving_unit_formatted,
|
||||
'servingWeight' => $resource->serving_weight,
|
||||
'unitsSupported' => $resource->units_supported->pluck('value'),
|
||||
'createdAt' => $resource->created_at,
|
||||
'updatedAt' => $resource->updated_at,
|
||||
'showUrl' => route('foods.show', $resource),
|
||||
|
|
|
@ -36,6 +36,7 @@ class RecipeSchema extends SchemaProvider
|
|||
'servings' => $resource->servings,
|
||||
'weight' => $resource->weight,
|
||||
'serving_weight' => $resource->serving_weight,
|
||||
'units_supported' => $resource->units_supported->pluck('label'),
|
||||
'caloriesPerServing' => $resource->caloriesPerServing(),
|
||||
'carbohydratesPerServing' => $resource->carbohydratesPerServing(),
|
||||
'cholesterolPerServing' => $resource->cholesterolPerServing(),
|
||||
|
|
|
@ -73,6 +73,7 @@ use Laravel\Scout\Searchable;
|
|||
* @mixin \Eloquent
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Food withUniqueSlugConstraints(\Illuminate\Database\Eloquent\Model $model, string $attribute, array $config, string $slug)
|
||||
* @method static \Database\Factories\FoodFactory factory(...$parameters)
|
||||
* @property-read \Illuminate\Support\Collection $units_supported
|
||||
*/
|
||||
final class Food extends Model
|
||||
{
|
||||
|
@ -129,7 +130,8 @@ final class Food extends Model
|
|||
*/
|
||||
protected $appends = [
|
||||
'serving_size_formatted',
|
||||
'serving_unit_formatted'
|
||||
'serving_unit_formatted',
|
||||
'units_supported',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
@ -77,6 +77,7 @@ use Spatie\MediaLibrary\MediaCollections\Models\Media;
|
|||
* @property-read Collection $ingredients_list
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\RecipeSeparator[] $separators
|
||||
* @property-read int|null $separators_count
|
||||
* @property-read Collection $units_supported
|
||||
*/
|
||||
final class Recipe extends Model implements HasMedia
|
||||
{
|
||||
|
@ -132,6 +133,7 @@ final class Recipe extends Model implements HasMedia
|
|||
protected $appends = [
|
||||
'serving_weight',
|
||||
'time_total',
|
||||
'units_supported'
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,8 +3,10 @@
|
|||
namespace App\Models\Traits;
|
||||
|
||||
use App\Models\IngredientAmount;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use App\Support\Nutrients;
|
||||
use Illuminate\Database\Eloquent\Collection as DatabaseCollection;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Spatie\Tags\Tag;
|
||||
|
||||
|
@ -40,7 +42,7 @@ trait Ingredient
|
|||
*
|
||||
* @see \Spatie\Tags\HasTags
|
||||
*/
|
||||
public static function getTagTotals(string $locale = null): Collection {
|
||||
public static function getTagTotals(string $locale = null): DatabaseCollection {
|
||||
$locale = $locale ?? app()->getLocale();
|
||||
return Tag::query()->join('taggables', 'taggables.tag_id', '=', 'id')
|
||||
->select(['id', 'name', DB::raw('count(*) as total')])
|
||||
|
@ -49,4 +51,20 @@ trait Ingredient
|
|||
->orderBy("name->{$locale}")
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a collection of units supported by this ingredient.
|
||||
*/
|
||||
public function getUnitsSupportedAttribute(): Collection {
|
||||
$units = Nutrients::units();
|
||||
$supported = $units->where('value', 'serving');
|
||||
if (!empty($this->serving_unit)) {
|
||||
$type = $units->where('value', $this->serving_unit)->pluck('type')->first();
|
||||
$supported = $supported->merge($units->where('type', $type));
|
||||
}
|
||||
if (!empty($this->serving_weight)) {
|
||||
$supported = $supported->merge($units->where('type', 'weight'));
|
||||
}
|
||||
return $supported->sortBy('label');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,8 @@ use Illuminate\Support\Facades\Auth;
|
|||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\Goal[] $goals
|
||||
* @property-read int|null $goals_count
|
||||
* @method static \Database\Factories\UserFactory factory(...$parameters)
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\JournalEntry[] $journalEntries
|
||||
* @property-read int|null $journal_entries_count
|
||||
*/
|
||||
final class User extends Authenticatable
|
||||
{
|
||||
|
|
|
@ -16,6 +16,7 @@ class Nutrients
|
|||
* Each entry has two keys:
|
||||
* - value: Machine name for the unit.
|
||||
* - label: Human-readable name for the unit.
|
||||
* - type: Unit type -- matching types can be converted.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
|
@ -23,27 +24,33 @@ class Nutrients
|
|||
return new Collection([
|
||||
'cup' => [
|
||||
'value' => 'cup',
|
||||
'label' => 'cup'
|
||||
'label' => 'cup',
|
||||
'type' => 'volume',
|
||||
],
|
||||
'gram' => [
|
||||
'value' => 'gram',
|
||||
'label' => 'gram'
|
||||
'label' => 'gram',
|
||||
'type' => 'weight',
|
||||
],
|
||||
'oz' => [
|
||||
'value' => 'oz',
|
||||
'label' => 'oz'
|
||||
'label' => 'oz',
|
||||
'type' => 'weight',
|
||||
],
|
||||
'serving' => [
|
||||
'value' => 'serving',
|
||||
'label' => 'serving'
|
||||
'label' => 'serving',
|
||||
'type' => 'division',
|
||||
],
|
||||
'tbsp' => [
|
||||
'value' => 'tbsp',
|
||||
'label' => 'tbsp.'
|
||||
'label' => 'tbsp.',
|
||||
'type' => 'volume',
|
||||
],
|
||||
'tsp' => [
|
||||
'value' => 'tsp',
|
||||
'label' => 'tsp.'
|
||||
'label' => 'tsp.',
|
||||
'type' => 'volume',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
<x-inputs.label for="ingredients[unit][]" value="Unit" class="md:hidden"/>
|
||||
<x-inputs.select name="ingredients[unit][]"
|
||||
class="block w-full"
|
||||
:options="$units"
|
||||
:options="$units ?? []"
|
||||
:selectedValue="$unit ?? null">
|
||||
<option value="">-- Unit --</option>
|
||||
</x-inputs.select>
|
||||
|
@ -74,7 +74,20 @@
|
|||
window.addEventListener('ingredient-picked', (e) => {
|
||||
const entryItem = e.target.closest('.entry-item');
|
||||
const ingredient = e.detail.ingredient;
|
||||
let servingSize, servingUnit;
|
||||
let servingSize, servingUnit
|
||||
|
||||
// Restrict unit select list values to supported units.
|
||||
const unitsSelectList = entryItem.querySelector(':scope select[name="ingredients[unit][]"]');
|
||||
for (const [key, option] in unitsSelectList.options) {
|
||||
unitsSelectList.remove(key);
|
||||
}
|
||||
for (const key in ingredient.units_supported) {
|
||||
const unit = ingredient.units_supported[key];
|
||||
const option = document.createElement('option');
|
||||
option.value = unit.value;
|
||||
option.text = unit.label;
|
||||
unitsSelectList.add(option);
|
||||
}
|
||||
|
||||
// Always set recipes to a default of 1 serving.
|
||||
if (ingredient.type === 'App\\Models\\Recipe') {
|
||||
|
|
Loading…
Reference in New Issue