From 6eff6bf11b34d00d6952359357d9727fe5737383 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D0=B4=D1=80=D0=B5=D0=B9=20=20=D0=9B=D0=B0=D1=80?= =?UTF-8?q?=D0=B8=D0=BE=D0=BD=D0=BE=D0=B2?= Date: Tue, 4 Apr 2023 20:26:20 +0700 Subject: [PATCH] =?UTF-8?q?=D0=90=D0=B4=D0=BC=D0=B8=D0=BD=D0=BA=D0=B0=20=D1=81?= =?UTF-8?q?=D0=B0=D0=B9=D1=82=D0=B0=20=D0=BA=D0=B0=D1=82=D0=B5=D0=B3=D0=BE=D1?= =?UTF-8?q?=80=D0=B8=D0=B8,=20=D0=B1=D0=B0=D0=BD=D0=BD=D0=B5=D1=80=D1=8B,=20?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2=D0=BE=D1=81=D1=82=D0=B8,=20=D0=BF=D1=80=D0=BE=D0?= =?UTF-8?q?=B5=D0=BA=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Admin/BannerController.php | 11 +-- app/Http/Controllers/Admin/CategoryController.php | 38 +++++++++-- app/Http/Controllers/Admin/NewsController.php | 67 +++++++++++++++++-- app/Http/Controllers/Admin/ProjectController.php | 74 +++++++++++++++++++-- app/Http/Requests/CategoryRequest.php | 51 ++++++++++++++ app/Models/Category.php | 2 + app/Providers/ComposerServiceProvider.php | 57 ++++++++++++++++ config/app.php | 1 + resources/views/admin/banners/create.blade.php | 15 +++++ resources/views/admin/banners/edit.blade.php | 14 ++++ resources/views/admin/banners/form.blade.php | 37 +++++++++++ resources/views/admin/banners/index.blade.php | 5 +- resources/views/admin/category/create.blade.php | 15 +++++ resources/views/admin/category/edit.blade.php | 14 ++++ resources/views/admin/category/form.blade.php | 51 ++++++++++++++ resources/views/admin/category/index.blade.php | 64 ++++++++++++++++++ resources/views/admin/news/create.blade.php | 15 +++++ resources/views/admin/news/edit.blade.php | 14 ++++ resources/views/admin/news/form.blade.php | 37 +++++++++++ resources/views/admin/news/index.blade.php | 64 ++++++++++++++++++ resources/views/admin/part/parents.blade.php | 10 +++ resources/views/admin/projects/create.blade.php | 15 +++++ resources/views/admin/projects/edit.blade.php | 14 ++++ resources/views/admin/projects/form.blade.php | 46 +++++++++++++ resources/views/admin/projects/index.blade.php | 64 ++++++++++++++++++ resources/views/layout/admin.blade.php | 12 ++-- 26 files changed, 777 insertions(+), 30 deletions(-) create mode 100644 app/Http/Requests/CategoryRequest.php create mode 100644 app/Providers/ComposerServiceProvider.php create mode 100644 resources/views/admin/category/create.blade.php create mode 100644 resources/views/admin/category/edit.blade.php create mode 100644 resources/views/admin/category/form.blade.php create mode 100644 resources/views/admin/category/index.blade.php create mode 100644 resources/views/admin/news/create.blade.php create mode 100644 resources/views/admin/news/edit.blade.php create mode 100644 resources/views/admin/news/form.blade.php create mode 100644 resources/views/admin/news/index.blade.php create mode 100644 resources/views/admin/part/parents.blade.php create mode 100644 resources/views/admin/projects/create.blade.php create mode 100644 resources/views/admin/projects/edit.blade.php create mode 100644 resources/views/admin/projects/form.blade.php create mode 100644 resources/views/admin/projects/index.blade.php diff --git a/app/Http/Controllers/Admin/BannerController.php b/app/Http/Controllers/Admin/BannerController.php index ac6a5b0..d7e1936 100644 --- a/app/Http/Controllers/Admin/BannerController.php +++ b/app/Http/Controllers/Admin/BannerController.php @@ -84,7 +84,7 @@ class BannerController extends Controller */ public function edit(Banner $banner) { - return view('admin.banners.edit', compact($banner)); + return view('admin.banners.edit', compact('banner')); } /** @@ -97,16 +97,19 @@ class BannerController extends Controller public function update(Request $request, Banner $banner) { $rules = [ - 'image' => 'required|min:3|max:10000', 'title' => 'required|min:3|max:255' ]; + + if (empty($banner->image)) { + $rules['image'] = 'required|min:3|max:10000'; + } $messages = [ 'required' => 'Поле не может быть пустым!', ]; $validator = Validator::make($request->all(), $rules, $messages); if ($validator->fails()) { - return redirect()->route('admin.banner.edit') + return redirect()->route('admin.banner.edit', ['banner' => $banner->id]) ->withErrors($validator); } else { $params = $request->all(); @@ -132,7 +135,7 @@ class BannerController extends Controller if (!empty($banner->image)) { Storage::delete($banner->image); } - $image->delete(); + $banner->delete(); return redirect()->route('admin.banner.index'); } } diff --git a/app/Http/Controllers/Admin/CategoryController.php b/app/Http/Controllers/Admin/CategoryController.php index 4577d73..de60ac9 100644 --- a/app/Http/Controllers/Admin/CategoryController.php +++ b/app/Http/Controllers/Admin/CategoryController.php @@ -3,8 +3,10 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; +use App\Http\Requests\CategoryRequest; use App\Models\Category; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Storage; class CategoryController extends Controller { @@ -15,7 +17,8 @@ class CategoryController extends Controller */ public function index() { - // + $categories = Category::query()->orderBy('id')->paginate(5); + return view('admin.category.index', compact('categories')); } /** @@ -25,7 +28,7 @@ class CategoryController extends Controller */ public function create() { - // + return view('admin.category.create'); } /** @@ -34,9 +37,16 @@ class CategoryController extends Controller * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ - public function store(Request $request) + public function store(CategoryRequest $request) { - // + $params = $request->all(); + + if ($request->has('image')) { + $params['image'] = $request->file('image')->store('category', 'public'); + } + + Category::create($params); + return redirect()->route('admin.category.index'); } /** @@ -58,7 +68,7 @@ class CategoryController extends Controller */ public function edit(Category $category) { - // + return view('admin.category.edit', compact('category')); } /** @@ -70,7 +80,17 @@ class CategoryController extends Controller */ public function update(Request $request, Category $category) { - // + $params = $request->all(); + + if ($request->has('image')) { + Storage::delete($category->image); + $params['image'] = $request->file('image')->store('category', 'public'); + } else { + if (!empty($category->image)) $params['image'] = $category->image; + } + + $category->update($params); + return redirect()->route('admin.category.index'); } /** @@ -81,6 +101,10 @@ class CategoryController extends Controller */ public function destroy(Category $category) { - // + if (!empty($category->image)) { + Storage::delete($category->image); + } + $category->delete(); + return redirect()->route('admin.category.index'); } } diff --git a/app/Http/Controllers/Admin/NewsController.php b/app/Http/Controllers/Admin/NewsController.php index 2b3e596..1f5f847 100644 --- a/app/Http/Controllers/Admin/NewsController.php +++ b/app/Http/Controllers/Admin/NewsController.php @@ -4,7 +4,10 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; use App\Models\News; +use Illuminate\Database\Eloquent\Model; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Storage; +use Illuminate\Support\Facades\Validator; class NewsController extends Controller { @@ -15,7 +18,8 @@ class NewsController extends Controller */ public function index() { - // + $news = News::query()->orderBy('id')->paginate(5); + return view('admin.news.index', compact('news')); } /** @@ -25,7 +29,7 @@ class NewsController extends Controller */ public function create() { - // + return view('admin.news.create'); } /** @@ -36,7 +40,29 @@ class NewsController extends Controller */ public function store(Request $request) { - // + $rules = [ + 'image' => 'required|min:3|max:10000', + 'title' => 'required|min:3|max:255', + ]; + $messages = [ + 'required' => 'Поле не может быть пустым!', + ]; + $validator = Validator::make($request->all(), $rules, $messages); + + if ($validator->fails()) { + return redirect()->route('admin.news.create') + ->withErrors($validator); + } else { + + $news = new News(); + $news->title = $request->title; + $news->text = $request->text; + $news->image = $request->file('image')->store('news', 'public'); + $news->save(); + + //$area->fotos()->save($foto_area); + return redirect()->route('admin.news.index'); + } } /** @@ -58,7 +84,7 @@ class NewsController extends Controller */ public function edit(News $news) { - // + return view('admin.news.edit', compact('news')); } /** @@ -70,7 +96,32 @@ class NewsController extends Controller */ public function update(Request $request, News $news) { - // + $rules = [ + 'title' => 'required|min:3|max:255' + ]; + + if (empty($news->image)) { + $rules['image'] = 'required|min:3|max:10000'; + } + $messages = [ + 'required' => 'Поле не может быть пустым!', + ]; + $validator = Validator::make($request->all(), $rules, $messages); + + if ($validator->fails()) { + return redirect()->route('admin.news.edit', ['news' => $news->id]) + ->withErrors($validator); + } else { + $params = $request->all(); + unset($params['image']); + if ($request->has('image')) { + Storage::delete($news->image); + $params['image'] = $request->file('image')->store('news', 'public'); + } + + $news->update($params); + return redirect()->route('admin.news.index'); + } } /** @@ -81,6 +132,10 @@ class NewsController extends Controller */ public function destroy(News $news) { - // + if (!empty($news->image)) { + Storage::delete($news->image); + } + $news->delete(); + return redirect()->route('admin.news.index'); } } diff --git a/app/Http/Controllers/Admin/ProjectController.php b/app/Http/Controllers/Admin/ProjectController.php index 580168b..1bd0ea2 100644 --- a/app/Http/Controllers/Admin/ProjectController.php +++ b/app/Http/Controllers/Admin/ProjectController.php @@ -4,7 +4,10 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; use App\Models\Project; +use Illuminate\Database\Eloquent\Model; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Storage; +use Illuminate\Support\Facades\Validator; class ProjectController extends Controller { @@ -15,7 +18,8 @@ class ProjectController extends Controller */ public function index() { - // + $projects = Project::query()->orderBy('id')->paginate(5); + return view('admin.projects.index', compact('projects')); } /** @@ -25,7 +29,7 @@ class ProjectController extends Controller */ public function create() { - // + return view('admin.projects.create'); } /** @@ -36,7 +40,33 @@ class ProjectController extends Controller */ public function store(Request $request) { - // + $rules = [ + 'image' => 'required|min:3|max:10000', + 'title' => 'required|min:3|max:255', + 'customer' => 'required|min:3|max:255', + 'date_project' => 'required|min:3|max:255|date_format:d.m.Y', + ]; + $messages = [ + 'required' => 'Поле не может быть пустым!', + 'date' => 'Поле должно быть формата дата', + ]; + $validator = Validator::make($request->all(), $rules, $messages); + + if ($validator->fails()) { + return redirect()->route('admin.project.create') + ->withErrors($validator); + } else { + + $Project = new Project(); + $Project->title = $request->title; + $Project->customer = $request->customer; + $Project->date_project = date("Y-m-d", strtotime($request->date_project)); + $Project->image = $request->file('image')->store('project', 'public'); + $Project->save(); + + //$area->fotos()->save($foto_area); + return redirect()->route('admin.project.index'); + } } /** @@ -58,7 +88,7 @@ class ProjectController extends Controller */ public function edit(Project $project) { - // + return view('admin.projects.edit', compact('project')); } /** @@ -70,7 +100,35 @@ class ProjectController extends Controller */ public function update(Request $request, Project $project) { - // + $rules = [ + 'title' => 'required|min:3|max:255', + 'customer' => 'required|min:3|max:255', + 'date_project' => 'required|min:3|max:255|date_format:d.m.Y', + ]; + + if (empty($project->image)) { + $rules['image'] = 'required|min:3|max:10000'; + } + $messages = [ + 'required' => 'Поле не может быть пустым!', + ]; + + $validator = Validator::make($request->all(), $rules, $messages); + + if ($validator->fails()) { + return redirect()->route('admin.project.edit', ['project' => $project->id]) + ->withErrors($validator); + } else { + $params = $request->all(); + unset($params['image']); + if ($request->has('image')) { + Storage::delete($project->image); + $params['image'] = $request->file('image')->store('project', 'public'); + } + + $project->update($params); + return redirect()->route('admin.project.index'); + } } /** @@ -81,6 +139,10 @@ class ProjectController extends Controller */ public function destroy(Project $project) { - // + if (!empty($project->image)) { + Storage::delete($project->image); + } + $project->delete(); + return redirect()->route('admin.project.index'); } } diff --git a/app/Http/Requests/CategoryRequest.php b/app/Http/Requests/CategoryRequest.php new file mode 100644 index 0000000..8d69aa9 --- /dev/null +++ b/app/Http/Requests/CategoryRequest.php @@ -0,0 +1,51 @@ + + */ + public function rules() + { + return [ + 'name' => 'required|min:3|max:255', + //'description' => 'required|min:5', + 'image' => [ + 'mimes:jpeg,jpg,png', + 'max:10000' + ], + ]; + } + + public function messages() { + return [ + 'required' => 'Поле :attribute обязательно для ввода', + 'min' => [ + 'string' => 'Поле «:attribute» должно быть не меньше :min символов', + 'file' => 'Файл «:attribute» должен быть не меньше :min Кбайт' + ], + 'max' => [ + 'string' => 'Поле «:attribute» должно быть не больше :max символов', + 'file' => 'Файл «:attribute» должен быть не больше :max Кбайт' + ], + + ]; + } + +} diff --git a/app/Models/Category.php b/app/Models/Category.php index c9d6222..c33148f 100644 --- a/app/Models/Category.php +++ b/app/Models/Category.php @@ -8,4 +8,6 @@ use Illuminate\Database\Eloquent\Model; class Category extends Model { use HasFactory; + + protected $fillable = ['name', 'image', 'content', 'parent_id']; } diff --git a/app/Providers/ComposerServiceProvider.php b/app/Providers/ComposerServiceProvider.php new file mode 100644 index 0000000..1340da8 --- /dev/null +++ b/app/Providers/ComposerServiceProvider.php @@ -0,0 +1,57 @@ +with(['items' => $items]); + }); + } + + /** + * Bootstrap services. + * + * @return void + */ + public function boot() + { + View::composer('layout.part.categories', + function($view) + { + static $items = null; + + if (is_null($items)) { + $items = Category::all(); + $parent = 0; + $view->with(['items' => $items, 'parent' => $parent]); + } else { + $view->with(['items' => $items]); + } + + } + ); + } +} diff --git a/config/app.php b/config/app.php index ef76a7e..461276f 100644 --- a/config/app.php +++ b/config/app.php @@ -194,6 +194,7 @@ return [ // App\Providers\BroadcastServiceProvider::class, App\Providers\EventServiceProvider::class, App\Providers\RouteServiceProvider::class, + App\Providers\ComposerServiceProvider::class, ], diff --git a/resources/views/admin/banners/create.blade.php b/resources/views/admin/banners/create.blade.php index e69de29..04713c5 100644 --- a/resources/views/admin/banners/create.blade.php +++ b/resources/views/admin/banners/create.blade.php @@ -0,0 +1,15 @@ +@extends('layout.admin', ['title' => 'Создание баннера']) + +@section('content') +
+
+ + + +
+
+@endsection diff --git a/resources/views/admin/banners/edit.blade.php b/resources/views/admin/banners/edit.blade.php index e69de29..010df75 100644 --- a/resources/views/admin/banners/edit.blade.php +++ b/resources/views/admin/banners/edit.blade.php @@ -0,0 +1,14 @@ +@extends('layout.admin', ['title' => 'Редактирование баннера']) + +@section('content') +
+
+ + +
+
+@endsection diff --git a/resources/views/admin/banners/form.blade.php b/resources/views/admin/banners/form.blade.php index e69de29..d3c6ca9 100644 --- a/resources/views/admin/banners/form.blade.php +++ b/resources/views/admin/banners/form.blade.php @@ -0,0 +1,37 @@ +@csrf + +@isset($banner) + @method('PUT') +@endisset + +
+@error('title') +
{{ $message }}
+@enderror +

+ +
+@error('text') +
{{ $message }}
+@enderror +

+ + +
+ +@isset($banner->image) +
+ +
+@endisset + +< diff --git a/resources/views/admin/banners/index.blade.php b/resources/views/admin/banners/index.blade.php index 188fef9..698740b 100644 --- a/resources/views/admin/banners/index.blade.php +++ b/resources/views/admin/banners/index.blade.php @@ -1,9 +1,12 @@ -@extends('layout.admin', ['title' => 'Профиль пользователя']) +@extends('layout.admin', ['title' => 'Баннеры']) @section('content')
+


diff --git a/resources/views/admin/category/create.blade.php b/resources/views/admin/category/create.blade.php new file mode 100644 index 0000000..9f6d019 --- /dev/null +++ b/resources/views/admin/category/create.blade.php @@ -0,0 +1,15 @@ +@extends('layout.admin', ['title' => 'Создание категории']) + +@section('content') +
+
+ + + +
+
+@endsection diff --git a/resources/views/admin/category/edit.blade.php b/resources/views/admin/category/edit.blade.php new file mode 100644 index 0000000..a98d783 --- /dev/null +++ b/resources/views/admin/category/edit.blade.php @@ -0,0 +1,14 @@ +@extends('layout.admin', ['title' => 'Редактирование категории']) + +@section('content') +
+
+ + +
+
+@endsection diff --git a/resources/views/admin/category/form.blade.php b/resources/views/admin/category/form.blade.php new file mode 100644 index 0000000..57698e0 --- /dev/null +++ b/resources/views/admin/category/form.blade.php @@ -0,0 +1,51 @@ +@csrf + +@isset($category) + @method('PUT') +@endisset + +
+@error('name') +
{{ $message }}
+@enderror +

+ +
+@error('content') +
{{ $message }}
+@enderror +

+ + +
+ +@isset($category->image) +
+ +
+@endisset + +
+ +
+ @php + $parent_id = old('parent_id') ?? $category->parent_id ?? 0; + @endphp + +
+ +< diff --git a/resources/views/admin/category/index.blade.php b/resources/views/admin/category/index.blade.php new file mode 100644 index 0000000..b01d138 --- /dev/null +++ b/resources/views/admin/category/index.blade.php @@ -0,0 +1,64 @@ +@extends('layout.admin', ['title' => 'Категории']) + +@section('content') +
+
+
+

+ + + + + + + + + + + + + @if ($categories->count()) + @foreach($categories as $category) + + + + + + + + + @endforeach + @else + + + + + + + + @endif + + +
IDФотоЗаголовокДата созданияДействия
{{ $category->id }}image)) {?>Нет фото + + + {{ $category->name }}{{ $category->created_at }}
+ + Редактировать + | + @csrf + @method('DELETE') + +
+
-----
+ + {{ $categories->onEachSide(1)->links('catalogs.paginate') }} + +
+
+

+@endsection diff --git a/resources/views/admin/news/create.blade.php b/resources/views/admin/news/create.blade.php new file mode 100644 index 0000000..edf61fb --- /dev/null +++ b/resources/views/admin/news/create.blade.php @@ -0,0 +1,15 @@ +@extends('layout.admin', ['title' => 'Создание новости']) + +@section('content') +
+
+ + + +
+
+@endsection diff --git a/resources/views/admin/news/edit.blade.php b/resources/views/admin/news/edit.blade.php new file mode 100644 index 0000000..5e67d4c --- /dev/null +++ b/resources/views/admin/news/edit.blade.php @@ -0,0 +1,14 @@ +@extends('layout.admin', ['title' => 'Редактирование новости']) + +@section('content') +
+
+ + +
+
+@endsection diff --git a/resources/views/admin/news/form.blade.php b/resources/views/admin/news/form.blade.php new file mode 100644 index 0000000..8b90e2b --- /dev/null +++ b/resources/views/admin/news/form.blade.php @@ -0,0 +1,37 @@ +@csrf + +@isset($news) + @method('PUT') +@endisset + +
+@error('title') +
{{ $message }}
+@enderror +

+ +
+@error('text') +
{{ $message }}
+@enderror +

+ + +
+ +@isset($news->image) +
+ +
+@endisset + +< diff --git a/resources/views/admin/news/index.blade.php b/resources/views/admin/news/index.blade.php new file mode 100644 index 0000000..73b6ff9 --- /dev/null +++ b/resources/views/admin/news/index.blade.php @@ -0,0 +1,64 @@ +@extends('layout.admin', ['title' => 'Новости']) + +@section('content') +
+
+
+

+ + + + + + + + + + + + + @if ($news->count()) + @foreach($news as $new) + + + + + + + + + @endforeach + @else + + + + + + + + @endif + + +
IDФотоЗаголовокДата созданияДействия
{{ $new->id }}image)) {?>Нет фото + + + {{ $new->title }}{{ $new->created_at }}
+ + Редактировать + | + @csrf + @method('DELETE') + +
+
-----
+ + {{ $news->onEachSide(1)->links('catalogs.paginate') }} + +
+
+

+@endsection diff --git a/resources/views/admin/part/parents.blade.php b/resources/views/admin/part/parents.blade.php new file mode 100644 index 0000000..63d5df6 --- /dev/null +++ b/resources/views/admin/part/parents.blade.php @@ -0,0 +1,10 @@ +@if ($items->where('parent_id', $parent)->count()) + @php $level++ @endphp + @foreach ($items->where('parent_id', $parent) as $item) + + @include('admin.part.parents', ['level' => $level, 'parent' => $item->id]) + @endforeach +@endif diff --git a/resources/views/admin/projects/create.blade.php b/resources/views/admin/projects/create.blade.php new file mode 100644 index 0000000..868c297 --- /dev/null +++ b/resources/views/admin/projects/create.blade.php @@ -0,0 +1,15 @@ +@extends('layout.admin', ['title' => 'Создание проекта']) + +@section('content') +
+
+ + + +
+
+@endsection diff --git a/resources/views/admin/projects/edit.blade.php b/resources/views/admin/projects/edit.blade.php new file mode 100644 index 0000000..f55684d --- /dev/null +++ b/resources/views/admin/projects/edit.blade.php @@ -0,0 +1,14 @@ +@extends('layout.admin', ['title' => 'Редактирование проекта']) + +@section('content') +
+
+ + +
+
+@endsection diff --git a/resources/views/admin/projects/form.blade.php b/resources/views/admin/projects/form.blade.php new file mode 100644 index 0000000..93513e4 --- /dev/null +++ b/resources/views/admin/projects/form.blade.php @@ -0,0 +1,46 @@ + +@csrf + +@isset($project) + @method('PUT') +@endisset + +
+@error('title') +
{{ $message }}
+@enderror +

+ +
+@error('customer') +
{{ $message }}
+@enderror +

+ +
+@error('date_project') +
{{ $message }}
+@enderror +

+ +
+ +@isset($project->image) +
+ +
+@endisset + +< diff --git a/resources/views/admin/projects/index.blade.php b/resources/views/admin/projects/index.blade.php new file mode 100644 index 0000000..0710e2d --- /dev/null +++ b/resources/views/admin/projects/index.blade.php @@ -0,0 +1,64 @@ +@extends('layout.admin', ['title' => 'Проекты']) + +@section('content') +
+
+
+

+ + + + + + + + + + + + + @if ($projects->count()) + @foreach($projects as $project) + + + + + + + + + @endforeach + @else + + + + + + + + @endif + + +
IDФотоЗаголовокДата созданияДействия
{{ $project->id }}image)) {?>Нет фото + + + {{ $project->title }}{{ $project->created_at }}
+ + Редактировать + | + @csrf + @method('DELETE') + +
+
-----
+ + {{ $projects->onEachSide(1)->links('catalogs.paginate') }} + +
+
+

+@endsection diff --git a/resources/views/layout/admin.blade.php b/resources/views/layout/admin.blade.php index f0dbaa2..daf3739 100644 --- a/resources/views/layout/admin.blade.php +++ b/resources/views/layout/admin.blade.php @@ -443,13 +443,13 @@ Личный кабинет