Big update for category controller - for admin panel

This commit is contained in:
Kamil Niemczycki 2022-02-15 15:26:10 +01:00
parent 982438a26e
commit 38e5a8f485
19 changed files with 363 additions and 14 deletions

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
@ -15,6 +16,9 @@ class LoginController extends Controller
public function authenticate(Request $request)
{
if (Auth::check())
return redirect()->route('admin.home');
$credentials = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
@ -39,8 +43,11 @@ class LoginController extends Controller
return redirect()->route('admin.auth.login');
}
public function login(): View
public function login(): View|RedirectResponse
{
if (Auth::check())
return redirect()->route('admin.home');
return view('auth.login');
}

View File

@ -3,6 +3,8 @@
namespace App\Http\Controllers\Dashboard;
use App\Http\Controllers\Controller;
use App\Repository\Interfaces\CategoryRepository;
use App\Repository\Interfaces\ProjectRepository;
use Illuminate\Http\Request;
use Illuminate\View\View;
@ -10,12 +12,18 @@ class AdminPanelController extends Controller
{
public function __construct(
) {}
private CategoryRepository $categoryRepository,
private ProjectRepository $projectRepository
) {
$this->categoryRepository->auth = true;
}
public function __invoke(Request $request): View
{
return view('dashboard.home');
$categories = $this->categoryRepository->all();
$projects = $this->projectRepository->all();
return view('dashboard.home', compact('categories', 'projects'));
}
}

View File

@ -0,0 +1,63 @@
<?php
declare(strict_types=1);
namespace App\Http\Controllers\Dashboard;
use App\Http\Requests\CategoryRequest;
use App\Models\Category;
use App\Repository\Interfaces\CategoryRepository;
use Illuminate\Http\RedirectResponse;
use Illuminate\View\View;
class CategoryController
{
public function __construct(
private CategoryRepository $categoryRepository
) {}
public function update(CategoryRequest $request, Category $category)
{
$validate = $request->validated();
if ($this->categoryRepository->update($category, $validate)) {
return back()->with('message', 'Zaktualizowano kategorię!');
}
return back()->withError(['message_error', 'Wystąpił błąd podczas aktualizacji!']);
}
public function store(CategoryRequest $request)
{
$validate = $request->validated();
if ($category = $this->categoryRepository->create($validate)) {
return redirect()->route('admin.category.update', ['category' => $category])->with('message', 'Utworzono kategorię!');
}
return back()->withError(['message_error', 'Wystąpił błąd podczas tworzenia!']);
}
public function create(): View
{
return view('dashboard.categories.create');
}
public function edit(Category $category): View
{
return view('dashboard.categories.edit', compact('category'));
}
public function delete(Category $category): View
{
return view('dashboard.categories.delete', compact('category'));
}
public function destroy(Category $category): RedirectResponse
{
$name = $category->name;
$category->delete();
return redirect()->route('admin.home')->with('message', 'Usunięto kategorię "'. $name .'"');
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CategoryRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => 'required|string|min:3|max:25',
'slug' => 'required|string|min:3|max:25',
'priority' => 'required|numeric|min:0|max:10',
'default' => 'nullable|in:yes,1,true,on',
'visible' => 'nullable|in:yes,1,true,on'
];
}
}

View File

@ -2,7 +2,7 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
/**
@ -25,4 +25,13 @@ class Category extends Model
'default' => 'bool',
'visible' => 'bool'
];
public function scopeVisibled(Builder $builder)
{
return $builder->where(function (Builder $query) {
$query->where('visible', true)
->orWhere('default', true);
});
}
}

View File

@ -13,6 +13,8 @@ use Illuminate\Support\Collection;
class CategoryRepository implements CategoryRepositoryInterface
{
public bool $auth = false;
public function __construct(
private Category $category
) {}
@ -22,8 +24,12 @@ class CategoryRepository implements CategoryRepositoryInterface
$categories = $this->category
->query()
->orderby('priority', 'ASC')
->orderby('name', 'ASC')->get();
return (new CategoryCollection($categories))->collection;
->orderby('name', 'ASC');
if (!$this->auth)
$categories->visibled();
return (new CategoryCollection($categories->get()))->collection;
}
public function get(string $slug): CategoryResource
@ -32,12 +38,19 @@ class CategoryRepository implements CategoryRepositoryInterface
->query()
->where('slug', $slug)
->firstOrFail();
if (!$this->auth)
$category->visibled();
return new CategoryResource($category);
}
public function update(Category $category, array $data = []): bool
{
$data = $this->parseToArray($data);
if (!$category->default && isset($data['default']) && $data['default'] === true)
$this->unsetDefault();
return $category
->update($data);
}
@ -45,11 +58,22 @@ class CategoryRepository implements CategoryRepositoryInterface
public function create(array $data = []): Category
{
$data = $this->parseToArray($data);
if (isset($data['default']) && $data['default'] === true)
$this->unsetDefault();
return $this->category
->query()
->create($data);
}
private function unsetDefault(): void
{
$this->category
->query()
->where('default', true)
->first()?->update(['default' => false]);
}
private function parseToArray(array $data = []): array
{
$toSave = [];
@ -58,10 +82,21 @@ class CategoryRepository implements CategoryRepositoryInterface
$toSave['name'] = $data['name'];
if (isset($data['slug']) && !empty($data['slug']))
$toSave['slug'] = $data['slug'];
if (isset($data['default']) && is_bool($data['default']))
$toSave['default'] = $data['default'];
if (isset($data['visible']) && is_bool($data['visible']))
$toSave['visible'] = $data['visible'];
if (isset($data['priority']) && !is_integer($data['priority']))
$toSave['priority'] = (int)$data['priority'];
if (
isset($data['default']) &&
in_array($data['default'], ['yes', 'on', 1, true])
) $toSave['default'] = true;
else $toSave['default'] = false;
if (
(isset($toSave['default']) && $toSave['default'] === true) ||
(isset($data['visible']) &&
in_array($data['visible'], ['yes', 'on', 1, true]))
) $toSave['visible'] = true;
else $toSave['visible'] = false;
return $toSave;
}

19
public/js/app.js vendored
View File

@ -19318,6 +19318,19 @@ __webpack_require__.r(__webpack_exports__);
// extracted by mini-css-extract-plugin
/***/ }),
/***/ "./resources/sass/dashboard.scss":
/*!***************************************!*\
!*** ./resources/sass/dashboard.scss ***!
\***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
// extracted by mini-css-extract-plugin
/***/ }),
/***/ "./node_modules/process/browser.js":
@ -19636,6 +19649,7 @@ module.exports = JSON.parse('{"name":"axios","version":"0.21.4","description":"P
/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
/******/ var installedChunks = {
/******/ "/js/app": 0,
/******/ "css/dashboard": 0,
/******/ "css/app": 0
/******/ };
/******/
@ -19686,8 +19700,9 @@ module.exports = JSON.parse('{"name":"axios","version":"0.21.4","description":"P
/******/ // startup
/******/ // Load entry module and return exports
/******/ // This entry module depends on other loaded chunks and execution need to be delayed
/******/ __webpack_require__.O(undefined, ["css/app"], () => (__webpack_require__("./resources/js/app.js")))
/******/ var __webpack_exports__ = __webpack_require__.O(undefined, ["css/app"], () => (__webpack_require__("./resources/sass/app.scss")))
/******/ __webpack_require__.O(undefined, ["css/dashboard","css/app"], () => (__webpack_require__("./resources/js/app.js")))
/******/ __webpack_require__.O(undefined, ["css/dashboard","css/app"], () => (__webpack_require__("./resources/sass/app.scss")))
/******/ var __webpack_exports__ = __webpack_require__.O(undefined, ["css/dashboard","css/app"], () => (__webpack_require__("./resources/sass/dashboard.scss")))
/******/ __webpack_exports__ = __webpack_require__.O(__webpack_exports__);
/******/
/******/ })()

View File

@ -1,4 +1,5 @@
{
"/js/app.js": "/js/app.js",
"/css/dashboard.css": "/css/dashboard.css",
"/css/app.css": "/css/app.css"
}

1
resources/sass/dashboard.scss vendored Normal file
View File

@ -0,0 +1 @@
@import "./dashboard/categories"

View File

@ -0,0 +1,5 @@
.categories {
.category {
display: block;
}
}

View File

@ -0,0 +1,49 @@
@extends('layout.app')
@section('title', 'Utwórz kategorię')
@section('main')
@if (\Session::has('message'))
<span>{{ \Session::get('message') }}</span>
@endif
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form class="form" method="POST" action="{{ route('admin.category.store') }}">
@csrf
<label for="name">Nazwa kategorii</label>
<input id="name" type="text" name="name" value="{{ old('name') }}" placeholder="Nazwa">
@error('name')
<span class="error">{{ $message }}</span>
@enderror
<label for="slug">Slug (opcjonalny)</label>
<input id="slug" type="text" name="slug" value="{{ old('slug') }}" placeholder="Slug">
@error('slug')
<span class="error">{{ $message }}</span>
@enderror
<label for="priority">Priority</label>
<input id="priority" type="number" name="priority" value="{{ old('priority', 0) }}" min="0">
@error('name')
<span class="error">{{ $message }}</span>
@enderror
<label for="default">Default</label>
<input id="default" type="checkbox" name="default" {{ old('default') != 0 ? 'checked' : '' }}>
<label for="visible">Visible</label>
<input id="visible" type="checkbox" name="visible" {{ old('default') != 0 ? 'checked' : '' }}>
<input type="submit" value="Utwórz">
</form>
<div>
<a href="{{ route('admin.home') }}"><< Cofnij</a>
</div>
@endsection

View File

@ -0,0 +1,14 @@
@extends('layout.app')
@section('title', 'Login')
@section('main')
<form method="POST" action="{{ route('admin.category.destroy', compact('category')) }}">
@method('DELETE')
@csrf
Czy jesteś pewien, że chcesz usunąć kategorię "{{ $category->name .' - '. $category->slug }}"?
<input type="submit" value="Tak, usuń!">
</form>
<div>
<a href="{{ route('admin.category.edit', compact('category')) }}"><< Cofnij</a>
</div>
@endsection

View File

@ -0,0 +1,53 @@
@extends('layout.app')
@section('title', 'Login')
@section('main')
@if (\Session::has('message'))
<span>{{ \Session::get('message') }}</span>
@endif
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form class="form" method="POST" action="{{ route('admin.category.update', ['category' => $category]) }}">
@method('PUT')
@csrf
<label for="name">Nazwa kategorii</label>
<input id="name" type="text" name="name" value="{{ old('name', $category->name) }}" placeholder="Nazwa">
@error('name')
<span class="error">{{ $message }}</span>
@enderror
<label for="slug">Slug (opcjonalny)</label>
<input id="slug" type="text" name="slug" value="{{ old('slug', $category->slug) }}" placeholder="Slug">
@error('slug')
<span class="error">{{ $message }}</span>
@enderror
<label for="priority">Priority</label>
<input id="priority" type="number" name="priority" value="{{ old('priority', $category->priority) }}" min="0">
@error('priority')
<span class="error">{{ $message }}</span>
@enderror
<label for="default">Default</label>
<input id="default" type="checkbox"
name="default" {{ old('default', $category->default) != 0 ? 'checked' : '' }}>
<label for="visible">Visible</label>
<input id="visible" type="checkbox"
name="visible" {{ old('visible', $category->visible) != 0 ? 'checked' : '' }}>
<input type="submit" value="Edytuj">
</form>
<div>
<a href="{{ route('admin.category.delete', compact('category')) }}">USUŃ!</a><br>
<a href="{{ route('admin.home') }}"><< Cofnij</a>
</div>
@endsection

View File

@ -0,0 +1,11 @@
<div class="categories">
<header><h1>Kategorie</h1></header>
<a href="{{ route('admin.category.create') }}">
<button>Utwórz nową kategorię</button>
</a>
<ul class="category_items">
@foreach ($categories as $category)
<li class="project_element">{{ $category->name }} | <a href="{{ route('admin.category.edit', ['category' => $category->id]) }}">Edytuj</a></li>
@endforeach
<ul>
</div>

View File

@ -1,6 +1,23 @@
@extends('layout.app')
@section('title', 'Dashboard')
@section('main')
@push('styles')
<style>
#main {
display: grid;
grid-template-columns: repeat(3, 1fr);
column-gap: 1em;
}
#main .projects {
grid-column: 1 / 3;
}
</style>
@endpush
@section('main')
@if(\Session::has('message'))
<span>{{ \Session::get('message') }}</span>
@endif
@include('dashboard.projects.list')
@include('dashboard.categories.list')
@endsection

View File

@ -0,0 +1,11 @@
<div class="projects">
<header><h1>Projekty</h1></header>
<a href="{{ route('admin.category.create') }}">
<button>Utwórz nowy projekt</button>
</a>
<ul class="project_items">
@foreach ($projects as $project)
<li class="project_element">{{ $project->title }} | <a href="{{ route('admin.category.edit', ['category' => $project->id]) }}">Edytuj</a></li>
@endforeach
<ul>
</div>

View File

@ -11,6 +11,7 @@
<!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
@stack('styles')
</head>
<body class="antialiased">
<main id="main">

View File

@ -16,6 +16,20 @@ use Illuminate\Support\Facades\Route;
Route::name('admin.')->group(function () {
Route::namespace('Dashboard')->middleware('auth')->group(function () {
Route::get('', 'AdminPanelController')->name('home');
Route::name('category.')->prefix('category')->group(function () {
Route::get('create', 'CategoryController@create')
->name('create');
Route::post('', 'CategoryController@store')
->name('store');
Route::get('{category}', 'CategoryController@edit')
->name('edit');
Route::put('{category}', 'CategoryController@update')
->name('update');
Route::get('{category}/delete', 'CategoryController@delete')
->name('delete');
Route::delete('{category}/delete', 'CategoryController@destroy')
->name('destroy');
});
});
Route::name('auth.')->namespace('Auth')->group(function () {
Route::get('login', 'LoginController@login')->name('login');

1
webpack.mix.js vendored
View File

@ -3,3 +3,4 @@ const mix = require('laravel-mix');
mix.js('resources/js/app.js', 'public/js');
mix.sass('resources/sass/app.scss', 'public/css');
mix.sass('resources/sass/dashboard.scss', 'public/css');