mirror of https://github.com/kcal-app/kcal.git
Move date and meal fields to each line (WIP)
Frontend only, no backend support yet.
This commit is contained in:
parent
7526138ad2
commit
309ec6810c
|
@ -9,6 +9,7 @@ use App\Models\Food;
|
|||
use App\Models\JournalEntry;
|
||||
use App\Models\Recipe;
|
||||
use App\Rules\ArrayNotEmpty;
|
||||
use App\Rules\InArray;
|
||||
use App\Rules\StringIsDecimalOrFraction;
|
||||
use App\Rules\UsesIngredientTrait;
|
||||
use App\Support\Number;
|
||||
|
@ -44,10 +45,18 @@ class JournalEntryController extends Controller
|
|||
$ingredients = [];
|
||||
if ($old = old('ingredients')) {
|
||||
foreach ($old['amount'] as $key => $amount) {
|
||||
if (empty($amount) && empty($old['unit'][$key]) && empty($old['id'][$key])) {
|
||||
if (
|
||||
empty($old['date'][$key])
|
||||
&& empty($old['meal'][$key])
|
||||
&& empty($amount)
|
||||
&& empty($old['unit'][$key])
|
||||
&& empty($old['id'][$key])
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
$ingredients[] = [
|
||||
'date' => $old['date'][$key],
|
||||
'meal' => $old['meal'][$key],
|
||||
'amount' => $amount,
|
||||
'unit' => $old['unit'][$key],
|
||||
'id' => $old['id'][$key],
|
||||
|
@ -59,12 +68,7 @@ class JournalEntryController extends Controller
|
|||
|
||||
return view('journal-entries.create')
|
||||
->with('ingredients', $ingredients)
|
||||
->with('meals', [
|
||||
['value' => 'breakfast', 'label' => 'Breakfast'],
|
||||
['value' => 'lunch', 'label' => 'Lunch'],
|
||||
['value' => 'dinner', 'label' => 'Dinner'],
|
||||
['value' => 'snacks', 'label' => 'Snacks'],
|
||||
])
|
||||
->with('meals', JournalEntry::$meals)
|
||||
->with('units', [
|
||||
['value' => 'tsp', 'label' => 'tsp.'],
|
||||
['value' => 'tbsp', 'label' => 'tbsp.'],
|
||||
|
@ -81,12 +85,14 @@ class JournalEntryController extends Controller
|
|||
public function store(Request $request): RedirectResponse
|
||||
{
|
||||
$input = $request->validate([
|
||||
'date' => 'required|date',
|
||||
'meal' => 'required|string',
|
||||
'ingredients.date' => ['required', 'array', new ArrayNotEmpty],
|
||||
'ingredients.date.*' => ['nullable', 'date', 'required_with:ingredients.id.*'],
|
||||
'ingredients.meal' => ['required', 'array', new ArrayNotEmpty],
|
||||
'ingredients.meal.*' => ['nullable', 'string', 'required_with:ingredients.id.*', new InArray(array_column(JournalEntry::$meals, 'value'))],
|
||||
'ingredients.amount' => ['required', 'array', new ArrayNotEmpty],
|
||||
'ingredients.amount.*' => ['required_with:foods.*,recipes.*', 'nullable', new StringIsDecimalOrFraction],
|
||||
'ingredients.unit' => 'required|array',
|
||||
'ingredients.unit.*' => 'nullable|string',
|
||||
'ingredients.amount.*' => ['required_with:ingredients.id.*', 'nullable', new StringIsDecimalOrFraction],
|
||||
'ingredients.unit' => ['required', 'array'],
|
||||
'ingredients.unit.*' => ['nullable', 'string'],
|
||||
'ingredients.id' => ['required', 'array', new ArrayNotEmpty],
|
||||
'ingredients.id.*' => 'required_with:ingredients.amount.*|nullable',
|
||||
'ingredients.type' => ['required', 'array', new ArrayNotEmpty],
|
||||
|
|
|
@ -86,6 +86,16 @@ class JournalEntry extends Model
|
|||
*/
|
||||
protected $with = ['user', 'foods:id,name,slug', 'recipes:id,name,slug'];
|
||||
|
||||
/**
|
||||
* Valid meal options.
|
||||
*/
|
||||
public static array $meals = [
|
||||
['value' => 'breakfast', 'label' => 'Breakfast'],
|
||||
['value' => 'lunch', 'label' => 'Lunch'],
|
||||
['value' => 'dinner', 'label' => 'Dinner'],
|
||||
['value' => 'snacks', 'label' => 'Snacks'],
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the User this entry belongs to.
|
||||
*/
|
||||
|
|
|
@ -7,11 +7,7 @@ use Illuminate\Contracts\Validation\Rule;
|
|||
class ArrayNotEmpty implements Rule
|
||||
{
|
||||
/**
|
||||
* Determine if the array is empty.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function passes($attribute, $value): bool
|
||||
{
|
||||
|
@ -19,9 +15,7 @@ class ArrayNotEmpty implements Rule
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the validation error message.
|
||||
*
|
||||
* @return string
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function message(): string
|
||||
{
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use Illuminate\Contracts\Validation\Rule;
|
||||
|
||||
class InArray implements Rule
|
||||
{
|
||||
|
||||
/**
|
||||
* Array to validate against.
|
||||
*/
|
||||
private array $array;
|
||||
|
||||
/**
|
||||
* InArray constructor.
|
||||
*
|
||||
* @param array $array
|
||||
* Array to use for validation.
|
||||
*/
|
||||
public function __construct(array $array) {
|
||||
$this->array = $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function passes($attribute, $value): bool
|
||||
{
|
||||
return in_array($value, $this->array);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function message(): string
|
||||
{
|
||||
return 'Invalid :attribute value :input.';
|
||||
}
|
||||
}
|
|
@ -8,11 +8,7 @@ use Illuminate\Contracts\Validation\Rule;
|
|||
class StringIsDecimalOrFraction implements Rule
|
||||
{
|
||||
/**
|
||||
* Determine if the string is a decimal or fraction, excluding zero.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function passes($attribute, $value): bool
|
||||
{
|
||||
|
@ -27,9 +23,7 @@ class StringIsDecimalOrFraction implements Rule
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the validation error message.
|
||||
*
|
||||
* @return string
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function message(): string
|
||||
{
|
||||
|
|
|
@ -8,11 +8,7 @@ use Illuminate\Contracts\Validation\Rule;
|
|||
class UsesIngredientTrait implements Rule
|
||||
{
|
||||
/**
|
||||
* Determine if the array is empty.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function passes($attribute, $value): bool
|
||||
{
|
||||
|
@ -23,9 +19,7 @@ class UsesIngredientTrait implements Rule
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the validation error message.
|
||||
*
|
||||
* @return string
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function message(): string
|
||||
{
|
||||
|
|
|
@ -11,39 +11,13 @@
|
|||
<div class="p-6 bg-white border-b border-gray-200">
|
||||
<form method="POST" action="{{ route('journal-entries.store') }}">
|
||||
@csrf
|
||||
<div class="flex flex-row mb-4 space-x-4">
|
||||
<!-- Date -->
|
||||
<div>
|
||||
<x-inputs.label for="date" :value="__('Date')"/>
|
||||
|
||||
<x-inputs.input id="date"
|
||||
class="block mt-1"
|
||||
type="date"
|
||||
name="date"
|
||||
:value="old('date', \Illuminate\Support\Carbon::now()->toDateString())"
|
||||
required />
|
||||
</div>
|
||||
|
||||
<!-- Meal -->
|
||||
<div>
|
||||
<x-inputs.label for="meal" :value="__('Meal')"/>
|
||||
|
||||
<x-inputs.select name="meal"
|
||||
class="block mt-1"
|
||||
:options="$meals"
|
||||
:selectedValue="old('meal')"
|
||||
required>
|
||||
<option value=""></option>
|
||||
</x-inputs.select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Items -->
|
||||
<div x-data="{ ingredients: 0 }">
|
||||
<div x-data="{ ingredients: {{ empty($ingredients) ? 0 : -1 }} }">
|
||||
<div class="grid grid-cols-12 gap-4 items-center">
|
||||
<x-inputs.label for="amounts" value="Amount"/>
|
||||
<x-inputs.label for="units" value="Unit" class="col-span-2"/>
|
||||
<x-inputs.label for="foods" value="Food or Recipe" class="col-span-8"/>
|
||||
<x-inputs.label for="ingredients[date][]" value="Date" class="col-span-2"/>
|
||||
<x-inputs.label for="ingredients[meal][]" value="Meal" class="col-span-2"/>
|
||||
<x-inputs.label for="ingredients[amount][]" value="Amount"/>
|
||||
<x-inputs.label for="ingredients[unit][]" value="Unit" class="col-span-2"/>
|
||||
<x-inputs.label for="ingredients[id][]" value="Food or Recipe" class="col-span-4"/>
|
||||
</div>
|
||||
<div>
|
||||
@foreach($ingredients as $ingredient)
|
||||
|
|
|
@ -1,10 +1,33 @@
|
|||
<div class="grid grid-cols-12 gap-4 items-center mt-2">
|
||||
<!-- Date -->
|
||||
<div class="col-span-2">
|
||||
<x-inputs.input class="block w-full"
|
||||
type="date"
|
||||
name="ingredients[date][]"
|
||||
:value="$date ?? \Illuminate\Support\Carbon::now()->toDateString()"
|
||||
required />
|
||||
</div>
|
||||
|
||||
<!-- Meal -->
|
||||
<div class="col-span-2">
|
||||
<x-inputs.select name="ingredients[meal][]"
|
||||
class="block w-full"
|
||||
:options="$meals"
|
||||
:selectedValue="$meal ?? null"
|
||||
required>
|
||||
<option value=""></option>
|
||||
</x-inputs.select>
|
||||
</div>
|
||||
|
||||
<!-- Amount -->
|
||||
<div>
|
||||
<x-inputs.input type="text"
|
||||
name="ingredients[amount][]"
|
||||
class="block w-full"
|
||||
:value="$amount ?? null" />
|
||||
</div>
|
||||
|
||||
<!-- Unit -->
|
||||
<div class="col-span-2">
|
||||
<x-inputs.select name="ingredients[unit][]"
|
||||
class="block w-full"
|
||||
|
@ -13,13 +36,16 @@
|
|||
<option value=""></option>
|
||||
</x-inputs.select>
|
||||
</div>
|
||||
<div class="col-span-8">
|
||||
|
||||
<!-- Ingredient -->
|
||||
<div class="col-span-4">
|
||||
<x-ingredient-picker :default-id="$id ?? null"
|
||||
:default-type="$type ?? null"
|
||||
:default-name="$name ?? null" />
|
||||
</div>
|
||||
<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">
|
||||
|
||||
<x-inputs.icon-button type="button" color="red" x-on:click="$event.target.parentNode.remove(); ingredients--;">
|
||||
<svg class="h-8 w-8 pointer-events-none m-auto" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</x-inputs.icon-button>
|
||||
|
|
Loading…
Reference in New Issue