Added place edit function
This commit is contained in:
@@ -60,22 +60,37 @@ class PlacesController extends Controller
|
|||||||
return str_replace([',',' '], ['|',''], $gps);
|
return str_replace([',',' '], ['|',''], $gps);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function edit(Place $place): VIEW
|
public function edit(int $id): VIEW
|
||||||
{
|
{
|
||||||
|
$place = Place::find($id);
|
||||||
return view('places.edit', compact('place'));
|
return view('places.edit', compact('place'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update(Request $request, Place $place): Redirector|RedirectResponse
|
public function update(Request $request, int $id)
|
||||||
{
|
{
|
||||||
$data = $request->validate([
|
// Очистка телефона от маски перед валидацией
|
||||||
'name' => 'required|string|max:255',
|
if ($request->filled('phone')) {
|
||||||
'lat' => 'required|numeric',
|
$request->merge(['phone' => preg_replace('/\D/', '', $request->phone)]);
|
||||||
'lng' => 'required|numeric',
|
}
|
||||||
|
|
||||||
|
$validated = $request->validate([
|
||||||
|
'name' => 'required|max:512',
|
||||||
|
'address' => 'nullable|max:512',
|
||||||
|
'phone' => 'nullable|digits:11',
|
||||||
|
'gps' => [
|
||||||
|
'nullable',
|
||||||
|
'regex:/^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$/'
|
||||||
|
],
|
||||||
|
'url' => 'nullable|url|max:255',
|
||||||
|
'description' => 'nullable',
|
||||||
]);
|
]);
|
||||||
$place->update($data);
|
|
||||||
|
$place = Place::findOrFail($id);
|
||||||
|
$place->update($validated);
|
||||||
|
|
||||||
return redirect()
|
return redirect()
|
||||||
->route('places.index')
|
->route('places.index')
|
||||||
->with('status', 'Обновлено!');
|
->with('success', 'Данные обновлены');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete(int $id): Redirector|RedirectResponse
|
public function delete(int $id): Redirector|RedirectResponse
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('places', function (Blueprint $create) {
|
||||||
|
$create->id();
|
||||||
|
|
||||||
|
// Основные поля
|
||||||
|
$create->string('name', 512)->nullable();
|
||||||
|
$create->string('address', 512)->nullable();
|
||||||
|
$create->string('phone', 128)->nullable();
|
||||||
|
$create->string('gps', 512)->nullable();
|
||||||
|
$create->string('url', 255)->nullable();
|
||||||
|
$create->text('description')->nullable();
|
||||||
|
|
||||||
|
// Даты (Laravel по умолчанию использует timestamp,
|
||||||
|
// но здесь приведены к вашему формату datetime)
|
||||||
|
$create->datetime('created_at')->useCurrent();
|
||||||
|
$create->datetime('updated_at')->useCurrent()->useCurrentOnUpdate();
|
||||||
|
$create->softDeletes(); // Это поле deleted_at
|
||||||
|
|
||||||
|
// Индексы с ограничением длины (как в вашем SQL)
|
||||||
|
$create->index([DB::raw('name(255)')], 'idx_name');
|
||||||
|
$create->index([DB::raw('gps(255)')], 'idx_gps');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('places');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<!-- Кнопка назад -->
|
||||||
|
<div class="mb-3 d-flex justify-content-between align-items-center">
|
||||||
|
<a href="{{ route('places.index') }}" class="text-decoration-none text-dark fw-bold">
|
||||||
|
← Назад к списку
|
||||||
|
</a>
|
||||||
|
<span class="text-muted small">ID: {{ $place->id }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card shadow-none">
|
||||||
|
<div class="card-header fw-bold">
|
||||||
|
Редактировать локацию: {{ $place->name }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<form method="POST" action="{{ route('places.update', $place->id) }}">
|
||||||
|
@csrf
|
||||||
|
@method('PUT')
|
||||||
|
|
||||||
|
<!-- Название -->
|
||||||
|
<div class="mb-4">
|
||||||
|
<label for="name" class="form-label fw-bold">Название места</label>
|
||||||
|
<input type="text" name="name" id="name"
|
||||||
|
class="form-control @error('name') is-invalid @enderror"
|
||||||
|
value="{{ old('name', $place->name) }}" required placeholder="Например: Главный офис">
|
||||||
|
@error('name')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Адрес -->
|
||||||
|
<div class="mb-4">
|
||||||
|
<label for="address" class="form-label fw-bold">Полный адрес</label>
|
||||||
|
<input type="text" name="address" id="address"
|
||||||
|
class="form-control @error('address') is-invalid @enderror"
|
||||||
|
value="{{ old('address', $place->address) }}" placeholder="Улица, дом, город">
|
||||||
|
@error('address')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Телефон -->
|
||||||
|
<div class="mb-4">
|
||||||
|
<label for="phone" class="form-label fw-bold">Телефон</label>
|
||||||
|
<input type="text" name="phone" id="phone"
|
||||||
|
class="form-control @error('phone') is-invalid @enderror"
|
||||||
|
value="{{ old('phone', $place->phone) }}" placeholder="Телефон">
|
||||||
|
@error('phone')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- URL -->
|
||||||
|
<div class="mb-4">
|
||||||
|
<label for="url" class="form-label fw-bold">URL</label>
|
||||||
|
<input type="text" name="url" id="url"
|
||||||
|
class="form-control @error('url') is-invalid @enderror"
|
||||||
|
value="{{ old('url', $place->url) }}" placeholder="Адрес сайта">
|
||||||
|
@error('url')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- GPS Координаты -->
|
||||||
|
<div class="mb-4">
|
||||||
|
<label for="gps" class="form-label fw-bold">GPS Координаты</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text">
|
||||||
|
<svg xmlns="http://w3.org" width="16" height="16" fill="currentColor" class="bi bi-pin-map" viewBox="0 0 16 16">
|
||||||
|
<path fill-rule="evenodd" d="M3.1 11.2a.5.5 0 0 1 .4-.2H6a.5.5 0 0 1 0 1H3.75L1.5 15h13l-2.25-3H10a.5.5 0 0 1 0-1h2.5a.5.5 0 0 1 .4.2l3 4a.5.5 0 0 1-.4.8H.5a.5.5 0 0 1-.4-.8z"/>
|
||||||
|
<path fill-rule="evenodd" d="M8 1a3 3 0 1 0 0 6 3 3 0 0 0 0-6M4 4a4 4 0 1 1 4.5 3.969V13.5a.5.5 0 0 1-1 0V7.97A4 4 0 0 1 4 4"/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input type="text" name="gps" id="gps"
|
||||||
|
class="form-control @error('gps') is-invalid @enderror"
|
||||||
|
value="{{ old('gps', $place->gps) }}" placeholder="55.7558, 37.6173">
|
||||||
|
</div>
|
||||||
|
@error('gps')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Описание -->
|
||||||
|
<div class="mb-4">
|
||||||
|
<label for="description" class="form-label fw-bold">Описание</label>
|
||||||
|
<textarea name="description" id="description" rows="3"
|
||||||
|
class="form-control @error('description') is-invalid @enderror"
|
||||||
|
placeholder="Дополнительная информация">{{ old('description', $place->description) }}</textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if ($errors->any())
|
||||||
|
<div class="alert alert-danger border-2 shadow-none mb-4">
|
||||||
|
<div class="fw-bold mb-2">При сохранении возникли ошибки:</div>
|
||||||
|
<ul class="mb-0">
|
||||||
|
@foreach ($errors->all() as $error)
|
||||||
|
<li>{{ $error }}</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<div class="d-grid">
|
||||||
|
<button type="submit" class="btn btn-secondary fw-bold">
|
||||||
|
Обновить локацию
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@push('scripts')
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
const phoneInput = document.getElementById('phone');
|
||||||
|
|
||||||
|
function applyMask(val) {
|
||||||
|
let input = val.replace(/\D/g, '');
|
||||||
|
if (input.startsWith('7') || input.startsWith('8')) {
|
||||||
|
input = input.substring(1);
|
||||||
|
}
|
||||||
|
let result = '+7';
|
||||||
|
if (input.length > 0) result += ' (' + input.substring(0, 3);
|
||||||
|
if (input.length >= 4) result += ') ' + input.substring(3, 6);
|
||||||
|
if (input.length >= 7) result += '-' + input.substring(6, 8);
|
||||||
|
if (input.length >= 9) result += '-' + input.substring(8, 10);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Применяем маску к уже существующему значению при загрузке
|
||||||
|
if (phoneInput.value) {
|
||||||
|
phoneInput.value = applyMask(phoneInput.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
phoneInput.addEventListener('input', function (e) {
|
||||||
|
e.target.value = applyMask(e.target.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
phoneInput.addEventListener('keydown', function(e) {
|
||||||
|
if (e.target.selectionStart < 3 && (e.key === 'Backspace' || e.key === 'Delete')) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const coordsInput = document.getElementById('gps');
|
||||||
|
coordsInput.addEventListener('input', function(e) {
|
||||||
|
e.target.value = e.target.value.replace(/[^0-9.,\- ]/g, '');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endpush
|
||||||
@@ -26,11 +26,6 @@
|
|||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
@if(session('success'))
|
|
||||||
<div class="alert alert-success border-2 fw-bold mb-4" style="border-color: #0f5132 !important;">
|
|
||||||
{{ session('success') }}
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
<table class="table table-hover mb-0">
|
<table class="table table-hover mb-0">
|
||||||
<thead class="table-light">
|
<thead class="table-light">
|
||||||
<tr>
|
<tr>
|
||||||
@@ -61,7 +56,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="d-flex justify-left gap-2">
|
<div class="d-flex justify-left gap-2">
|
||||||
<a href="#" class="btn btn-outline-secondary">Редактировать</a>
|
<a href="{{ route('places.edit', $place->id) }}" class="btn btn-outline-secondary">Редактировать</a>
|
||||||
<form action="{{ route('places.delete', $place->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Удалить эту локацию?')">
|
<form action="{{ route('places.delete', $place->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Удалить эту локацию?')">
|
||||||
@csrf
|
@csrf
|
||||||
@method('DELETE')
|
@method('DELETE')
|
||||||
@@ -81,7 +76,6 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="d-flex justify-left mt-4">
|
<div class="d-flex justify-left mt-4">
|
||||||
{{ $places->links() }}
|
{{ $places->links() }}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+2
-1
@@ -15,7 +15,8 @@ use App\Http\Controllers\PlacesController;
|
|||||||
Route::middleware('auth')
|
Route::middleware('auth')
|
||||||
->group(function () {
|
->group(function () {
|
||||||
Route::get('/places', [PlacesController::class, 'index'])->name('places.index');
|
Route::get('/places', [PlacesController::class, 'index'])->name('places.index');
|
||||||
Route::patch('/places/{id}', [PlacesController::class, 'update'])->name('places.update');
|
Route::get('/places/{id}', [PlacesController::class, 'edit'])->name('places.edit');
|
||||||
|
Route::put('/places/{id}', [PlacesController::class, 'update'])->name('places.update');
|
||||||
Route::get('/places/create', [PlacesController::class, 'create'])->name('places.create');
|
Route::get('/places/create', [PlacesController::class, 'create'])->name('places.create');
|
||||||
Route::post('/places/store', [PlacesController::class, 'store'])->name('places.store');
|
Route::post('/places/store', [PlacesController::class, 'store'])->name('places.store');
|
||||||
Route::delete('/places/{id}', [PlacesController::class, 'delete'])->name('places.delete');
|
Route::delete('/places/{id}', [PlacesController::class, 'delete'])->name('places.delete');
|
||||||
|
|||||||
Reference in New Issue
Block a user