Commit 7c115bff1b6da3dd756680c7026e2086c20b26c3

Authored by Андрей Ларионов
1 parent 3a94dc815e
Exists in master

Админка - объекты недвижимости

Showing 15 changed files with 366 additions and 42 deletions Side-by-side Diff

app/Classes/RusDate.php
... ... @@ -68,7 +68,8 @@ class RusDate
68 68 }
69 69  
70 70 public static function clear_items() {
71   - unset($_COOKIE['favorite_house']);
  71 + if (!empty($_COOKIE['favorite_house']))
  72 + unset($_COOKIE['favorite_house']);
72 73 //print_r($_COOKIE['arr']);
73 74 }
74 75 }
app/Http/Controllers/Admin/AreaController.php
... ... @@ -3,8 +3,10 @@
3 3 namespace App\Http\Controllers\Admin;
4 4  
5 5 use App\Http\Controllers\Controller;
  6 +use App\Http\Requests\AreasRequest;
6 7 use App\Models\Area;
7 8 use Illuminate\Http\Request;
  9 +use Illuminate\Support\Facades\Storage;
8 10  
9 11 class AreaController extends Controller
10 12 {
... ... @@ -21,12 +23,12 @@ class AreaController extends Controller
21 23  
22 24 /**
23 25 * Show the form for creating a new resource.
24   - *
  26 + * Форма создания объекта
25 27 * @return \Illuminate\Http\Response
26 28 */
27 29 public function create()
28 30 {
29   - //
  31 + return view('admin.area.create');
30 32 }
31 33  
32 34  
... ... @@ -40,53 +42,73 @@ class AreaController extends Controller
40 42 * @param \Illuminate\Http\Request $request
41 43 * @return \Illuminate\Http\Response
42 44 */
43   - public function store(Request $request)
  45 + public function store(AreasRequest $request)
44 46 {
45   - //
  47 + $params = $request->all();
  48 + //unset($params['foto_main']);
  49 +
  50 + if ($request->has('foto_main')) {
  51 + $params['foto_main'] = $request->file('foto_main')->store('areas', 'public');
  52 + }
  53 +
  54 + Area::create($params);
  55 + return redirect()->route('admin.area.index');
46 56 }
47 57  
48 58 /**
49 59 * Display the specified resource.
50   - *
  60 + * Просмотр объекта недвижимости
51 61 * @param \App\Models\Area $area
52 62 * @return \Illuminate\Http\Response
53 63 */
54 64 public function show(Area $area)
55 65 {
56   - //
  66 + return view('admin.area.view', compact('area'));
57 67 }
58 68  
59 69 /**
60 70 * Show the form for editing the specified resource.
61   - *
  71 + * Форма редактирования объекта
62 72 * @param \App\Models\Area $area
63 73 * @return \Illuminate\Http\Response
64 74 */
65 75 public function edit(Area $area)
66 76 {
67   - //
  77 + return view('admin.area.edit', compact('area'));
68 78 }
69 79  
70 80 /**
71 81 * Update the specified resource in storage.
72   - *
  82 + * Обновление-сохранение объекта недвижимости
73 83 * @param \Illuminate\Http\Request $request
74 84 * @param \App\Models\Area $area
75 85 * @return \Illuminate\Http\Response
76 86 */
77   - public function update(Request $request, Area $area)
  87 + public function update(AreasRequest $request, Area $area)
78 88 {
79   - //
  89 + $params = $request->all();
  90 + unset($params['foto_main']);
  91 + if ($request->has('foto_main')) {
  92 + Storage::delete($area->foto_main);
  93 + $params['foto_main'] = $request->file('foto_main')->store('areas', 'public');
  94 + }
  95 +
  96 + $area->update($params);
  97 + return redirect()->route('admin.area.index');
80 98 }
81 99  
82 100 /**
83 101 * Remove the specified resource from storage.
84   - *
  102 + * Удаление объекта недвижимости
85 103 * @param \App\Models\Area $area
86 104 * @return \Illuminate\Http\Response
87 105 */
88 106 public function destroy(Area $area)
89 107 {
90   - //
  108 + if (!empty($area->foto_main)) {
  109 + Storage::delete($area->foto_main);
  110 + }
  111 + $area->delete();
  112 + return redirect()->route('admin.area.index');
91 113 }
92 114 }
app/Http/Controllers/AdminController.php
... ... @@ -10,6 +10,4 @@ class AdminController extends Controller
10 10 public function index() {
11 11 return view('admin.index');
12 12 }
13   -
14   - // страница
15 13 }
app/Http/Requests/AreasRequest.php
... ... @@ -0,0 +1,40 @@
  1 +<?php
  2 +
  3 +namespace App\Http\Requests;
  4 +
  5 +use Illuminate\Foundation\Http\FormRequest;
  6 +
  7 +class AreasRequest extends FormRequest
  8 +{
  9 + /**
  10 + * Determine if the user is authorized to make this request.
  11 + *
  12 + * @return bool
  13 + */
  14 + public function authorize()
  15 + {
  16 + return true;
  17 + }
  18 +
  19 + /**
  20 + * Get the validation rules that apply to the request.
  21 + *
  22 + * @return array<string, mixed>
  23 + */
  24 + public function rules()
  25 + {
  26 + return [
  27 + 'name_area' => 'required|min:3|max:255',
  28 + 'description' => 'required|min:5',
  29 + ];
  30 + }
  31 +
  32 + public function messages() {
  33 + return [
  34 + 'required' => 'Поле :attribute обязательно для ввода',
  35 + 'min' => 'Поле :attribute должно иметь минимум :min символов',
  36 + 'max' => 'Поле :attribute должно содержать не более :max символов'
  37 + ];
  38 + }
  39 +
  40 +}
... ... @@ -9,6 +9,9 @@ class Area extends Model
9 9 {
10 10 use HasFactory;
11 11  
  12 + protected $fillable = ['name_area', 'description', 'foto_main', 'coord_x', 'coord_y'];
  13 +
  14 +
12 15 /*
13 16 * Связь Объектов недвижимости с офисами
14 17 */
database/migrations/2023_03_01_072712_create_areas_table.php
... ... @@ -15,13 +15,13 @@ return new class extends Migration
15 15 {
16 16 Schema::create('areas', function (Blueprint $table) {
17 17 $table->id();
18   - $table->string('name_area', 255);
19   - $table->string('slug', 255)->unique();
20   - $table->text('description');
  18 + $table->string('name_area', 255)->nullable();
  19 + $table->string('slug', 255)->unique()->nullable();
  20 + $table->text('description')->nullable();
21 21 $table->string('map_coord')->default('');
22   - $table->float('coord_x')->default(0.0);
23   - $table->float('coord_y')->default(0.0);
24   - $table->string('foto_main', 255);
  22 + $table->integer('coord_x')->default(0);
  23 + $table->integer('coord_y')->default(0);
  24 + $table->string('foto_main', 255)->nullable();
25 25 $table->timestamps();
26 26 });
27 27 }
resources/views/admin/area/create.blade.php
... ... @@ -0,0 +1,25 @@
  1 +@extends('layout.admin', ['title' => 'Создание нового объекта'])
  2 +
  3 +@section('content')
  4 + <section class="favorites">
  5 + <div class="favorites-top">
  6 + <div class="container">
  7 + <div class="breadcrumbs">
  8 + <ul class="breadcrumbs__list">
  9 + <li class="breadcrumbs__item"><a class="breadcrumbs__link" href="{{ route('user.index') }}">Главная</a></li>
  10 + <li class="breadcrumbs__item"><a class="breadcrumbs__link" href="{{ route('admin.area.index') }}">Объекты недвижимости </a></li>
  11 + <li class="breadcrumbs__item"><span class="breadcrumbs__link">Создание объекта недвижимости </span></li>
  12 + </ul>
  13 + </div>
  14 + <h1 class="favorites__title title-main">Создание объекта недвижимости</h1>
  15 + </div>
  16 + </div>
  17 + <div class="favorites-cnt">
  18 + <div class="container">
  19 + <form method="post" enctype="multipart/form-data" action="{{ route('admin.area.store') }}" style="width:100%">
  20 + @include('admin.area.form')
  21 + </form>
  22 + </div>
  23 + </div>
  24 + </section>
  25 +@endsection
resources/views/admin/area/edit.blade.php
... ... @@ -0,0 +1,26 @@
  1 +@extends('layout.admin', ['title' => 'Изменение объекта'])
  2 +
  3 +@section('content')
  4 + <section class="favorites">
  5 + <div class="favorites-top">
  6 + <div class="container">
  7 + <div class="breadcrumbs">
  8 + <ul class="breadcrumbs__list">
  9 + <li class="breadcrumbs__item"><a class="breadcrumbs__link" href="{{ route('user.index') }}">Главная</a></li>
  10 + <li class="breadcrumbs__item"><a class="breadcrumbs__link" href="{{ route('admin.area.index') }}">Объекты недвижимости </a></li>
  11 + <li class="breadcrumbs__item"><span class="breadcrumbs__link">Изменение объекта недвижимости </span></li>
  12 + </ul>
  13 + </div>
  14 + <h1 class="favorites__title title-main">Изменение объекта недвижимости</h1>
  15 + </div>
  16 + </div>
  17 + <div class="favorites-cnt">
  18 + <div class="container">
  19 + <form method="post" enctype="multipart/form-data" action="{{ route('admin.area.update', ['area' => $area->id]) }}" style="width:100%">
  20 + @include('admin.area.form')
  21 + </form>
  22 + </div>
  23 + </div>
  24 + </section>
  25 +@endsection
  26 +
resources/views/admin/area/form.blade.php
... ... @@ -0,0 +1,45 @@
  1 +@csrf
  2 +
  3 +@isset($area)
  4 + @method('PUT')
  5 +@endisset
  6 +
  7 +<label for="name_area">Название объекта: <span class="req">*</span></label>
  8 +@error('name_area')
  9 +<div class="alert alert-danger">{{ $message }}</div>
  10 +@enderror
  11 +<input type="text" class="form-control_ txt" name="name_area" placeholder="Название объекта"
  12 + required maxlength="100" style="width: 80%" value="{{ old('name_area') ?? $area->name_area ?? '' }}"><br>
  13 +
  14 +<label for="description">Описание объекта: <span class="req">*</span></label>
  15 +@error('description')
  16 +<div class="alert alert-danger">{{ $message }}</div>
  17 +@enderror
  18 +<textarea class="form-control_ txtarea ckeditor" name="description" placeholder="Описание" required
  19 + rows="10" style="width: 80%">{{ old('description') ?? $area->description ?? '' }}</textarea><br>
  20 +
  21 +<label for="coord_X">Коорд. X: </label>
  22 +<input type="text" class="form-control_ txt" name="coord_X" placeholder="Координаты X"
  23 + required maxlength="100" value="{{ old('coord_x') ?? $area->coord_x ?? '' }}"><br>
  24 +
  25 +<label for="coord_Y">Коорд. Y: </label>
  26 +<input type="text" class="form-control_ txt" name="coord_Y" placeholder="Координаты Y"
  27 + required maxlength="100" value="{{ old('coord_y') ?? $area->coord_y ?? '' }}"><br>
  28 +
  29 +
  30 +<label for="foto_main">Файл-картинка:</label>
  31 +<input type="file" class="form-control-file txt" name="foto_main" id="foto_main" accept="image/png, image/jpeg">
  32 +
  33 +@isset($area->foto_main)
  34 + <div class="form-group form-check">
  35 + <img src="<?=asset(Storage::url($area->foto_main))?>" width="100px"/>
  36 + <input type="checkbox" class="form-check-input" name="remove" id="remove">
  37 + <label class="form-check-label" for="remove">
  38 + Удалить загруженное изображение
  39 + </label>
  40 + </div>
  41 +@endisset
  42 +<br><br>
  43 +<button type="submit" class="btn hero-search__btn btn--main">Сохранить</button>
  44 +
  45 +
resources/views/admin/area/index.blade.php
... ... @@ -15,32 +15,60 @@
15 15 </div>
16 16 <div class="favorites-cnt">
17 17 <div class="container">
  18 + <a href="{{ route('admin.area.create') }}" class="btn hero-search__btn btn--main">
  19 + Создать объект
  20 + </a><br><br>
18 21 <table class="table" style="width: 100%">
19 22 <thead>
20 23 <tr>
21   - <th>First Name</th>
22   - <th>Last Name</th>
23   - <th>ZIP</th>
24   - <th>Birthday</th>
25   - <th>Points</th>
26   - <th>Average</th>
27   - <th>Amount</th>
  24 + <th>Фото</th>
  25 + <th>ID</th>
  26 + <th>Название объекта</th>
  27 + <th>Координаты X</th>
  28 + <th>Координаты Y</th>
  29 + <th>Дата создания</th>
  30 + <th>Действия</th>
28 31 </tr>
29 32 </thead>
30 33 <tbody>
31   - <tr>
32   - <td>Gloria</td>
33   - <td>Reeves</td>
34   - <td>67439</td>
35   - <td>10/18/1985</td>
36   - <td>4</td>
37   - <td>0.1</td>
38   - <td>$50</td>
39   - </tr>
40   - ...
  34 + @if ($areas->count())
  35 + @foreach($areas as $area)
  36 + <tr>
  37 + <td><? if (empty($area->foto_main)) {?>Нет фото<?} else {?><img src="<?=asset(Storage::url($area->foto_main))?>" width="100px"/><?}?></td>
  38 + <td>{{ $area->id }}</td>
  39 + <td>{{ $area->name_area }}</td>
  40 + <td>{{ $area->coord_x }}</td>
  41 + <td>{{ $area->coord_y }}</td>
  42 + <td>{{ $area->created_at }}</td>
  43 + <td> <form action="{{ route('admin.area.destroy', $area) }}" method="POST">
  44 + <a style="color:green" href="{{ route('admin.area.show', ['area' => $area->id]) }}">
  45 + Просмотр
  46 + </a> |
  47 + <a href="{{ route('admin.area.edit', ['area' => $area->id]) }}">
  48 + Редактировать
  49 + </a> |
  50 + @csrf
  51 + @method('DELETE')
  52 + <input class=" btn-danger" type="submit" value="Удалить">
  53 + </form>
  54 + </td>
  55 + </tr>
  56 + @endforeach
  57 + @else
  58 + <tr>
  59 + <td>-</td>
  60 + <td>-</td>
  61 + <td>-</td>
  62 + <td>-</td>
  63 + <td>-</td>
  64 + <td>-</td>
  65 + <td>-</td>
  66 + </tr>
  67 + @endif
  68 +
41 69 </tbody>
42 70 </table>
43   -
  71 + {{ $areas->onEachSide(1)->links('catalogs.paginate') }}
44 72 <div class="favorites__items">
45 73  
46 74  
resources/views/admin/area/view.blade.php
... ... @@ -0,0 +1,48 @@
  1 +@extends('layout.admin', ['title' => 'Просмотр объекта'])
  2 +
  3 +@section('content')
  4 + <section class="favorites">
  5 + <div class="favorites-top">
  6 + <div class="container">
  7 + <div class="breadcrumbs">
  8 + <ul class="breadcrumbs__list">
  9 + <li class="breadcrumbs__item"><a class="breadcrumbs__link" href="{{ route('user.index') }}">Главная</a></li>
  10 + <li class="breadcrumbs__item"><a class="breadcrumbs__link" href="{{ route('admin.area.index') }}">Объекты недвижимости </a></li>
  11 + <li class="breadcrumbs__item"><span class="breadcrumbs__link">Просмотр объекта недвижимости </span></li>
  12 + </ul>
  13 + </div>
  14 + <h1 class="favorites__title title-main">Просмотр объекта недвижимости</h1>
  15 + </div>
  16 + </div>
  17 + <div class="favorites-cnt">
  18 + <div class="container">
  19 + <label for="name_area">Название объекта: <span class="req">*</span></label><br>
  20 + <input type="text" class="form-control_ txt" name="name_area" placeholder="Название объекта"
  21 + required maxlength="100" style="width: 80%" value="{{ old('name_area') ?? $area->name_area ?? '' }}"><br><br>
  22 +
  23 + <label for="description">Описание объекта: <span class="req">*</span></label><br>
  24 + <textarea class="form-control_ txtarea ckeditor" name="description" placeholder="Описание" required
  25 + rows="10" style="width: 80%">{{ old('description') ?? $area->description ?? '' }}</textarea><br><br>
  26 +
  27 + <label for="coord_X">Коорд. X: </label><br>
  28 + <input type="text" class="form-control_ txt" name="coord_X" placeholder="Координаты X"
  29 + required maxlength="100" value="{{ old('coord_x') ?? $area->coord_x ?? '' }}"><br><br>
  30 +
  31 + <label for="coord_Y">Коорд. Y: </label><br>
  32 + <input type="text" class="form-control_ txt" name="coord_Y" placeholder="Координаты Y"
  33 + required maxlength="100" value="{{ old('coord_y') ?? $area->coord_y ?? '' }}"><br><br>
  34 +
  35 +
  36 + <label for="foto_main">Файл-картинка:</label><br>
  37 + @isset($area->foto_main)
  38 + <div class="form-group form-check">
  39 + <img src="<?=asset(Storage::url($area->foto_main))?>" width="100px"/>
  40 + </div>
  41 + @endisset
  42 + <br>
  43 + <a href="{{ route('admin.area.index') }}" class="btn hero-search__btn btn--main">Вернуться к объектам</a>
  44 + </div>
  45 + </div>
  46 + </section>
  47 +@endsection
  48 +
resources/views/admin/index.blade.php
... ... @@ -19,7 +19,7 @@
19 19 <h2>Меню</h2>
20 20 <ul class="breadcrumbs__list">
21 21 <li class="breadcrumbs__item"><a class="breadcrumbs__link" href="{{ route('index') }}">Сайт</a></li>
22   - <li class="breadcrumbs__item"><a class="breadcrumbs__link" href="{{ route('user.index') }}">Главная (админкв) </a></li>
  22 + <li class="breadcrumbs__item"><a class="breadcrumbs__link" href="{{ route('admin.area.index') }}">Объекты </a></li>
23 23 </ul>
24 24 </div>
25 25 </div>
resources/views/auth/vefiry-message.blade.php
... ... @@ -0,0 +1,23 @@
  1 +@extends('layout.site', ['title' => 'Неудачный вход в личный кабинет'])
  2 +
  3 +@section('content')
  4 + <section class="favorites">
  5 + <div class="favorites-top">
  6 + <div class="container">
  7 +
  8 + <div class="footer-top">
  9 + <div class="container">
  10 + <div class="footer-feedback">
  11 + <div class="footer-feedback__cnt">
  12 + <h2 class="footer-feedback__title title">Вход в личный кабинет не удался!</h2>
  13 + <p class="footer-feedback__descr">Обратитесь к администратору за правами!</p>
  14 + </div>
  15 +
  16 + </div>
  17 + </div>
  18 + </div>
  19 +
  20 + </div>
  21 + </div>
  22 + </section>
  23 +@endsection
resources/views/layout/admin.blade.php
... ... @@ -15,6 +15,65 @@
15 15 <link rel="stylesheet" href="{{ asset('css/swiper-bundle.min.css') }}">
16 16 <link rel="stylesheet" href="{{ asset('css/style.css') }}">
17 17 <link rel="stylesheet" href="{{ asset('css/style_table.css') }}">
  18 + <style>
  19 + /* form styles */
  20 + form .row {
  21 + display: block;
  22 + padding: 7px 8px;
  23 + margin-bottom: 7px;
  24 + }
  25 + form .row:hover {
  26 + background: #f1f7fa;
  27 + }
  28 +
  29 + form label {
  30 + display: inline-block;
  31 + font-size: 1.2em;
  32 + font-weight: bold;
  33 + width: 120px;
  34 + padding: 6px 0;
  35 + color: #464646;
  36 + vertical-align: top;
  37 + }
  38 + form .req { color: #ca5354; }
  39 +
  40 + form .note {
  41 + font-size: 1.2em;
  42 + line-height: 1.33em;
  43 + font-weight: normal;
  44 + padding: 2px 7px;
  45 + margin-bottom: 10px;
  46 + }
  47 +
  48 + form input:focus, form textarea:focus { outline: none; }
  49 +
  50 + /* placeholder styles: http://stackoverflow.com/a/2610741/477958 */
  51 + ::-webkit-input-placeholder { color: #aaafbd; font-style: italic; } /* WebKit */
  52 + :-moz-placeholder { color: #aaafbd; font-style: italic; } /* Mozilla Firefox 4 to 18 */
  53 + ::-moz-placeholder { color: #aaafbd; font-style: italic; } /* Mozilla Firefox 19+ */
  54 + :-ms-input-placeholder { color: #aaafbd; font-style: italic; } /* Internet Explorer 10+ */
  55 +
  56 + form .txt {
  57 + display: inline-block;
  58 + padding: 8px 9px;
  59 + padding-right: 30px;
  60 + width: 240px;
  61 + font-family: 'Oxygen', sans-serif;
  62 + font-size: 1.35em;
  63 + font-weight: normal;
  64 + color: #898989;
  65 + }
  66 +
  67 + form .txtarea {
  68 + display: inline-block;
  69 + padding: 8px 9px;
  70 + padding-right: 30px;
  71 + font-family: 'Oxygen', sans-serif;
  72 + font-size: 1.35em;
  73 + font-weight: normal;
  74 + color: #898989;
  75 + }
  76 + </style>
18 77 </head>
19 78 <body>
20 79 <div class="spinner"></div>
... ... @@ -24,7 +83,7 @@
24 83 <div class="header__wrap"><a class="header__logo" href="{{ route('index') }}"><img src="{{ asset('images/logo.svg') }}" alt="Лого"></a>
25 84 <nav class="header__nav nav">
26 85 <ul class="nav__list">
27   - <li class="nav__item"><a class="nav__link" href="{{ route('catalog') }}">Каталог</a></li>
  86 + <li class="nav__item"><a class="nav__link" href="{{ route('admin.area.index') }}">Объекты</a></li>
28 87 <li class="nav__item"><a class="nav__link" href="{{ route('about') }}">О компании</a></li>
29 88 <li class="nav__item"><a class="nav__link" href="{{ route('contact') }}">Контакты</a></li>
30 89 <li class="nav__item"><a class="nav__link nav__link-favorites" href="{{ route('favorite') }}">Избранное<span><?=\App\Classes\RusDate::count_item_fav();?></span></a></li>
... ... @@ -100,6 +100,12 @@ Route::group([
100 100  
101 101 // выход
102 102 Route::get('logout', [LoginController::class, 'logout'])->name('logout');
  103 +
  104 +//Страница неудачной авторизации
  105 + Route::get('vefiry-message', function () {
  106 + return view('auth.vefiry-message');
  107 + })->name('vefiry-message');
  108 +
103 109 });
104 110  
105 111 /*