mirror of https://github.com/kcal-app/kcal.git
Refactor ingredients field structure
This commit is contained in:
parent
0c0febed6c
commit
9f180b9b62
|
|
@ -70,8 +70,37 @@ class RecipeController extends Controller
|
||||||
*/
|
*/
|
||||||
public function edit(Recipe $recipe): View
|
public function edit(Recipe $recipe): View
|
||||||
{
|
{
|
||||||
|
// Pre-populate ingredients from form data or current recipe.
|
||||||
|
$ingredients = [];
|
||||||
|
if ($old = old('ingredients')) {
|
||||||
|
foreach ($old['id'] as $key => $food_id) {
|
||||||
|
if (empty($food_id)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$ingredients[] = [
|
||||||
|
'amount' => $old['amount'][$key],
|
||||||
|
'unit' => $old['unit'][$key],
|
||||||
|
'food_id' => $food_id,
|
||||||
|
'food_name' => $old['name'][$key],
|
||||||
|
'detail' => $old['detail'][$key],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
foreach ($recipe->foodAmounts as $foodAmount) {
|
||||||
|
$ingredients[] = [
|
||||||
|
'amount' => $foodAmount->amount_formatted,
|
||||||
|
'unit' => $foodAmount->unit,
|
||||||
|
'food_id' => $foodAmount->food->id,
|
||||||
|
'food_name' => $foodAmount->food->name,
|
||||||
|
'detail' => $foodAmount->detail,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return view('recipes.edit')
|
return view('recipes.edit')
|
||||||
->with('recipe', $recipe)
|
->with('recipe', $recipe)
|
||||||
|
->with('ingredients', $ingredients)
|
||||||
->with('ingredients_units', new Collection([
|
->with('ingredients_units', new Collection([
|
||||||
['value' => 'tsp', 'label' => 'tsp.'],
|
['value' => 'tsp', 'label' => 'tsp.'],
|
||||||
['value' => 'tbsp', 'label' => 'tbsp.'],
|
['value' => 'tbsp', 'label' => 'tbsp.'],
|
||||||
|
|
@ -98,14 +127,14 @@ class RecipeController extends Controller
|
||||||
'description' => 'nullable|string',
|
'description' => 'nullable|string',
|
||||||
'source' => 'nullable|string',
|
'source' => 'nullable|string',
|
||||||
'servings' => 'required|numeric',
|
'servings' => 'required|numeric',
|
||||||
'ingredients_amount' => ['required', 'array', new ArrayNotEmpty],
|
'ingredients.amount' => ['required', 'array', new ArrayNotEmpty],
|
||||||
'ingredients_amount.*' => ['required_with:ingredients.*', 'nullable', new StringIsDecimalOrFraction],
|
'ingredients.amount.*' => ['required_with:ingredients.id.*', 'nullable', new StringIsDecimalOrFraction],
|
||||||
'ingredients_unit' => ['required', 'array'],
|
'ingredients.unit' => ['required', 'array'],
|
||||||
'ingredients_unit.*' => 'nullable|string',
|
'ingredients.unit.*' => 'nullable|string',
|
||||||
'ingredients_detail' => ['required', 'array'],
|
'ingredients.detail' => ['required', 'array'],
|
||||||
'ingredients_detail.*' => 'nullable|string',
|
'ingredients.detail.*' => 'nullable|string',
|
||||||
'ingredients' => ['required', 'array', new ArrayNotEmpty],
|
'ingredients.id' => ['required', 'array', new ArrayNotEmpty],
|
||||||
'ingredients.*' => 'required_with:ingredients_amount.*|nullable|exists:App\Models\Food,id',
|
'ingredients.id.*' => 'required_with:ingredients.amount.*|nullable|exists:App\Models\Food,id',
|
||||||
'steps' => ['required', 'array', new ArrayNotEmpty],
|
'steps' => ['required', 'array', new ArrayNotEmpty],
|
||||||
'steps.*' => 'nullable|string',
|
'steps.*' => 'nullable|string',
|
||||||
]);
|
]);
|
||||||
|
|
@ -126,15 +155,15 @@ class RecipeController extends Controller
|
||||||
$food_amounts = [];
|
$food_amounts = [];
|
||||||
$weight = 0;
|
$weight = 0;
|
||||||
// TODO: Handle removals.
|
// TODO: Handle removals.
|
||||||
foreach (array_filter($input['ingredients_amount']) as $key => $amount) {
|
foreach (array_filter($input['ingredients']['id']) as $key => $food_id) {
|
||||||
$food_amounts[$key] = $recipe->foodAmounts[$key] ?? new FoodAmount();
|
$food_amounts[$key] = $recipe->foodAmounts[$key] ?? new FoodAmount();
|
||||||
$food_amounts[$key]->fill([
|
$food_amounts[$key]->fill([
|
||||||
'amount' => Number::floatFromString($amount),
|
'amount' => Number::floatFromString($input['ingredients']['amount'][$key]),
|
||||||
'unit' => $input['ingredients_unit'][$key],
|
'unit' => $input['ingredients']['unit'][$key],
|
||||||
'detail' => $input['ingredients_detail'][$key],
|
'detail' => $input['ingredients']['detail'][$key],
|
||||||
'weight' => $weight++,
|
'weight' => $weight++,
|
||||||
]);
|
]);
|
||||||
$food_amounts[$key]->food()->associate($input['ingredients'][$key]);
|
$food_amounts[$key]->food()->associate($food_id);
|
||||||
}
|
}
|
||||||
$recipe->foodAmounts()->saveMany($food_amounts);
|
$recipe->foodAmounts()->saveMany($food_amounts);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<x-inputs.input type="hidden"
|
<x-inputs.input type="hidden"
|
||||||
name="ingredients[]"
|
name="ingredients[id][]"
|
||||||
value="{{ $defaultId ?? '' }}"
|
value="{{ $defaultId ?? '' }}"
|
||||||
x-ref="ingredients"/>
|
x-ref="ingredients"/>
|
||||||
<x-inputs.input type="text"
|
<x-inputs.input type="text"
|
||||||
name="ingredients_name[]"
|
name="ingredients[name][]"
|
||||||
value="{{ $defaultName ?? '' }}"
|
value="{{ $defaultName ?? '' }}"
|
||||||
placeholder="Search..."
|
placeholder="Search..."
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
|
|
|
||||||
|
|
@ -64,30 +64,9 @@
|
||||||
<!-- Ingredients -->
|
<!-- Ingredients -->
|
||||||
<h3 class="pt-2 mb-2 font-extrabold">Ingredients</h3>
|
<h3 class="pt-2 mb-2 font-extrabold">Ingredients</h3>
|
||||||
<div x-data="{ ingredients: 0 }">
|
<div x-data="{ ingredients: 0 }">
|
||||||
@if(old('ingredients'))
|
@foreach($ingredients as $ingredient)
|
||||||
@foreach(old('ingredients') as $i => $ingredient)
|
@include('recipes.partials.ingredient-input', $ingredient)
|
||||||
@if (empty($ingredient) && empty(old('ingredients_amount')[$i]) && empty(old('ingredients_unit')[$i]))
|
|
||||||
@continue
|
|
||||||
@endif
|
|
||||||
@include('recipes.partials.ingredient-input', [
|
|
||||||
'amount' => old('ingredients_amount')[$i],
|
|
||||||
'unit' => old('ingredients_unit')[$i],
|
|
||||||
'food_id' => old('ingredients')[$i],
|
|
||||||
'food_name' => old('ingredients_name')[$i],
|
|
||||||
'detail' => old('ingredients_detail')[$i],
|
|
||||||
])
|
|
||||||
@endforeach
|
@endforeach
|
||||||
@else
|
|
||||||
@foreach($recipe->foodAmounts as $foodAmount)
|
|
||||||
@include('recipes.partials.ingredient-input', [
|
|
||||||
'amount' => $foodAmount->amount_formatted,
|
|
||||||
'unit' => $foodAmount->unit,
|
|
||||||
'food_id' => $foodAmount->food->id,
|
|
||||||
'food_name' => $foodAmount->food->name,
|
|
||||||
'detail' => $foodAmount->detail,
|
|
||||||
])
|
|
||||||
@endforeach
|
|
||||||
@endif
|
|
||||||
<template x-for="i in ingredients + 1">
|
<template x-for="i in ingredients + 1">
|
||||||
@include('recipes.partials.ingredient-input')
|
@include('recipes.partials.ingredient-input')
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -100,7 +79,7 @@
|
||||||
|
|
||||||
<!-- Steps -->
|
<!-- Steps -->
|
||||||
<h3 class="pt-2 mb-2 font-extrabold">Steps</h3>
|
<h3 class="pt-2 mb-2 font-extrabold">Steps</h3>
|
||||||
<div x-data="{ steps: 0, step_number: 0 }">
|
<div x-data="{ steps: 0 }">
|
||||||
@if(old('steps'))
|
@if(old('steps'))
|
||||||
@foreach(old('steps') as $i => $step_default)
|
@foreach(old('steps') as $i => $step_default)
|
||||||
@if (empty($step)) @continue @endif
|
@if (empty($step)) @continue @endif
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<div class="flex flex-row space-x-4 mb-4">
|
<div class="flex flex-row space-x-4 mb-4">
|
||||||
<x-inputs.input type="text"
|
<x-inputs.input type="text"
|
||||||
name="ingredients_amount[]"
|
name="ingredients[amount][]"
|
||||||
size="5"
|
size="5"
|
||||||
:value="$amount ?? null" />
|
:value="$amount ?? null" />
|
||||||
<x-inputs.select name="ingredients_unit[]"
|
<x-inputs.select name="ingredients[unit][]"
|
||||||
:options="$ingredients_units"
|
:options="$ingredients_units"
|
||||||
:selectedValue="$unit ?? null">
|
:selectedValue="$unit ?? null">
|
||||||
<option value=""></option>
|
<option value=""></option>
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
:default-name="$food_name ?? null" />
|
:default-name="$food_name ?? null" />
|
||||||
<x-inputs.input type="text"
|
<x-inputs.input type="text"
|
||||||
class="block"
|
class="block"
|
||||||
name="ingredients_detail[]"
|
name="ingredients[detail][]"
|
||||||
:value="$detail ?? null" />
|
:value="$detail ?? null" />
|
||||||
<x-inputs.icon-button type="button" color="red" x-on:click="$event.target.parentNode.remove();">
|
<x-inputs.icon-button type="button" color="red" x-on:click="$event.target.parentNode.remove();">
|
||||||
<svg class="h-8 w-8 pointer-events-none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
|
<svg class="h-8 w-8 pointer-events-none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,14 @@
|
||||||
<x-app-layout>
|
<x-app-layout>
|
||||||
<x-slot name="header">
|
<x-slot name="header">
|
||||||
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
|
<h2 class="font-semibold text-xl text-gray-800 leading-tight flex flex-auto">
|
||||||
{{ $recipe->name }}
|
{{ $recipe->name }}
|
||||||
|
<a class="ml-2 text-gray-500 hover:text-gray-700 hover:border-gray-300 text-sm"
|
||||||
|
href="{{ route('recipes.edit', $recipe) }}">
|
||||||
|
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
|
||||||
|
<path d="M17.414 2.586a2 2 0 00-2.828 0L7 10.172V13h2.828l7.586-7.586a2 2 0 000-2.828z" />
|
||||||
|
<path fill-rule="evenodd" d="M2 6a2 2 0 012-2h4a1 1 0 010 2H4v10h10v-4a1 1 0 112 0v4a2 2 0 01-2 2H4a2 2 0 01-2-2V6z" clip-rule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
</h2>
|
</h2>
|
||||||
</x-slot>
|
</x-slot>
|
||||||
<div class="py-12">
|
<div class="py-12">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue