fix! исправлены обнаруженные баги в админке
This commit is contained in:
parent
ce78fad613
commit
55bf61a359
@ -44,6 +44,16 @@ public function edit(Company $company)
|
|||||||
|
|
||||||
public function update(Request $request, Company $company)
|
public function update(Request $request, Company $company)
|
||||||
{
|
{
|
||||||
|
$validated = $request->validate([
|
||||||
|
'name' => 'required',
|
||||||
|
'email' => "required|unique:companies,email,{$company->id}",
|
||||||
|
'phone' => "required|unique:companies,phone,{$company->id}",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'email.unique' => 'Указанная электронная почта уже существует',
|
||||||
|
'phone.unique' => 'Указанный номер телефона уже существует'
|
||||||
|
]
|
||||||
|
);
|
||||||
$company->update($request->only('name', 'email', 'phone'));
|
$company->update($request->only('name', 'email', 'phone'));
|
||||||
if ($request->token) {
|
if ($request->token) {
|
||||||
$company->bitrixy->token = $request->token;
|
$company->bitrixy->token = $request->token;
|
||||||
|
|||||||
@ -28,6 +28,7 @@ public function index(Request $request)
|
|||||||
$complexes = $complexes->get();
|
$complexes = $complexes->get();
|
||||||
return view('admin::complexes.index', [
|
return view('admin::complexes.index', [
|
||||||
'complexes' => $complexes,
|
'complexes' => $complexes,
|
||||||
|
'cities' => City::orderBy('name')->get(),
|
||||||
'filter' => $request->filter
|
'filter' => $request->filter
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@ -48,7 +49,16 @@ public function update(Request $request, Complex $complex)
|
|||||||
|
|
||||||
public function create(Request $request)
|
public function create(Request $request)
|
||||||
{
|
{
|
||||||
$city = Complex::create($request->only('name'));
|
$validated = $request->validate([
|
||||||
|
'name' => "required",
|
||||||
|
'city_id' => "required",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name.required' => 'Необходимо указать название жилого комплекса',
|
||||||
|
'city_id.required' => 'Необходимо указать город'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$city = Complex::create($request->only('name', 'city_id'));
|
||||||
return to_route('admin.complexes');
|
return to_route('admin.complexes');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,8 @@
|
|||||||
@csrf
|
@csrf
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="nameFormControl" class="form-label">Название</label>
|
<label for="nameFormControl" class="form-label">Название</label>
|
||||||
<input type="text" class="form-control" id="nameFormControl" name="name" value="{{ $company->name }}">
|
<input type="text" class="form-control" id="nameFormControl" name="name"
|
||||||
|
value="{{ old('name', $company->name) }}">
|
||||||
@error('name')
|
@error('name')
|
||||||
<div class="text-danger">{{ $message }}</div>
|
<div class="text-danger">{{ $message }}</div>
|
||||||
@enderror
|
@enderror
|
||||||
@ -18,17 +19,17 @@
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="emailFormControl" class="form-label">Email</label>
|
<label for="emailFormControl" class="form-label">Email</label>
|
||||||
<input type="text" class="form-control" id="emailFormControl" name="email"
|
<input type="text" class="form-control" id="emailFormControl" name="email"
|
||||||
value="{{ $company->email }}">
|
value="{{ old('email', $company->email) }}">
|
||||||
@error('email')
|
@error('email')
|
||||||
<div class="text-danger">{{ $message }}</div>
|
<div class="text-danger d-none">{{ $message }}</div>
|
||||||
@enderror
|
@enderror
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="phoneFormControl" class="form-label">Телефон</label>
|
<label for="phoneFormControl" class="form-label">Телефон</label>
|
||||||
<input type="text" class="form-control" id="phoneFormControl" name="phone"
|
<input type="tel" class="form-control" id="phoneFormControl" name="phone"
|
||||||
value="{{ $company->phone }}">
|
value="{{ old('phone', $company->phone) }}">
|
||||||
@error('phone')
|
@error('phone')
|
||||||
<div class="text-danger">{{ $message }}</div>
|
<div class="text-danger d-none">{{ $message }}</div>
|
||||||
@enderror
|
@enderror
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -16,7 +16,6 @@
|
|||||||
<div class="text-danger">{{ $message }}</div>
|
<div class="text-danger">{{ $message }}</div>
|
||||||
@enderror
|
@enderror
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="cityFormControl" class="form-label">Город</label>
|
<label for="cityFormControl" class="form-label">Город</label>
|
||||||
<select class="form-select" name="city_id" id="cityFormControl">
|
<select class="form-select" name="city_id" id="cityFormControl">
|
||||||
|
|||||||
@ -47,8 +47,8 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="text-end">
|
<td class="text-end">
|
||||||
<div class="dropdown" style="">
|
<div class="dropdown" style="">
|
||||||
<button class="btn btn-light" type="button" id="dropdownMenuButton"
|
<button class="btn btn-light" type="button" id="dropdownMenuButton" data-bs-toggle="dropdown"
|
||||||
data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
aria-haspopup="true" aria-expanded="false">
|
||||||
@if ($complex->trashed())
|
@if ($complex->trashed())
|
||||||
<i class="bi bi-recycle"></i>
|
<i class="bi bi-recycle"></i>
|
||||||
@else
|
@else
|
||||||
@ -65,8 +65,7 @@
|
|||||||
@else
|
@else
|
||||||
<a class="dropdown-item"
|
<a class="dropdown-item"
|
||||||
href="{{ route('admin.complexes.edit', ['complex' => $complex]) }}">Редактировать</a>
|
href="{{ route('admin.complexes.edit', ['complex' => $complex]) }}">Редактировать</a>
|
||||||
<form method="post"
|
<form method="post" action="{{ route('admin.complexes.delete', ['complex' => $complex]) }}">
|
||||||
action="{{ route('admin.complexes.delete', ['complex' => $complex]) }}">
|
|
||||||
@csrf
|
@csrf
|
||||||
<button class="dropdown-item" type="submit">Удалить</button>
|
<button class="dropdown-item" type="submit">Удалить</button>
|
||||||
</form>
|
</form>
|
||||||
@ -83,21 +82,28 @@
|
|||||||
<!-- Modal -->
|
<!-- Modal -->
|
||||||
<div class="modal fade" id="createCityModal" tabindex="-1" aria-labelledby="createCityModalLabel" aria-hidden="true">
|
<div class="modal fade" id="createCityModal" tabindex="-1" aria-labelledby="createCityModalLabel" aria-hidden="true">
|
||||||
|
|
||||||
<form class="modal-dialog modal-dialog-centered" action="{{ route('admin.cities.create') }}" method="post">
|
<form class="modal-dialog modal-dialog-centered" action="{{ route('admin.complexes.create') }}" method="post">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h1 class="modal-title fs-5" id="createCityModalLabel">Новый город</h1>
|
<h1 class="modal-title fs-5" id="createCityModalLabel">Новый жилой комплекс</h1>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
|
||||||
<div class="my-3">
|
|
||||||
@csrf
|
@csrf
|
||||||
<label for="cityNameInput" class="form-label">Введите название нового города</label>
|
<div class="mb-3">
|
||||||
<input class="form-control" type="text" id="cityNameInput" name="name" required>
|
<label for="nameFormControl" class="form-label">Название</label>
|
||||||
@error('text')
|
<input type="text" class="form-control" id="nameFormControl" name="name"
|
||||||
<div class="text-danger">{{ $message }}</div>
|
value="{{ old('name') }}">
|
||||||
@enderror
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="cityFormControl" class="form-label">Город</label>
|
||||||
|
<select class="form-select" name="city_id" id="cityFormControl">
|
||||||
|
@foreach ($cities as $city)
|
||||||
|
<option value="{{ $city->id }}" @if (old('city_id') == $city->id) selected @endif>
|
||||||
|
{{ $city->name }}
|
||||||
|
</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="phoneFormControl" class="form-label">телефон</label>
|
<label for="phoneFormControl" class="form-label">телефон</label>
|
||||||
<input type="text" class="form-control" id="phoneFormControl" name="phone"
|
<input type="tel" class="form-control" id="phoneFormControl" name="phone"
|
||||||
value="{{ $user->phone }}">
|
value="{{ $user->phone }}">
|
||||||
@error('phone')
|
@error('phone')
|
||||||
<div class="text-danger">{{ $message }}</div>
|
<div class="text-danger">{{ $message }}</div>
|
||||||
|
|||||||
@ -100,7 +100,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="my-3">
|
<div class="my-3">
|
||||||
<label for="nameInput" class="form-label">Телефон</label>
|
<label for="nameInput" class="form-label">Телефон</label>
|
||||||
<input class="form-control" type="text" id="phoneInput" name="phone" required>
|
<input class="form-control" type="tel" id="phoneInput" name="phone" required>
|
||||||
@error('phone')
|
@error('phone')
|
||||||
<div class="text-danger">{{ $message }}</div>
|
<div class="text-danger">{{ $message }}</div>
|
||||||
@enderror
|
@enderror
|
||||||
|
|||||||
@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="agentPhone" class="form-label">Телефон</label>
|
<label for="agentPhone" class="form-label">Телефон</label>
|
||||||
<input type="text" class="form-control" id="agentPhone" name="phone">
|
<input type="tel" class="form-control" id="agentPhone" name="phone">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3 form-check form-switch">
|
<div class="mb-3 form-check form-switch">
|
||||||
|
|||||||
@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="adminPhone" class="form-label">Телефон</label>
|
<label for="adminPhone" class="form-label">Телефон</label>
|
||||||
<input type="text" class="form-control" id="adminPhone" name="phone">
|
<input type="tel" class="form-control" id="adminPhone" name="phone">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3 form-check form-switch">
|
<div class="mb-3 form-check form-switch">
|
||||||
|
|||||||
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
if($json['total_commits'] > 0)
|
if($json['total_commits'] > 0)
|
||||||
{
|
{
|
||||||
$result = shell_exec("cd /var/www/lk && git reset --hard HEAD && git pull && php artisan migrate");
|
$result = shell_exec("cd /var/www/lk && git reset --hard HEAD && git pull && php artisan migrate && npm run build");
|
||||||
echo "<p>$result</p>";
|
echo "<p>$result</p>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
81
resources/js/phone-format.js
Normal file
81
resources/js/phone-format.js
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
function initPhoneMask(selector = 'input[type="tel"]') {
|
||||||
|
const format = (digits) => {
|
||||||
|
// Пример маски: +7 (999) 123-45-67
|
||||||
|
const d = digits.slice(0, 11); // ограничим 11 цифрами (под РФ)
|
||||||
|
if (!d.length) return '';
|
||||||
|
|
||||||
|
// если начали вводить с 8/7 — приведём к +7
|
||||||
|
let rest = d;
|
||||||
|
let prefix = '+7';
|
||||||
|
if (d[0] === '8') rest = '7' + d.slice(1);
|
||||||
|
if (rest[0] === '7') rest = rest.slice(1);
|
||||||
|
else {
|
||||||
|
// если первая цифра не 7, считаем что пользователь вводит локально, но всё равно показываем +7
|
||||||
|
// (при желании можно тут менять логику)
|
||||||
|
}
|
||||||
|
|
||||||
|
const a = rest.slice(0, 3);
|
||||||
|
const b = rest.slice(3, 6);
|
||||||
|
const c = rest.slice(6, 8);
|
||||||
|
const e = rest.slice(8, 10);
|
||||||
|
|
||||||
|
let out = prefix;
|
||||||
|
if (a) out += ` (${a}`;
|
||||||
|
if (a && a.length === 3) out += `)`;
|
||||||
|
if (b) out += ` ${b}`;
|
||||||
|
if (c) out += `-${c}`;
|
||||||
|
if (e) out += `-${e}`;
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
|
||||||
|
const applyToInput = (input) => {
|
||||||
|
if (input.dataset.phoneMasked === '1') return;
|
||||||
|
input.dataset.phoneMasked = '1';
|
||||||
|
|
||||||
|
// Подсказки браузеру: tel-поле и события input/change поддерживаются стандартно [web:2]
|
||||||
|
input.autocomplete = input.autocomplete || 'tel';
|
||||||
|
input.inputMode = input.inputMode || 'tel'; // подсказка клавиатуры, особенно на мобилках [web:12]
|
||||||
|
|
||||||
|
const handler = () => {
|
||||||
|
const digits = input.value.replace(/\D/g, '');
|
||||||
|
input.value = format(digits);
|
||||||
|
};
|
||||||
|
|
||||||
|
input.addEventListener('input', handler); // события input/change для tel описаны в MDN [web:2]
|
||||||
|
input.addEventListener('change', handler); // [web:2]
|
||||||
|
};
|
||||||
|
|
||||||
|
// 1) применяем ко всем уже существующим
|
||||||
|
document.querySelectorAll(selector).forEach(applyToInput);
|
||||||
|
|
||||||
|
// 2) применяем к добавляемым динамически
|
||||||
|
const mo = new MutationObserver((mutations) => {
|
||||||
|
for (const m of mutations) {
|
||||||
|
for (const node of m.addedNodes) {
|
||||||
|
if (!(node instanceof Element)) continue;
|
||||||
|
if (node.matches?.(selector)) applyToInput(node);
|
||||||
|
node.querySelectorAll?.(selector).forEach(applyToInput);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mo.observe(document.documentElement, { childList: true, subtree: true });
|
||||||
|
return () => mo.disconnect();
|
||||||
|
}
|
||||||
|
// запуск
|
||||||
|
initPhoneMask();
|
||||||
|
|
||||||
|
function runOnDomUpdate(fn, root = document.documentElement) {
|
||||||
|
const observer = new MutationObserver((mutations) => {
|
||||||
|
// если важно “не дергать” лишний раз — фильтруем
|
||||||
|
if (mutations.some(m => m.type === 'childList' && (m.addedNodes.length || m.removedNodes.length))) {
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(root, { childList: true, subtree: true }); // childList/subtree — ключевые опции [web:16]
|
||||||
|
return () => observer.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
// пример: заново применить маску к новым инпутам
|
||||||
|
const stop = runOnDomUpdate(() => initPhoneMask());
|
||||||
@ -59,10 +59,12 @@ class="bi bi-caret-left" viewBox="0 0 16 16">
|
|||||||
<!-- Right Side Of Navbar -->
|
<!-- Right Side Of Navbar -->
|
||||||
<ul class="navbar-nav ms-auto">
|
<ul class="navbar-nav ms-auto">
|
||||||
<li class="nav-item dropdown">
|
<li class="nav-item dropdown">
|
||||||
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button"
|
<a id="navbarDropdown" class="nav-link dropdown-toggle link-secondary" href="#" role="button"
|
||||||
data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
|
data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
|
||||||
<img src="../../images/icons/user.png" class="img-fluid align-middle"
|
<svg class="" xmlns="http://www.w3.org/2000/svg" width="38" height="38" fill="currentColor" class="bi bi-person-circle" viewBox="0 0 16 16">
|
||||||
style="height: 40px;">
|
<path d="M11 6a3 3 0 1 1-6 0 3 3 0 0 1 6 0"/>
|
||||||
|
<path fill-rule="evenodd" d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8m8-7a7 7 0 0 0-5.468 11.37C3.242 11.226 4.805 10 8 10s4.757 1.225 5.468 2.37A7 7 0 0 0 8 1"/>
|
||||||
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
|
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
|
||||||
@ -119,7 +121,16 @@ class="bi bi-caret-left" viewBox="0 0 16 16">
|
|||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
@foreach ($errors->all() as $error)
|
@foreach ($errors->all() as $error)
|
||||||
|
|
||||||
|
<div class="alert alert-danger d-flex align-items-center" role="alert">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-exclamation-triangle" viewBox="0 0 16 16">
|
||||||
|
<path d="M7.938 2.016A.13.13 0 0 1 8.002 2a.13.13 0 0 1 .063.016.15.15 0 0 1 .054.057l6.857 11.667c.036.06.035.124.002.183a.2.2 0 0 1-.054.06.1.1 0 0 1-.066.017H1.146a.1.1 0 0 1-.066-.017.2.2 0 0 1-.054-.06.18.18 0 0 1 .002-.183L7.884 2.073a.15.15 0 0 1 .054-.057m1.044-.45a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767z"/>
|
||||||
|
<path d="M7.002 12a1 1 0 1 1 2 0 1 1 0 0 1-2 0M7.1 5.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0z"/>
|
||||||
|
</svg>
|
||||||
|
<div class="ms-3 fw-bold">
|
||||||
{{ $error }}
|
{{ $error }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
@yield('content')
|
@yield('content')
|
||||||
</div>
|
</div>
|
||||||
@ -129,5 +140,5 @@ class="bi bi-caret-left" viewBox="0 0 16 16">
|
|||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@vite(['resources/js/phone-format.js'])
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -233,33 +233,7 @@ class="bi bi-emoji-astonished" viewBox="0 0 16 16">
|
|||||||
</div>
|
</div>
|
||||||
@script
|
@script
|
||||||
<script>
|
<script>
|
||||||
eventCalllback = function(e) {
|
|
||||||
var el = e.target,
|
|
||||||
clearVal = el.dataset.phoneClear,
|
|
||||||
pattern = el.dataset.phonePattern,
|
|
||||||
matrix_def = "+7(___) ___-__-__",
|
|
||||||
matrix = pattern ? pattern : matrix_def,
|
|
||||||
i = 0,
|
|
||||||
def = matrix.replace(/\D/g, ""),
|
|
||||||
val = e.target.value.replace(/\D/g, "");
|
|
||||||
if (clearVal !== 'false' && e.type === 'blur') {
|
|
||||||
if (val.length < matrix.match(/([\_\d])/g).length) {
|
|
||||||
e.target.value = '';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (def.length >= val.length) val = def;
|
|
||||||
e.target.value = matrix.replace(/./g, function(a) {
|
|
||||||
return /[_\d]/.test(a) && i < val.length ? val.charAt(i++) : i >= val.length ? "" :
|
|
||||||
a
|
|
||||||
});
|
|
||||||
}
|
|
||||||
var phone_inputs = document.querySelectorAll('[data-phone-pattern]');
|
|
||||||
for (let elem of phone_inputs) {
|
|
||||||
for (let ev of ['input', 'blur', 'focus']) {
|
|
||||||
elem.addEventListener(ev, eventCalllback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
@endscript
|
@endscript
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -11,6 +11,7 @@ export default defineConfig({
|
|||||||
'resources/css/app.css',
|
'resources/css/app.css',
|
||||||
'resources/css/docs.css',
|
'resources/css/docs.css',
|
||||||
'resources/css/multiselect.css',
|
'resources/css/multiselect.css',
|
||||||
|
'resources/js/phone-format.js',
|
||||||
],
|
],
|
||||||
refresh: true,
|
refresh: true,
|
||||||
}),
|
}),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user