Add "manual" journal entry option

This commit is contained in:
Christopher C. Wells 2021-01-24 18:56:03 -08:00
parent 089b2edab2
commit d1c66924ea
5 changed files with 137 additions and 12 deletions

View File

@ -80,6 +80,23 @@ class JournalEntryController extends Controller
]); ]);
} }
/**
* Show the form for creating a journal entry from nutrients directly.
*/
public function createFromNutrients(): View
{
return view('journal-entries.create-from-nutrients')
->with('meals', JournalEntry::$meals)
->with('units', [
['value' => 'tsp', 'label' => 'tsp.'],
['value' => 'tbsp', 'label' => 'tbsp.'],
['value' => 'cup', 'label' => 'cup'],
['value' => 'oz', 'label' => 'oz'],
['value' => 'g', 'label' => 'grams'],
['value' => 'servings', 'label' => 'servings'],
]);
}
/** /**
* Store a newly created resource in storage. * Store a newly created resource in storage.
*/ */
@ -158,6 +175,32 @@ class JournalEntryController extends Controller
return redirect()->route('journal-entries.index'); return redirect()->route('journal-entries.index');
} }
/**
* Store an entry from nutrients.
*/
public function storeFromNutrients(Request $request): RedirectResponse {
$attributes = $request->validate([
'date' => ['required', 'date'],
'meal' => ['required', 'string', new InArray(array_column(JournalEntry::$meals, 'value'))],
'summary' => ['required', 'string'],
'calories' => ['nullable', 'required_without_all:fat,cholesterol,sodium,carbohydrates,protein', 'numeric'],
'fat' => ['nullable', 'required_without_all:calories,cholesterol,sodium,carbohydrates,protein', 'numeric'],
'cholesterol' => ['nullable', 'required_without_all:calories,fat,sodium,carbohydrates,protein', 'numeric'],
'sodium' => ['nullable', 'required_without_all:calories,fat,cholesterol,carbohydrates,protein', 'numeric'],
'carbohydrates' => ['nullable', 'required_without_all:calories,fat,cholesterol,sodium,protein', 'numeric'],
'protein' => ['nullable', 'required_without_all:calories,fat,cholesterol,sodium,carbohydrates', 'numeric'],
]);
$entry = JournalEntry::make(array_filter($attributes))
->user()->associate(Auth::user());
$entry->save();
session()->flash('message', "Journal entry added!");
return redirect()->route(
'journal-entries.index',
['date' => $entry->date->format('Y-m-d')]
);
}
/** /**
* Confirm removal of the specified resource. * Confirm removal of the specified resource.
*/ */

View File

@ -0,0 +1,76 @@
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ __('Add Nutrient Journal Entry') }}
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 bg-white border-b border-gray-200">
<form method="POST" action="{{ route('journal-entries.store.from-nutrients') }}">
@csrf
<div class="flex mb-4 space-x-4">
<!-- Date -->
<div>
<x-inputs.label for="date" value="Date"/>
<x-inputs.input name="date"
type="date"
class="block mt-1"
: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>
<!-- Summary -->
<div class="flex-auto">
<x-inputs.label for="summary" value="Summary"/>
<x-inputs.input name="summary"
type="text"
class="block mt-1 w-full"
:value="old('summary')"
required />
</div>
</div>
<div class="flex flex-auto">
@foreach (\App\Support\Nutrients::$all as $nutrient)
<!-- {{ ucfirst($nutrient) }} -->
<div>
<x-inputs.label for="{{ $nutrient }}"
:value="ucfirst($nutrient) . ' (g)'"/>
<x-inputs.input id="{{ $nutrient }}"
class="block w-5/6 mt-1"
type="number"
step="any"
name="{{ $nutrient }}"
:value="old($nutrient)"/>
</div>
@endforeach
</div>
<div class="flex items-center justify-end mt-4">
<x-inputs.button class="ml-3">Add Entry</x-inputs.button>
</div>
</form>
</div>
</div>
</div>
</div>
</x-app-layout>

View File

@ -1,7 +1,7 @@
<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">
{{ __('Add Journal Entry') }} {{ __('Add Journal Entries') }}
</h2> </h2>
</x-slot> </x-slot>

View File

@ -39,6 +39,9 @@
<x-dropdown-link :href="route('journal-entries.create')"> <x-dropdown-link :href="route('journal-entries.create')">
{{ __('Add Entries') }} {{ __('Add Entries') }}
</x-dropdown-link> </x-dropdown-link>
<x-dropdown-link :href="route('journal-entries.create.from-nutrients')">
{{ __('Add Nutrient Entry') }}
</x-dropdown-link>
</x-slot> </x-slot>
</x-dropdown> </x-dropdown>
</div> </div>

View File

@ -25,18 +25,21 @@ Route::get('/dashboard', function () {
return view('dashboard'); return view('dashboard');
})->middleware(['auth'])->name('dashboard'); })->middleware(['auth'])->name('dashboard');
// Foods.
Route::resource('foods', FoodController::class)->middleware(['auth']); Route::resource('foods', FoodController::class)->middleware(['auth']);
Route::get('/foods/{food}/delete', [FoodController::class, 'delete']) Route::get('/foods/{food}/delete', [FoodController::class, 'delete'])->middleware(['auth'])->name('foods.delete');
->middleware(['auth'])
->name('foods.delete');
Route::resource('recipes', RecipeController::class)->middleware(['auth']);
Route::resource('journal-entries', JournalEntryController::class)->middleware(['auth']);
Route::get('/journal-entries/{journalEntry}/delete', [JournalEntryController::class, 'delete'])
->middleware(['auth'])
->name('journal-entries.delete');
Route::get('/ingredient-picker/search', [IngredientPickerController::class, 'search']) // Recipes.
->middleware(['auth']) Route::resource('recipes', RecipeController::class)->middleware(['auth']);
->name('ingredient-picker.search');
// Journal entries.
Route::get('/journal-entries/create-from-nutrients', [JournalEntryController::class, 'createFromNutrients'])->middleware(['auth'])->name('journal-entries.create.from-nutrients');
Route::post('/journal-entries/create-from-nutrients', [JournalEntryController::class, 'storeFromNutrients'])->middleware(['auth'])->name('journal-entries.store.from-nutrients');
Route::resource('journal-entries', JournalEntryController::class)->middleware(['auth']);
Route::get('/journal-entries/{journalEntry}/delete', [JournalEntryController::class, 'delete'])->middleware(['auth'])->name('journal-entries.delete');
// Custom.
// TODO: Change this to a custom JSON API endpoint.
Route::get('/ingredient-picker/search', [IngredientPickerController::class, 'search'])->middleware(['auth'])->name('ingredient-picker.search');
require __DIR__.'/auth.php'; require __DIR__.'/auth.php';