Improve mobile usability in forms

This commit is contained in:
Christopher C. Wells 2021-01-25 07:31:38 -08:00
parent 536b2236f7
commit a575622c9c
13 changed files with 122 additions and 138 deletions

View File

@ -34,15 +34,15 @@ class JournalEntryController extends Controller
'user_id' => Auth::user()->id, 'user_id' => Auth::user()->id,
'date' => $date, 'date' => $date,
])->get()) ])->get())
->with('date', Carbon::createFromFormat('Y-m-d', $date)) ->with('date', Carbon::createFromFormat('Y-m-d', $date));
->with('nutrients', ['calories', 'fat', 'cholesterol', 'carbohydrates', 'sodium', 'protein']);
} }
/** /**
* Show the form for creating a new resource. * Show the form for creating a new resource.
*/ */
public function create(): View public function create(Request $request): View
{ {
$date = $request->date ?? Carbon::now()->toDateString();
$ingredients = []; $ingredients = [];
if ($old = old('ingredients')) { if ($old = old('ingredients')) {
foreach ($old['amount'] as $key => $amount) { foreach ($old['amount'] as $key => $amount) {
@ -77,7 +77,8 @@ class JournalEntryController extends Controller
['value' => 'oz', 'label' => 'oz'], ['value' => 'oz', 'label' => 'oz'],
['value' => 'g', 'label' => 'grams'], ['value' => 'g', 'label' => 'grams'],
['value' => 'servings', 'label' => 'servings'], ['value' => 'servings', 'label' => 'servings'],
]); ])
->with('default_date', Carbon::createFromFormat('Y-m-d', $date));
} }
/** /**

View File

@ -25,7 +25,8 @@
<div class="p-1 border-b-2 border-gray-500 hover:bg-yellow-300 cursor-pointer" <div class="p-1 border-b-2 border-gray-500 hover:bg-yellow-300 cursor-pointer"
x-bind:data-id="result.id" x-bind:data-id="result.id"
x-bind:data-type="result.type" x-bind:data-type="result.type"
x-bind:data-name="result.name"> x-bind:data-name="result.name"
x-bind:data-detail="result.detail">
<div class="pointer-events-none"> <div class="pointer-events-none">
<div> <div>
<span x-text="result.name"></span><span class="text-gray-600" x-text="', ' + result.detail" x-show="result.detail"></span> <span x-text="result.name"></span><span class="text-gray-600" x-text="', ' + result.detail" x-show="result.detail"></span>
@ -77,7 +78,7 @@
if (selected.dataset.id) { if (selected.dataset.id) {
this.$refs.ingredients.value = selected.dataset.id; this.$refs.ingredients.value = selected.dataset.id;
this.$refs.ingredients_type.value = selected.dataset.type; this.$refs.ingredients_type.value = selected.dataset.type;
this.$refs.ingredients_name.value = selected.dataset.name; this.$refs.ingredients_name.value = `${selected.dataset.name}, ${selected.dataset.detail}`;
this.searching = false; this.searching = false;
} }
} }

View File

@ -5,7 +5,7 @@
autocomplete="off" autocomplete="off"
class="w-full mb-4" class="w-full mb-4"
@input.debounce.400ms="search($event)" /> @input.debounce.400ms="search($event)" />
<div class="grid grid-cols-3 gap-4"> <div class="grid gap-4 grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
{{ $results }} {{ $results }}
</div> </div>
<x-inputs.button <x-inputs.button

View File

@ -13,9 +13,9 @@
@if ($food->exists)@method('put')@endif @if ($food->exists)@method('put')@endif
@csrf @csrf
<div class="flex flex-col space-y-4"> <div class="flex flex-col space-y-4">
<div class="grid grid-cols-3 gap-4"> <div class="flex flex-col space-y-4 md:flex-row md:space-x-4 md:space-y-0">
<!-- Name --> <!-- Name -->
<div> <div class="flex-auto">
<x-inputs.label for="name" value="Name"/> <x-inputs.label for="name" value="Name"/>
<x-inputs.input id="name" <x-inputs.input id="name"
@ -27,7 +27,7 @@
</div> </div>
<!-- Detail --> <!-- Detail -->
<div> <div class="flex-auto">
<x-inputs.label for="detail" value="Detail"/> <x-inputs.label for="detail" value="Detail"/>
<x-inputs.input id="detail" <x-inputs.input id="detail"
@ -38,7 +38,7 @@
</div> </div>
<!-- Brand --> <!-- Brand -->
<div> <div class="flex-auto">
<x-inputs.label for="brand" value="Brand"/> <x-inputs.label for="brand" value="Brand"/>
<x-inputs.input id="brand" <x-inputs.input id="brand"
@ -49,7 +49,7 @@
</div> </div>
</div> </div>
<div class="flex items-center space-x-4"> <div class="flex flex-col space-y-4 sm:flex-row sm:space-x-4 sm:space-y-0">
<!-- Serving size --> <!-- Serving size -->
@php @php
if (!empty($food->serving_size)) { if (!empty($food->serving_size)) {
@ -62,7 +62,7 @@
<x-inputs.label for="serving_size" value="Serving size"/> <x-inputs.label for="serving_size" value="Serving size"/>
<x-inputs.input id="serving_size" <x-inputs.input id="serving_size"
class="block mt-1" class="block mt-1 w-full"
type="text" type="text"
name="serving_size" name="serving_size"
size="10" size="10"
@ -74,6 +74,7 @@
<x-inputs.label for="serving_unit" value="Serving unit"/> <x-inputs.label for="serving_unit" value="Serving unit"/>
<x-inputs.select name="serving_unit" <x-inputs.select name="serving_unit"
class="block mt-1 w-full"
:options="$serving_units" :options="$serving_units"
:selectedValue="old('serving_unit', $food->serving_unit)"> :selectedValue="old('serving_unit', $food->serving_unit)">
<option value=""></option> <option value=""></option>
@ -85,7 +86,7 @@
<x-inputs.label for="serving_weight" value="Serving weight (g)"/> <x-inputs.label for="serving_weight" value="Serving weight (g)"/>
<x-inputs.input id="serving_weight" <x-inputs.input id="serving_weight"
class="block mt-1" class="block mt-1 w-full"
type="number" type="number"
step="any" step="any"
name="serving_weight" name="serving_weight"
@ -94,7 +95,7 @@
</div> </div>
</div> </div>
<div class="flex flex-col md:flex-row"> <div class="flex flex-col space-y-4 md:flex-row md:space-y-0">
@foreach ($nutrients as $nutrient) @foreach ($nutrients as $nutrient)
<!-- {{ ucfirst($nutrient) }} --> <!-- {{ ucfirst($nutrient) }} -->
<div class="flex-auto"> <div class="flex-auto">
@ -102,7 +103,7 @@
:value="ucfirst($nutrient) . ' (g)'"/> :value="ucfirst($nutrient) . ' (g)'"/>
<x-inputs.input id="{{ $nutrient }}" <x-inputs.input id="{{ $nutrient }}"
class="block w-5/6 mt-1" class="block w-full mt-1 md:w-5/6"
type="number" type="number"
step="any" step="any"
name="{{ $nutrient }}" name="{{ $nutrient }}"

View File

@ -1,6 +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">Foods</h2> <div class="flex justify-between items-center">
<h2 class="font-semibold text-2xl text-gray-800 leading-tight">Foods</h2>
<a href="{{ route('foods.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">
<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" />
</svg>
New Food
</a>
</div>
</x-slot> </x-slot>
<div class="py-12"> <div class="py-12">

View File

@ -22,7 +22,7 @@
@include('journal-entries.partials.entry-item-input', $ingredient) @include('journal-entries.partials.entry-item-input', $ingredient)
@endforeach @endforeach
<template x-for="i in ingredients + 1"> <template x-for="i in ingredients + 1">
@include('journal-entries.partials.entry-item-input') @include('journal-entries.partials.entry-item-input', ['default_date' => $default_date])
</template> </template>
</div> </div>
<x-inputs.icon-button type="button" color="green" x-on:click="ingredients++;"> <x-inputs.icon-button type="button" color="green" x-on:click="ingredients++;">

View File

@ -1,6 +1,17 @@
<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">{{ Auth::user()->name }}'s Journal</h2> <div class="flex justify-between items-center">
<h2 class="font-semibold text-2xl text-gray-800 leading-tight">
{{ Auth::user()->name }}'s Journal
<div class="text-base text-gray-500">{{ $date->format('D, j M Y') }}</div>
</h2>
<a href="{{ route('journal-entries.create', ['date' => $date->format('Y-m-d')]) }}" 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">
<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" />
</svg>
New Entry
</a>
</div>
</x-slot> </x-slot>
<div class="py-12"> <div class="py-12">
@ -37,7 +48,7 @@
<h3 class="font-semibold text-lg text-gray-800"> <h3 class="font-semibold text-lg text-gray-800">
{{ Str::ucfirst($meal) }} {{ Str::ucfirst($meal) }}
<span class="text-sm text-gray-500"> <span class="text-sm text-gray-500">
@foreach($nutrients as $nutrient) @foreach(\App\Support\Nutrients::$all as $nutrient)
{{ round($entries->where('meal', $meal)->sum($nutrient), 2) }}g {{ round($entries->where('meal', $meal)->sum($nutrient), 2) }}g
{{ $nutrient }}@if(!$loop->last), @endif {{ $nutrient }}@if(!$loop->last), @endif
@endforeach @endforeach
@ -57,7 +68,7 @@
</div> </div>
<div> <div>
<span class="font-bold">nutrients:</span> <span class="font-bold">nutrients:</span>
@foreach($nutrients as $nutrient) @foreach(\App\Support\Nutrients::$all as $nutrient)
{{ round($entry->{$nutrient}, 2) }}g {{ round($entry->{$nutrient}, 2) }}g
{{ $nutrient }}@if(!$loop->last), @endif {{ $nutrient }}@if(!$loop->last), @endif
@endforeach @endforeach

View File

@ -4,7 +4,7 @@
<x-inputs.input class="block w-full" <x-inputs.input class="block w-full"
type="date" type="date"
name="ingredients[date][]" name="ingredients[date][]"
:value="$date ?? \Illuminate\Support\Carbon::now()->toDateString()" :value="$date ?? $default_date->toDateString()"
required /> required />
</div> </div>

View File

@ -9,70 +9,10 @@
<x-application-logo class="block h-10 w-auto fill-current text-gray-600" /> <x-application-logo class="block h-10 w-auto fill-current text-gray-600" />
</a> </a>
</div> </div>
<div class="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">
<!-- Journal Dropdown --> <x-nav-link :href="route('journal-entries.index')" :active="request()->routeIs('journal-entries.index')">Journal</x-nav-link>
<div class="hidden sm:flex sm:items-center sm:ml-6"> <x-nav-link :href="route('recipes.index')" :active="request()->routeIs('recipes.index')">Recipes</x-nav-link>
<x-dropdown align="left" width="48"> <x-nav-link :href="route('foods.index')" :active="request()->routeIs('foods.index')">Foods</x-nav-link>
<x-slot name="trigger">
<button class="flex items-center text-sm font-medium text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-300 transition duration-150 ease-in-out">
<div>Journal</div>
<div class="ml-1">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
</div>
</button>
</x-slot>
<x-slot name="content">
<x-dropdown-link :href="route('journal-entries.index')">View Journal</x-dropdown-link>
<x-dropdown-link :href="route('journal-entries.create')">Add Entries</x-dropdown-link>
<x-dropdown-link :href="route('journal-entries.create.from-nutrients')">Add Nutrient Entry</x-dropdown-link>
</x-slot>
</x-dropdown>
</div>
<!-- Recipes Dropdown -->
<div class="hidden sm:flex sm:items-center sm:ml-6">
<x-dropdown align="left" width="48">
<x-slot name="trigger">
<button class="flex items-center text-sm font-medium text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-300 transition duration-150 ease-in-out">
<div>Recipes</div>
<div class="ml-1">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
</div>
</button>
</x-slot>
<x-slot name="content">
<x-dropdown-link :href="route('recipes.create')">Add Recipe</x-dropdown-link>
<x-dropdown-link :href="route('recipes.index')">List Recipes</x-dropdown-link>
</x-slot>
</x-dropdown>
</div>
<!-- Foods Dropdown -->
<div class="hidden sm:flex sm:items-center sm:ml-6">
<x-dropdown align="left" width="48">
<x-slot name="trigger">
<button class="flex items-center text-sm font-medium text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-300 transition duration-150 ease-in-out">
<div>Foods</div>
<div class="ml-1">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
</div>
</button>
</x-slot>
<x-slot name="content">
<x-dropdown-link :href="route('foods.create')">Add Food</x-dropdown-link>
<x-dropdown-link :href="route('foods.index')">List Foods</x-dropdown-link>
</x-slot>
</x-dropdown>
</div> </div>
</div> </div>

View File

@ -12,10 +12,9 @@
<form method="POST" action="{{ ($recipe->exists ? route('recipes.update', $recipe) : route('recipes.store')) }}"> <form method="POST" action="{{ ($recipe->exists ? route('recipes.update', $recipe) : route('recipes.store')) }}">
@if ($recipe->exists)@method('put')@endif @if ($recipe->exists)@method('put')@endif
@csrf @csrf
<div class="flex flex-col space-y-4"> <div class="flex flex-col space-y-4 md:flex-row md:space-x-4 md:space-y-0">
<div class="grid grid-cols-5 gap-4">
<!-- Name --> <!-- Name -->
<div class="col-span-4"> <div class="flex-auto">
<x-inputs.label for="name" value="Name" /> <x-inputs.label for="name" value="Name" />
<x-inputs.input id="name" <x-inputs.input id="name"
@ -27,7 +26,7 @@
</div> </div>
<!-- Servings --> <!-- Servings -->
<div> <div class="flex-auto">
<x-inputs.label for="servings" value="Servings" /> <x-inputs.label for="servings" value="Servings" />
<x-inputs.input id="servings" <x-inputs.input id="servings"
@ -37,10 +36,9 @@
:value="old('servings', $recipe->servings)" :value="old('servings', $recipe->servings)"
required /> required />
</div> </div>
</div>
<!-- Source --> <!-- Source -->
<div> <div class="flex-auto">
<x-inputs.label for="source" value="Source" /> <x-inputs.label for="source" value="Source" />
<x-inputs.input id="source" <x-inputs.input id="source"
@ -49,7 +47,8 @@
name="source" name="source"
:value="old('source', $recipe->source)" /> :value="old('source', $recipe->source)" />
</div> </div>
</div>
<div class="flex flex-col space-y-4 mt-4">
<!-- Description --> <!-- Description -->
<div> <div>
<x-inputs.label for="description" value="Description" /> <x-inputs.label for="description" value="Description" />
@ -65,12 +64,12 @@
</div> </div>
<!-- Ingredients --> <!-- Ingredients -->
<h3 class="pt-2 mb-2 font-extrabold">Ingredients</h3> <h3 class="mt-6 mb-2 font-extrabold text-lg">Ingredients</h3>
<div x-data="{ ingredients: 0 }"> <div x-data="{ ingredients: 1 }" class="space-y-4">
@foreach($ingredients as $ingredient) @foreach($ingredients as $ingredient)
@include('recipes.partials.ingredient-input', $ingredient) @include('recipes.partials.ingredient-input', $ingredient)
@endforeach @endforeach
<template x-for="i in ingredients + 1"> <template x-if="ingredients > 0" x-for="i in ingredients">
@include('recipes.partials.ingredient-input') @include('recipes.partials.ingredient-input')
</template> </template>
<x-inputs.icon-button type="button" color="green" x-on:click="ingredients++;"> <x-inputs.icon-button type="button" color="green" x-on:click="ingredients++;">
@ -81,7 +80,7 @@
</div> </div>
<!-- Steps --> <!-- Steps -->
<h3 class="pt-2 mb-2 font-extrabold">Steps</h3> <h3 class="mt-6 mb-2 font-extrabold text-lg">Steps</h3>
<div x-data="{ steps: 0 }"> <div x-data="{ steps: 0 }">
@foreach($steps as $step) @foreach($steps as $step)
@include('recipes.partials.step-input', $step) @include('recipes.partials.step-input', $step)

View File

@ -1,6 +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">Recipes</h2> <div class="flex justify-between items-center">
<h2 class="font-semibold text-2xl text-gray-800 leading-tight">Recipes</h2>
<a href="{{ route('recipes.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">
<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" />
</svg>
New Recipe
</a>
</div>
</x-slot> </x-slot>
<div class="py-12"> <div class="py-12">

View File

@ -1,24 +1,39 @@
<div class="flex flex-row space-x-4 mb-4"> <div>
<x-inputs.input type="hidden" name="ingredients[original_key][]" :value="$original_key ?? null" /> <x-inputs.input type="hidden" name="ingredients[original_key][]" :value="$original_key ?? null" />
<x-inputs.input type="text" <div class="flex items-center space-x-2">
name="ingredients[amount][]" <div class="flex flex-col space-y-4 md:flex-row md:space-x-4 md:space-y-0 w-full">
<x-inputs.input name="ingredients[amount][]"
type="text"
size="5" size="5"
placeholder="Amount"
class="block"
:value="$amount ?? null" /> :value="$amount ?? null" />
<x-inputs.select name="ingredients[unit][]" <x-inputs.select name="ingredients[unit][]"
class="block"
:options="$ingredients_units" :options="$ingredients_units"
:selectedValue="$unit ?? null"> :selectedValue="$unit ?? null">
<option value=""></option> <option value=""></option>
</x-inputs.select> </x-inputs.select>
<div class="w-full">
<x-ingredient-picker :default-id="$ingredient_id ?? null" <x-ingredient-picker :default-id="$ingredient_id ?? null"
:default-type="$ingredient_type ?? null" :default-type="$ingredient_type ?? null"
:default-name="$ingredient_name ?? null" /> :default-name="$ingredient_name ?? null" />
<x-inputs.input type="text" </div>
<x-inputs.input name="ingredients[detail][]"
type="text"
class="block" class="block"
name="ingredients[detail][]" placeholder="Detail (diced, chopped, etc.)"
:value="$detail ?? null" /> :value="$detail ?? null" />
<x-inputs.icon-button type="button" color="red" x-on:click="$event.target.parentNode.remove();"> </div>
<div class="flex-none">
<x-inputs.icon-button type="button"
color="red"
x-on:click="$event.target.parentNode.parentNode.parentNode.remove(); (ingredients > 1 ? ingredients-- : null);">
<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">
<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" /> <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> </svg>
</x-inputs.icon-button> </x-inputs.icon-button>
</div>
</div>
<hr class="my-4 md:hidden" x-show="ingredients > 0"/>
</div> </div>

View File

@ -41,7 +41,7 @@
{{ $ia->ingredient->name }} {{ $ia->ingredient->name }}
</a> </a>
@else @else
{{ $ia->ingredient->name }} {{ $ia->ingredient->name }}@if($ia->ingredient->detail), {{ $ia->ingredient->detail }}@endif
@endif @endif
</div> </div>
@if($ia->detail)<div class="text-gray-500">{{ $ia->detail }}</div>@endif @if($ia->detail)<div class="text-gray-500">{{ $ia->detail }}</div>@endif