Add basic personalized goal views (WIP)

This commit is contained in:
Christopher C. Wells 2021-02-13 13:49:11 -08:00
parent 755ef60561
commit a26a4c71d0
5 changed files with 92 additions and 6 deletions

View File

@ -6,6 +6,7 @@ use App\Models\Goal;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
class GoalController extends Controller class GoalController extends Controller
@ -13,9 +14,18 @@ class GoalController extends Controller
/** /**
* Display a listing of the resource. * Display a listing of the resource.
*/ */
public function index(): View public function index(Request $request): View
{ {
return view('goals.index'); if ($request->date) {
$date = Carbon::createFromFormat('Y-m-d', $request->date);
}
else {
$date = Carbon::now();
}
return view('goals.index')
->with('date', $date)
->with('goals', Auth::user()->getGoalsByTime($date))
->with('goalOptions', Goal::getGoalOptions());
} }
/** /**
@ -77,7 +87,9 @@ class GoalController extends Controller
*/ */
public function delete(Goal $goal): View public function delete(Goal $goal): View
{ {
return view('goals.delete')->with('goal', $goal); return view('goals.delete')
->with('goal', $goal)
->with('goalOptions', Goal::getGoalOptions());
} }
/** /**

View File

@ -74,6 +74,7 @@ final class Goal extends Model
$options[$key] = [ $options[$key] = [
'value' => $key, 'value' => $key,
'label' => "{$nutrient['value']} per day", 'label' => "{$nutrient['value']} per day",
'unit' => $nutrient['unit'],
]; ];
} }
return $options; return $options;

View File

@ -6,6 +6,8 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable; use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
/** /**
* App\Models\User * App\Models\User
@ -69,4 +71,31 @@ final class User extends Authenticatable
public function goals(): HasMany { public function goals(): HasMany {
return $this->hasMany(Goal::class); return $this->hasMany(Goal::class);
} }
/**
* Get User's past, present, and future goals.
*
* @return \App\Models\Goal[]
*/
public function getGoalsByTime(?Carbon $date = null): array {
$now = $date ?? Carbon::now();
$goals = ['past' => [], 'present' => [], 'future' => []];
Goal::all()->where('user_id', Auth::user()->id)
->each(function ($item) use(&$goals, $now) {
if ($item->to && $now->isAfter($item->to)) {
$goals['past'][$item->id] = $item;
}
elseif ($item->from && $now->isBefore($item->from)) {
$goals['future'][$item->id] = $item;
}
elseif (
empty($item->from)
|| empty($item->to)
|| $now->isBetween($item->from, $item->to)
) {
$goals['present'][$item->id] = $item;
}
});
return $goals;
}
} }

View File

@ -13,7 +13,7 @@
@method('delete') @method('delete')
@csrf @csrf
<div class="text-lg pb-3"> <div class="text-lg pb-3">
Are you sure what to delete your <span class="font-extrabold">{{ $goal->goal }}</span> goal? Are you sure what to delete your <span class="font-extrabold">{{ $goalOptions[$goal->goal]['label'] }}</span> goal?
</div> </div>
<x-inputs.button class="bg-red-800 hover:bg-red-700"> <x-inputs.button class="bg-red-800 hover:bg-red-700">
Yes, delete Yes, delete

View File

@ -1,7 +1,28 @@
<x-app-layout> <x-app-layout>
<x-slot name="header"> <x-slot name="header">
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
<h2 class="font-semibold text-2xl text-gray-800 leading-tight">{{ Auth::user()->name }}'s Goals</h2> <h2 class="leading-tight text-center">
<div class="text-2xl font-semibold text-gray-800">{{ Auth::user()->name }}'s Goals</div>
<div class="flex items-center space-x-2">
<div>
<a class="text-gray-500 hover:text-gray-700 hover:border-gray-300"
href="{{ route(Route::current()->getName(), ['date' => $date->copy()->subDay(1)->toDateString()]) }}">
<svg class="w-6 h-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm.707-10.293a1 1 0 00-1.414-1.414l-3 3a1 1 0 000 1.414l3 3a1 1 0 001.414-1.414L9.414 11H13a1 1 0 100-2H9.414l1.293-1.293z" clip-rule="evenodd" />
</svg>
</a>
</div>
<div class="text-base text-gray-500">{{ $date->format('D, j M Y') }}</div>
<div>
<a class="text-gray-500 hover:text-gray-700 hover:border-gray-300"
href="{{ route(Route::current()->getName(), ['date' => $date->copy()->addDay(1)->toDateString()]) }}">
<svg class="w-6 h-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-8.707l-3-3a1 1 0 00-1.414 1.414L10.586 9H7a1 1 0 100 2h3.586l-1.293 1.293a1 1 0 101.414 1.414l3-3a1 1 0 000-1.414z" clip-rule="evenodd" />
</svg>
</a>
</div>
</div>
</h2>
<a href="{{ route('goals.create') }}" class="inline-flex items-center rounded-md font-semibold text-white p-2 bg-green-500 tracking-widest hover:bg-green-700 active:bg-green-900 focus:outline-none focus:border-green-900 focus:ring ring-green-600 disabled:opacity-25 transition ease-in-out duration-150"> <a href="{{ route('goals.create') }}" class="inline-flex items-center rounded-md font-semibold text-white p-2 bg-green-500 tracking-widest hover:bg-green-700 active:bg-green-900 focus:outline-none focus:border-green-900 focus:ring ring-green-600 disabled:opacity-25 transition ease-in-out duration-150">
<svg class="w-6 h-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"> <svg class="w-6 h-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 5a1 1 0 011 1v3h3a1 1 0 110 2h-3v3a1 1 0 11-2 0v-3H6a1 1 0 110-2h3V6a1 1 0 011-1z" clip-rule="evenodd" /> <path fill-rule="evenodd" d="M10 5a1 1 0 011 1v3h3a1 1 0 110 2h-3v3a1 1 0 11-2 0v-3H6a1 1 0 110-2h3V6a1 1 0 011-1z" clip-rule="evenodd" />
@ -15,7 +36,30 @@
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8"> <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="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 bg-white border-b border-gray-200"> <div class="p-6 bg-white border-b border-gray-200">
TODO: Goals index. <h3 class="text-xl font-semibold text-gray-800">Goals</h3>
@forelse($goals['present'] as $goal)
<details>
<summary>{{ number_format($goal->amount, 0) }}{{ $goalOptions[$goal->goal]['unit'] }} {{ $goalOptions[$goal->goal]['label'] }}</summary>
TODO: Details for the day!
<div class="flex">
<a class="text-gray-500 hover:text-gray-700 hover:border-gray-300 text-sm"
href="{{ route('goals.edit', $goal) }}">
<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>
<a class="text-red-500 hover:text-red-700 hover:border-red-300 text-sm"
href="{{ route('goals.delete', $goal) }}">
<svg class="h-6 w-6" 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>
</a>
</div>
</details>
@empty
<div>No goals set.</div>
@endforelse
</div> </div>
</div> </div>
</div> </div>