File app/Http/Controllers/IngredientController.php
(link to Github)
use Auth;
use Gate;
use App\Models\Ingredient;
use Illuminate\Http\Request;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use App\Http\Requests\StoreIngredientRequest;
use App\Http\Requests\UpdateIngredientRequest;
class IngredientController extends Controller
{
public function index(): View
{
abort_if(Gate::denies('ingredient_access'), 403);
return view('admin.ingredients.index');
}
public function create(): View
{
abort_if(Gate::denies('ingredient_create'), 403);
return view('admin.ingredients.create');
}
public function store(StoreIngredientRequest $request): RedirectResponse
{
$ingredient = Auth::User()->Ingredients()->create($request->validated());
return redirect($ingredient->path());
}
public function show(Ingredient $ingredient): View
{
abort_if(Gate::denies('ingredient_show'), 403);
$ingredient->load('recipes.media', 'recipes.ratings');
return view('admin.ingredients.show', compact('ingredient'));
}
public function edit(Ingredient $ingredient): View
{
abort_if(Gate::denies('ingredient_edit'), 403);
abort_if($ingredient->user->id != \Auth::id(), 403);
return view('admin.ingredients.edit', compact('ingredient'));
}
public function update(UpdateIngredientRequest $request, Ingredient $ingredient): RedirectResponse
{
abort_if($ingredient->user->id != \Auth::id(), 403);
$ingredient->update($request->validated());
return redirect($ingredient->path());
}
public function destroy(Ingredient $ingredient): RedirectResponse
{
abort_if(Gate::denies('ingredient_delete')
|| $ingredient->user_id != \Auth::id(), 403);
$ingredient->delete();
return redirect()->route('admin.ingredients.index');
}
}
File routes/web.php
(link to Github)
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\IngredientController;
Route::middleware(['auth', 'verified', 'approved'])->group(function() {
//
Route::prefix('admin')->name('admin.')->group(function() {
//
Route::resource('ingredients', IngredientController::class);
});
});
File views/admin/ingredients/index.blade.php
(link to Github)
@extends('admin.layout')
@section('title', 'Ingredients')
@section('admin.content')
@livewire('ingredients.index')
@endsection
File resources/views/admin/ingredients/create.blade.php
(link to Github)
@extends('admin.layout')
@section('title', 'Create New Ingrident')
@section('admin.content')
<div class="w-full p-4 bg-white border-b border-gray-200 rounded-t-md dark:bg-gray-700">
<p class="font-bold dark:text-gray-200">
Create new Ingredient
</p>
</div>
<form action="{{ route('admin.ingredients.store') }}" method="POST" class="p-4 space-y-4">
@csrf
<div class="grid grid-cols-1 lg:grid-cols-6">
<label for="name" class="dark:text-gray-200 self-center">
Name
</label>
<input type="text" name="name" id="name" value="{{ old('name') }}" class="border-1 border-gray-100 shadow bg-opacity-20 rounded-lg placeholder-gray-500 w-full lg:w-60 focus:outline-none focus:ring-1 focus:border-green-500 focus:ring-green-500 dark:bg-gray-900 dark:border-transparent dark:text-gray-200">
</div>
<div>
<button type="submit" class="w-full lg:w-auto rounded shadow-md py-2 px-4 bg-green-700 text-white hover:bg-green-500">
Create Ingredient
</button>
</div>
</form>
@endsection
File resources/views/admin/ingredients/edit.blade.php
(link to Github)
@extends('admin.layout')
@section('title', 'Edit - ' . $ingredient->name)
@section('admin.content')
<div class="w-full p-4 bg-white border-b border-gray-200 rounded-t-md dark:bg-gray-700">
<p class="font-bold dark:text-gray-200">
Edit Ingredient - {{ $ingredient->name }}
</p>
</div>
<form action="{{ route('admin.ingredients.update', $ingredient) }}" method="POST" class="p-4 space-y-4">
@csrf
@method('PATCH')
<div class="grid grid-cols-1 lg:grid-cols-6">
<label for="name" class="dark:text-gray-200 self-center">
Name
</label>
<input type="text" name="name" id="name" value="{{ old('name', $ingredient->name) }}" class="border-1 border-gray-100 shadow bg-opacity-20 rounded-lg placeholder-gray-500 w-full lg:w-60 focus:outline-none focus:ring-1 focus:border-green-500 focus:ring-green-500 dark:bg-gray-900 dark:border-transparent dark:text-gray-200">
</div>
<div>
<button type="submit" class="w-full lg:w-auto rounded shadow-md py-2 px-4 bg-green-700 text-white hover:bg-green-500">
Save Changes
</button>
</div>
</form>
@endsection
File resources/views/admin/ingredients/show.blade.php
(link to Github)
@extends('admin.layout')
@section('title', $ingredient->name)
@section('admin.content')
<div class="w-full p-4 bg-white border-b border-gray-200 rounded-t-md dark:bg-gray-700">
<p class="font-bold dark:text-gray-200">
{{ $ingredient->name }}
</p>
</div>
<div class="p-4 space-y-4">
@if ($ingredient->recipes()->count() > 0)
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-6 mb-5">
@foreach ($ingredient->recipes as $recipe)
<a href="{{ route('recipes.show', $recipe) }}">
<div class="w-full h-full rounded-md shadow-md dark:bg-gray-700">
<div>
@if ($recipe->getMedia()->count() > 0)
<img src="{{ $recipe->getFirstMediaUrl('default', 'thumb') }}" class="w-full max-h-32 object-cover rounded-t-md">
@else
<img src="https://via.placeholder.com/640x360.png?text=No+Image" class="w-full h-32 object-cover rounded-t-md">
@endif
</div>
<div class="bg-white p-4 rounded-b-md dark:bg-gray-700 dark:text-gray-200">
<p class="mb-2">
{{ $recipe->name }}
</p>
<p class="text-sm text-yellow-400" title="{{ $recipe->avg_rating > 0 ? $recipe->avg_rating : '0' }}">
@for ($x = 0; $x < 5; $x++)
@if (floor($recipe->avg_rating)-$x >= 1)
<i class="fas fa-star"></i>
@elseif ($recipe->avg_rating-$x > 0)
<i class="fas fa-star-half-alt"></i>
@else
<i class="far fa-star"></i>
@endif
@endfor
</p>
</div>
</div>
</a>
@endforeach
</div>
@else
No Recipes are using this ingredient.
@endif
</div>
@endsection
Additional resources on CRUD:
-
Kingsley Okpara | dev.to
Published on