mirror of https://github.com/kcal-app/kcal.git
Add ability to change goal for a date (#14)
This commit is contained in:
parent
d81ef9952f
commit
c15f81ee6b
|
|
@ -3,6 +3,9 @@ on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\JournalDate;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class JournalDateController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the goals for a journal date.
|
||||||
|
*/
|
||||||
|
public function updateGoal(Request $request, JournalDate $journalDate): RedirectResponse
|
||||||
|
{
|
||||||
|
$attributes = $request->validate(['goal' => 'exists:App\Models\Goal,id']);
|
||||||
|
$journalDate->goal()->associate($attributes['goal'])->save();
|
||||||
|
return redirect()->route('journal-entries.index', [
|
||||||
|
'date' => $journalDate->date->format('Y-m-d')
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,8 @@ namespace App\Http\Controllers;
|
||||||
use App\Http\Requests\StoreFromNutrientsJournalEntryRequest;
|
use App\Http\Requests\StoreFromNutrientsJournalEntryRequest;
|
||||||
use App\Http\Requests\StoreJournalEntryRequest;
|
use App\Http\Requests\StoreJournalEntryRequest;
|
||||||
use App\Models\Food;
|
use App\Models\Food;
|
||||||
|
use App\Models\Goal;
|
||||||
|
use App\Models\JournalDate;
|
||||||
use App\Models\JournalEntry;
|
use App\Models\JournalEntry;
|
||||||
use App\Models\Recipe;
|
use App\Models\Recipe;
|
||||||
use App\Support\ArrayFormat;
|
use App\Support\ArrayFormat;
|
||||||
|
|
@ -53,11 +55,25 @@ class JournalEntryController extends Controller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get all goals as options to change for the date.
|
||||||
|
$goalOptions = Goal::whereUserId(Auth::user()->id)
|
||||||
|
->orderBy('name')
|
||||||
|
->get()
|
||||||
|
->map(function (Goal $goal) {
|
||||||
|
return ['value' => $goal->id, 'label' => $goal->name];
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get the associated journal date.
|
||||||
|
// @todo Refactor journal date as a relationship on journal entries.
|
||||||
|
$journalDate = JournalDate::getOrCreateJournalDate(Auth::user(), $date);
|
||||||
|
|
||||||
return view('journal-entries.index')
|
return view('journal-entries.index')
|
||||||
->with('entries', $entries)
|
->with('entries', $entries)
|
||||||
->with('sums', $sums)
|
->with('sums', $sums)
|
||||||
->with('goal', $goal)
|
->with('currentGoal', $goal)
|
||||||
->with('goalProgress', $goalProgress)
|
->with('goalProgress', $goalProgress)
|
||||||
|
->with('goalOptions', $goalOptions)
|
||||||
|
->with('journalDate', $journalDate)
|
||||||
->with('date', $date);
|
->with('date', $date);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ namespace App\Models;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* App\Models\JournalDate
|
* App\Models\JournalDate
|
||||||
|
|
@ -60,4 +61,24 @@ final class JournalDate extends Model
|
||||||
public function user(): BelongsTo {
|
public function user(): BelongsTo {
|
||||||
return $this->belongsTo(User::class);
|
return $this->belongsTo(User::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a journal date for a user and date, creating a new one if necessary.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $user
|
||||||
|
* User.
|
||||||
|
* @param \Illuminate\Support\Carbon $date
|
||||||
|
* Date.
|
||||||
|
*
|
||||||
|
* @return \App\Models\JournalDate
|
||||||
|
* Journal date for provided user and date.
|
||||||
|
*/
|
||||||
|
public static function getOrCreateJournalDate(User $user, Carbon $date): JournalDate {
|
||||||
|
/** @var \App\Models\JournalDate $journal_date */
|
||||||
|
$journal_date = $user->journalDates()->whereDate('date', '=', $date)->first();
|
||||||
|
if (empty($journal_date)) {
|
||||||
|
$journal_date = JournalDate::make(['date' => $date])->user()->associate($user);
|
||||||
|
}
|
||||||
|
return $journal_date;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -120,11 +120,7 @@ final class User extends Authenticatable implements HasMedia
|
||||||
* method also creates a JournalDate if one does not already exist.
|
* method also creates a JournalDate if one does not already exist.
|
||||||
*/
|
*/
|
||||||
public function getGoalByDate(Carbon $date): ?Goal {
|
public function getGoalByDate(Carbon $date): ?Goal {
|
||||||
/** @var \App\Models\JournalDate $journal_date */
|
$journal_date = JournalDate::getOrCreateJournalDate($this, $date);
|
||||||
$journal_date = $this->journalDates()->whereDate('date', '=', $date)->first();
|
|
||||||
if (empty($journal_date)) {
|
|
||||||
$journal_date = JournalDate::make(['date' => $date])->user()->associate(Auth::user());
|
|
||||||
}
|
|
||||||
if ($journal_date->goal) {
|
if ($journal_date->goal) {
|
||||||
return $journal_date->goal;
|
return $journal_date->goal;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,8 @@
|
||||||
'disabled:opacity-25',
|
'disabled:opacity-25',
|
||||||
'transition',
|
'transition',
|
||||||
'ease-in-out',
|
'ease-in-out',
|
||||||
'duration-150'
|
'duration-150',
|
||||||
|
'cursor-pointer',
|
||||||
];
|
];
|
||||||
@endphp
|
@endphp
|
||||||
<a {{ $attributes->merge(['class' => implode(' ', $classes)]) }}>
|
<a {{ $attributes->merge(['class' => implode(' ', $classes)]) }}>
|
||||||
|
|
|
||||||
|
|
@ -99,15 +99,40 @@
|
||||||
{{ $goalProgress['protein'] ?? 'N/A' }}
|
{{ $goalProgress['protein'] ?? 'N/A' }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h4 class="font-semibold text-lg pt-2">Goal</h4>
|
<section class="pt-2" x-data="{ showGoalChangeForm: false }">
|
||||||
@empty($goal)
|
<h4 class="font-semibold text-lg">
|
||||||
<div class="italic">No goal.</div>
|
Goal
|
||||||
@else
|
<span class="text-sm text-gray-500 hover:text-gray-700 hover:border-gray-300 font-normal cursor-pointer"
|
||||||
<a class="text-gray-500 hover:text-gray-700 hover:border-gray-300"
|
x-show="!showGoalChangeForm"
|
||||||
href="{{ route('goals.show', $goal) }}">
|
x-on:click="showGoalChangeForm = !showGoalChangeForm">[change]</span>
|
||||||
{{ $goal->name }}
|
</h4>
|
||||||
</a>
|
<div x-show="!showGoalChangeForm">
|
||||||
@endempty
|
@empty($currentGoal)
|
||||||
|
<div class="italic">No goal.</div>
|
||||||
|
@else
|
||||||
|
<a class="text-gray-500 hover:text-gray-700 hover:border-gray-300"
|
||||||
|
href="{{ route('goals.show', $currentGoal) }}">
|
||||||
|
{{ $currentGoal->name }}
|
||||||
|
</a>
|
||||||
|
@endempty
|
||||||
|
</div>
|
||||||
|
<div x-show="showGoalChangeForm">
|
||||||
|
<form method="POST" action="{{ route('journal-dates.update.goal', $journalDate) }}">
|
||||||
|
@csrf
|
||||||
|
<x-inputs.select name="goal"
|
||||||
|
class="block w-full"
|
||||||
|
:options="$goalOptions ?? []"
|
||||||
|
:selectedValue="$currentGoal?->id ?? null">
|
||||||
|
</x-inputs.select>
|
||||||
|
<div class="flex items-center justify-start mt-4">
|
||||||
|
<x-inputs.button class="bg-green-800 hover:bg-green-700">Change Goal</x-inputs.button>
|
||||||
|
<x-button-link.red class="ml-3" x-on:click="showGoalChangeForm = !showGoalChangeForm">
|
||||||
|
Cancel
|
||||||
|
</x-button-link.red>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full sm:w-3/5 md:w-2/3 lg:w-3/4 flex flex-col space-y-4">
|
<div class="w-full sm:w-3/5 md:w-2/3 lg:w-3/4 flex flex-col space-y-4">
|
||||||
@foreach(['breakfast', 'lunch', 'dinner', 'snacks'] as $meal)
|
@foreach(['breakfast', 'lunch', 'dinner', 'snacks'] as $meal)
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
use App\Http\Controllers\FoodController;
|
use App\Http\Controllers\FoodController;
|
||||||
use App\Http\Controllers\GoalController;
|
use App\Http\Controllers\GoalController;
|
||||||
use App\Http\Controllers\IngredientPickerController;
|
use App\Http\Controllers\IngredientPickerController;
|
||||||
|
use App\Http\Controllers\JournalDateController;
|
||||||
use App\Http\Controllers\JournalEntryController;
|
use App\Http\Controllers\JournalEntryController;
|
||||||
use App\Http\Controllers\ProfileController;
|
use App\Http\Controllers\ProfileController;
|
||||||
use App\Http\Controllers\RecipeController;
|
use App\Http\Controllers\RecipeController;
|
||||||
|
|
@ -30,6 +31,9 @@ Route::middleware(['auth'])->group(function () {
|
||||||
// Ingredient picker.
|
// Ingredient picker.
|
||||||
Route::get('/ingredient-picker/search', [IngredientPickerController::class, 'search'])->name('ingredient-picker.search');
|
Route::get('/ingredient-picker/search', [IngredientPickerController::class, 'search'])->name('ingredient-picker.search');
|
||||||
|
|
||||||
|
// Journal dates.
|
||||||
|
Route::post('/journal-dates/{journal_date}/update/goal', [JournalDateController::class, 'updateGoal'])->name('journal-dates.update.goal');
|
||||||
|
|
||||||
// Journal entries.
|
// Journal entries.
|
||||||
Route::get('/journal-entries/create/from-nutrients', [JournalEntryController::class, 'createFromNutrients'])->name('journal-entries.create.from-nutrients');
|
Route::get('/journal-entries/create/from-nutrients', [JournalEntryController::class, 'createFromNutrients'])->name('journal-entries.create.from-nutrients');
|
||||||
Route::post('/journal-entries/create/from-nutrients', [JournalEntryController::class, 'storeFromNutrients'])->name('journal-entries.store.from-nutrients');
|
Route::post('/journal-entries/create/from-nutrients', [JournalEntryController::class, 'storeFromNutrients'])->name('journal-entries.store.from-nutrients');
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue