mirror of https://github.com/kcal-app/kcal.git
Fix edit link in Foods list
This commit is contained in:
parent
c29c88776f
commit
2a6549c6d2
|
|
@ -19,8 +19,7 @@ class FoodController extends Controller
|
|||
*/
|
||||
public function index(): View
|
||||
{
|
||||
return view('foods.index')
|
||||
->with('foods', Food::all()->sortBy('name'));
|
||||
return view('foods.index');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -86,8 +85,13 @@ class FoodController extends Controller
|
|||
$attributes['serving_size'] = Number::floatFromString($attributes['serving_size']);
|
||||
$attributes['name'] = Str::lower($attributes['name']);
|
||||
$food->fill(array_filter($attributes))->save();
|
||||
return redirect(route('foods.show', $food))
|
||||
->with('message', 'Changes saved!');
|
||||
|
||||
// Sync tags.
|
||||
$tags = explode(',', $request->get('tags'));
|
||||
$food->syncTags($tags);
|
||||
|
||||
session()->flash('message', "Food {$food->name} updated!");
|
||||
return redirect()->route('foods.show', $food);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -186,6 +186,10 @@ class RecipeController extends Controller
|
|||
'servings' => (int) $input['servings'],
|
||||
]);
|
||||
|
||||
// Sync tags.
|
||||
$tags = explode(',', $request->get('tags'));
|
||||
$recipe->syncTags($tags);
|
||||
|
||||
try {
|
||||
DB::transaction(function () use ($recipe, $input) {
|
||||
if (!$recipe->save()) {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,12 @@ class TagAdapter extends AbstractAdapter
|
|||
*/
|
||||
protected function filter($query, Collection $filters)
|
||||
{
|
||||
$this->filterWithScopes($query, $filters);
|
||||
if ($term = $filters->get('name')) {
|
||||
$query->where('tags.name', 'like', "%{$term}%");
|
||||
}
|
||||
else {
|
||||
$this->filterWithScopes($query, $filters);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ class FoodSchema extends SchemaProvider
|
|||
public function getAttributes($resource): array
|
||||
{
|
||||
return [
|
||||
'slug' => $resource->slug,
|
||||
'name' => $resource->name,
|
||||
'detail' => $resource->detail,
|
||||
'brand' => $resource->brand,
|
||||
|
|
@ -41,6 +42,8 @@ class FoodSchema extends SchemaProvider
|
|||
'servingWeight' => $resource->serving_weight,
|
||||
'createdAt' => $resource->created_at,
|
||||
'updatedAt' => $resource->updated_at,
|
||||
'showUrl' => route('foods.show', $resource),
|
||||
'editUrl' => route('foods.edit', $resource),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ class RecipeSchema extends SchemaProvider
|
|||
public function getAttributes($resource): array
|
||||
{
|
||||
return [
|
||||
'slug' => $resource->slug,
|
||||
'name' => $resource->name,
|
||||
'description' => $resource->description,
|
||||
'source' => $resource->source,
|
||||
|
|
@ -44,6 +45,8 @@ class RecipeSchema extends SchemaProvider
|
|||
'sodiumTotal' => $resource->sodiumTotal(),
|
||||
'createdAt' => $resource->created_at,
|
||||
'updatedAt' => $resource->updated_at,
|
||||
'showUrl' => route('recipes.show', $resource),
|
||||
'editUrl' => route('recipes.edit', $resource),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,98 @@
|
|||
<div x-data data-tags="{{ $defaultTags ?? [] }}">
|
||||
<div x-data="tagSelect()" x-init="init('parentEl')" @click.away="clearSearch()" @keydown.escape="clearSearch()">
|
||||
<div class="relative" @keydown.enter.prevent="addTag(searchTerm)">
|
||||
<x-inputs.input type="hidden"
|
||||
name="tags"
|
||||
value=""
|
||||
x-model="tags"/>
|
||||
<x-inputs.label for="tag_picker" value="Tags"/>
|
||||
<div class="flex flex-row items-center">
|
||||
<x-inputs.input
|
||||
type="text"
|
||||
name="tag_picker"
|
||||
class="mr-2"
|
||||
x-model="searchTerm"
|
||||
x-ref="searchTerm"
|
||||
@input="search($event.target.value)"
|
||||
placeholder="Enter some tags..." />
|
||||
<div x-show="open">
|
||||
<div class="absolute z-40 left-0 mt-2">
|
||||
<div class="py-1 text-sm bg-white rounded shadow-lg border border-gray-300">
|
||||
<template x-for="result in results">
|
||||
<a @click.prevent="addTag(result)"
|
||||
x-text="result"
|
||||
class="block py-1 px-5 cursor-pointer hover:bg-indigo-600 hover:text-white"></a>
|
||||
</template>
|
||||
<a @click.prevent="addTag(searchTerm)"
|
||||
class="block py-1 px-5 cursor-pointer hover:bg-indigo-600 hover:text-white"
|
||||
x-text="searchTerm"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template x-for="(tag, index) in tags">
|
||||
<div class="bg-indigo-100 inline-flex items-center text-sm rounded mr-1">
|
||||
<span class="ml-2 mr-1 leading-relaxed truncate max-w-xs" x-text="tag"></span>
|
||||
<button @click.prevent="removeTag(index)" class="w-6 h-8 inline-block align-middle text-gray-500 hover:text-gray-600 focus:outline-none">
|
||||
<svg class="w-6 h-6 fill-current mx-auto" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill-rule="evenodd" d="M15.78 14.36a1 1 0 0 1-1.42 1.42l-2.82-2.83-2.83 2.83a1 1 0 1 1-1.42-1.42l2.83-2.82L7.3 8.7a1 1 0 0 1 1.42-1.42l2.83 2.83 2.82-2.83a1 1 0 0 1 1.42 1.42l-2.83 2.83 2.83 2.82z"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@once
|
||||
@push('scripts')
|
||||
<script type="text/javascript">
|
||||
function tagSelect() {
|
||||
return {
|
||||
open: false,
|
||||
searchTerm: '',
|
||||
tags: [],
|
||||
results: [],
|
||||
init() {
|
||||
this.tags = JSON.parse(this.$el.parentNode.getAttribute('data-tags'));
|
||||
},
|
||||
addTag(tag) {
|
||||
tag = tag.trim()
|
||||
if (tag !== "" && !this.hasTag(tag)) {
|
||||
this.tags.push( tag )
|
||||
}
|
||||
this.clearSearch()
|
||||
this.$refs.searchTerm.focus()
|
||||
},
|
||||
hasTag(tag) {
|
||||
let foundTag = this.tags.find(e => {
|
||||
return e.toLowerCase() === tag.toLowerCase()
|
||||
})
|
||||
return foundTag !== undefined
|
||||
},
|
||||
removeTag(index) {
|
||||
this.tags.splice(index, 1)
|
||||
},
|
||||
search(q) {
|
||||
if ( q.includes(",") ) {
|
||||
q.split(",").forEach((val) => {
|
||||
this.addTag(val)
|
||||
}, this)
|
||||
}
|
||||
fetch('{{ route('api:v1:tags.index') }}?filter[name]=' + q)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
this.results = data.data.map(tag => tag.attributes.name);
|
||||
});
|
||||
this.toggleSearch();
|
||||
},
|
||||
clearSearch() {
|
||||
this.searchTerm = ''
|
||||
this.toggleSearch();
|
||||
},
|
||||
toggleSearch() {
|
||||
this.open = this.searchTerm !== '';
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@endpush
|
||||
@endonce
|
||||
|
|
@ -110,7 +110,12 @@
|
|||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<!-- Tags -->
|
||||
<x-tagger :defaultTags="$food->tags->pluck('name')"/>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-end mt-4">
|
||||
<x-inputs.button class="ml-3">
|
||||
{{ ($food->exists ? 'Save' : 'Add') }}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
<template x-for="food in foods" :key="food">
|
||||
<div class="p-2 font-light rounded-t border-2 border-gray-400">
|
||||
<a class="h-6 w-6 text-gray-500 hover:text-gray-700 hover:border-gray-300 float-right text-sm"
|
||||
href="/TODO">
|
||||
x-bind:href="food.editUrl">
|
||||
<svg 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" />
|
||||
|
|
@ -76,7 +76,7 @@
|
|||
number: 1,
|
||||
size: 12,
|
||||
morePages: true,
|
||||
searchTerm: null,
|
||||
searchTerm: '{{ $defaultSearch ?? null }}',
|
||||
reset() {
|
||||
this.foods = [];
|
||||
this.number = 1;
|
||||
|
|
@ -88,7 +88,6 @@
|
|||
if (this.searchTerm) {
|
||||
url += `&filter[search]=${this.searchTerm}`;
|
||||
}
|
||||
console.log(url);
|
||||
fetch(url)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
|
|
|
|||
|
|
@ -1,4 +1 @@
|
|||
@php
|
||||
$foods = [$food];
|
||||
@endphp
|
||||
@include('foods.index')
|
||||
@include('foods.index', ['defaultSearch' => $food->name])
|
||||
|
|
|
|||
|
|
@ -39,16 +39,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Description -->
|
||||
<div>
|
||||
<x-inputs.label for="description" :value="__('Description')" />
|
||||
|
||||
<x-inputs.textarea id="description"
|
||||
class="block mt-1 w-full"
|
||||
name="description"
|
||||
:value="old('description', $recipe->description)" />
|
||||
</div>
|
||||
|
||||
<!-- Source -->
|
||||
<div>
|
||||
<x-inputs.label for="source" :value="__('Source')" />
|
||||
|
|
@ -59,6 +49,19 @@
|
|||
name="source"
|
||||
:value="old('source', $recipe->source)" />
|
||||
</div>
|
||||
|
||||
<!-- Description -->
|
||||
<div>
|
||||
<x-inputs.label for="description" :value="__('Description')" />
|
||||
|
||||
<x-inputs.textarea id="description"
|
||||
class="block mt-1 w-full"
|
||||
name="description"
|
||||
:value="old('description', $recipe->description)" />
|
||||
</div>
|
||||
|
||||
<!-- Tags -->
|
||||
<x-tagger :defaultTags="$recipe->tags->pluck('name')"/>
|
||||
</div>
|
||||
|
||||
<!-- Ingredients -->
|
||||
|
|
|
|||
|
|
@ -15,10 +15,18 @@
|
|||
<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">
|
||||
<div class="mb-2 text-gray-500 text-sm">
|
||||
<span class="font-extrabold">Source:</span>
|
||||
{{ $recipe->source }}
|
||||
</div>
|
||||
@if($recipe->tags)
|
||||
<div class="mb-2 text-gray-700 text-sm">
|
||||
<span class="font-extrabold">Tags:</span>
|
||||
{{ implode(', ', $recipe->tags->pluck('name')->all()) }}
|
||||
</div>
|
||||
@endif
|
||||
@if($recipe->source)
|
||||
<div class="mb-2 text-gray-500 text-sm">
|
||||
<span class="font-extrabold">Source:</span>
|
||||
{{ $recipe->source }}
|
||||
</div>
|
||||
@endif
|
||||
<h3 class="mb-2 font-bold">Description</h3>
|
||||
<div class="mb-2 text-gray-800">{{ $recipe->description }}</div>
|
||||
<h3 class="mb-2 font-bold">Ingredients</h3>
|
||||
|
|
|
|||
Loading…
Reference in New Issue