mirror of https://github.com/kcal-app/kcal.git
Complete initial food picker component
This commit is contained in:
parent
6dccf05f2d
commit
5877d24f64
|
|
@ -71,16 +71,8 @@ class RecipeController extends Controller
|
||||||
*/
|
*/
|
||||||
public function edit(Recipe $recipe): View
|
public function edit(Recipe $recipe): View
|
||||||
{
|
{
|
||||||
$foods = Food::all(['id', 'name', 'detail'])->sortBy('name')->collect()
|
|
||||||
->map(function ($food) {
|
|
||||||
return [
|
|
||||||
'value' => $food->id,
|
|
||||||
'label' => "{$food->name}" . ($food->detail ? ", {$food->detail}" : ""),
|
|
||||||
];
|
|
||||||
});
|
|
||||||
return view('recipes.edit')
|
return view('recipes.edit')
|
||||||
->with('recipe', $recipe)
|
->with('recipe', $recipe)
|
||||||
->with('foods', $foods)
|
|
||||||
->with('food_units', new Collection([
|
->with('food_units', new Collection([
|
||||||
['value' => 'tsp', 'label' => 'tsp.'],
|
['value' => 'tsp', 'label' => 'tsp.'],
|
||||||
['value' => 'tbsp', 'label' => 'tbsp.'],
|
['value' => 'tbsp', 'label' => 'tbsp.'],
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,17 @@ use Livewire\Component;
|
||||||
|
|
||||||
class FoodPicker extends Component
|
class FoodPicker extends Component
|
||||||
{
|
{
|
||||||
public string $term = '';
|
public ?string $term = NULL;
|
||||||
|
public int $index;
|
||||||
|
public ?int $defaultId = NULL;
|
||||||
|
public ?string $defaultName = NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the default term on mount.
|
||||||
|
*/
|
||||||
|
public function mount() {
|
||||||
|
$this->term = $this->defaultName;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the view / contents that represent the component.
|
* Get the view / contents that represent the component.
|
||||||
|
|
@ -21,6 +31,7 @@ class FoodPicker extends Component
|
||||||
} else {
|
} else {
|
||||||
$foods = [];
|
$foods = [];
|
||||||
}
|
}
|
||||||
return view('livewire.food-picker')->with('foods', $foods);
|
return view('livewire.food-picker')
|
||||||
|
->with('foods', $foods);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31425,6 +31425,12 @@ select {
|
||||||
animation: bounce 1s infinite;
|
animation: bounce 1s infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See: https://ryangjchandler.co.uk/articles/hiding-elements-until-alpine-is-ready-with-x-cloak */
|
||||||
|
|
||||||
|
[x-cloak] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: 640px) {
|
@media (min-width: 640px) {
|
||||||
.sm\:container {
|
.sm\:container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
||||||
|
|
@ -21338,8 +21338,8 @@ window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||||
/*! no static exports found */
|
/*! no static exports found */
|
||||||
/***/ (function(module, exports, __webpack_require__) {
|
/***/ (function(module, exports, __webpack_require__) {
|
||||||
|
|
||||||
__webpack_require__(/*! /Users/wellc/PhpstormProjects/prndb/resources/js/app.js */"./resources/js/app.js");
|
__webpack_require__(/*! /home/chris/PhpstormProjects/pfnj/resources/js/app.js */"./resources/js/app.js");
|
||||||
module.exports = __webpack_require__(/*! /Users/wellc/PhpstormProjects/prndb/resources/css/app.css */"./resources/css/app.css");
|
module.exports = __webpack_require__(/*! /home/chris/PhpstormProjects/pfnj/resources/css/app.css */"./resources/css/app.css");
|
||||||
|
|
||||||
|
|
||||||
/***/ })
|
/***/ })
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Lodash <https://lodash.com/>
|
||||||
|
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
|
||||||
|
* Released under MIT license <https://lodash.com/license>
|
||||||
|
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
|
||||||
|
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
||||||
|
*/
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
@import 'tailwindcss/base';
|
@import 'tailwindcss/base';
|
||||||
@import 'tailwindcss/components';
|
@import 'tailwindcss/components';
|
||||||
@import 'tailwindcss/utilities';
|
@import 'tailwindcss/utilities';
|
||||||
|
|
||||||
|
/* See: https://ryangjchandler.co.uk/articles/hiding-elements-until-alpine-is-ready-with-x-cloak */
|
||||||
|
[x-cloak] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,46 @@
|
||||||
<div x-data="{isTyped: false}">
|
<div x-data="{searching: false}">
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
|
<x-inputs.input type="hidden"
|
||||||
|
name="foods[{{ $index }}]"
|
||||||
|
:value="$defaultId"
|
||||||
|
x-ref="foods{{ $index }}"/>
|
||||||
<x-inputs.input type="text"
|
<x-inputs.input type="text"
|
||||||
name="food"
|
name="foods_name[{{ $index }}]"
|
||||||
placeholder="{{__('Search ...')}}"
|
:value="$defaultName"
|
||||||
x-on:input.debounce.400ms="isTyped = ($event.target.value != '')"
|
placeholder="Search..."
|
||||||
x-on:focusout="isTyped = false; $event.target.value = ''"
|
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
wire:model.debounce.500ms="term"
|
wire:model.debounce.500ms="term"
|
||||||
aria-label="Search input" />
|
x-on:input.debounce.400ms="searching = ($event.target.value != '')"
|
||||||
|
x-on:focusout.debounce.200ms="searching = false;"
|
||||||
|
x-ref="foods_name{{ $index }}" />
|
||||||
</div>
|
</div>
|
||||||
<div x-show="isTyped" x-cloak>
|
<div x-show="searching" x-cloak>
|
||||||
<div class="absolute border-2 border-gray-500 border-b-0 bg-white">
|
<div class="absolute border-2 border-gray-500 border-b-0 bg-white"
|
||||||
|
x-on:click="selected = $event.target; if (selected.dataset.id) { $refs.foods_name{{ $index }}.value = selected.dataset.value; $refs.foods{{ $index }}.value = selected.dataset.id; searching = false; }">
|
||||||
@forelse($foods as $food)
|
@forelse($foods as $food)
|
||||||
<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"
|
||||||
<div class="text">
|
wire:key="{{ $food->id }}"
|
||||||
{{ $food->name }}@if($food->detail), <span class="text-gray-500">{{ $food->detail }}</span>@endif
|
data-id="{{ $food->id }}"
|
||||||
</div>
|
data-value="{{ $food->name }}">
|
||||||
@if($food->brand)
|
<div class="pointer-events-none">
|
||||||
<div class="text-sm text-gray-600">
|
<div>
|
||||||
{{ $food->brand }}
|
{{ $food->name }}@if($food->detail), <span class="text-gray-500">{{ $food->detail }}</span>@endif
|
||||||
|
</div>
|
||||||
|
@if($food->brand)
|
||||||
|
<div class="text-sm text-gray-600">
|
||||||
|
{{ $food->brand }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
<div class="text-sm">
|
||||||
|
Serving size {{ \App\Support\Number::fractionStringFromFloat($food->serving_size) }}
|
||||||
|
{{ $food->serving_unit }}
|
||||||
|
({{ $food->serving_weight }}g)
|
||||||
</div>
|
</div>
|
||||||
@endif
|
|
||||||
<div class="text-sm">
|
|
||||||
Serving size {{ \App\Support\Number::fractionStringFromFloat($food->serving_size) }}
|
|
||||||
{{ $food->serving_unit }}
|
|
||||||
({{ $food->serving_weight }}g)
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@empty
|
@empty
|
||||||
<div class="border-b-2 border-gray-500" x-cloak>
|
<div class="p-1 border-b-2 border-gray-500" x-cloak>
|
||||||
No results found.
|
No results found.
|
||||||
</div>
|
</div>
|
||||||
@endforelse
|
@endforelse
|
||||||
|
|
|
||||||
|
|
@ -70,10 +70,11 @@
|
||||||
$amount = \App\Support\Number::fractionStringFromFloat($foodAmount->amount);
|
$amount = \App\Support\Number::fractionStringFromFloat($foodAmount->amount);
|
||||||
$unit = $foodAmount->unit;
|
$unit = $foodAmount->unit;
|
||||||
$food_id = $foodAmount->food->id;
|
$food_id = $foodAmount->food->id;
|
||||||
|
$food_name = $foodAmount->food->name;
|
||||||
$detail = $foodAmount->detail;
|
$detail = $foodAmount->detail;
|
||||||
} else {
|
} else {
|
||||||
$foodAmount = new \App\Models\FoodAmount();
|
$foodAmount = new \App\Models\FoodAmount();
|
||||||
$amount = $food_id = $unit = $detail = null;
|
$amount = $food_id = $food_name = $unit = $detail = null;
|
||||||
}
|
}
|
||||||
@endphp
|
@endphp
|
||||||
<div class="flex flex-row space-x-4 mb-4">
|
<div class="flex flex-row space-x-4 mb-4">
|
||||||
|
|
@ -86,12 +87,9 @@
|
||||||
:selectedValue="old('foods_unit.' . $i, $unit)">
|
:selectedValue="old('foods_unit.' . $i, $unit)">
|
||||||
<option value=""></option>
|
<option value=""></option>
|
||||||
</x-inputs.select>
|
</x-inputs.select>
|
||||||
{{-- <x-inputs.select name="foods[]"--}}
|
<livewire:food-picker :index="$i"
|
||||||
{{-- :options="$foods"--}}
|
:default-id="old('foods.' . $i, $food_id)"
|
||||||
{{-- :selectedValue="old('foods.' . $i, $food_id)">--}}
|
:default-name="old('foods_name.' . $i, $food_name)">
|
||||||
{{-- <option value=""></option>--}}
|
|
||||||
{{-- </x-inputs.select>--}}
|
|
||||||
<livewire:food-picker>
|
|
||||||
<x-inputs.input type="text"
|
<x-inputs.input type="text"
|
||||||
class="block"
|
class="block"
|
||||||
name="foods_detail[]"
|
name="foods_detail[]"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue