| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- @extends('layouts.app')
- @section('content')
- <div class="px-3">
- <form class="row" action="{{ route('responsible.update', $responsible) }}" method="post">
- <div class="col-xxl-6">
- <h4>Ответственный</h4>
- @csrf
- <div class="row mb-2">
- <label for="area_search" class="col-form-label small col-md-4 text-md-end">
- Район
- <sup>*</sup>
- </label>
- <div class="col-md-8">
- <div class="position-relative">
- <input type="text"
- class="form-control form-control-sm"
- id="area_search"
- placeholder="Введите район..."
- autocomplete="off"
- value="{{ old('area_name', $responsible->area?->name ?? '') }}"
- required>
- <input type="hidden"
- name="area_id"
- id="area_id"
- value="{{ old('area_id', $responsible->area?->id ?? '') }}"
- required>
- <div class="autocomplete-dropdown autocomplete-dropdown--order" id="area_dropdown"></div>
- </div>
- <div class="form-text" id="area_hint"></div>
- </div>
- </div>
- @include('partials.input', ['name' => 'name', 'title' => 'ФИО', 'required' => true, 'value' => $responsible->name])
- @include('partials.input', ['name' => 'phone', 'title' => 'Телефон', 'required' => true, 'value' => $responsible->phone])
- @include('partials.input', ['name' => 'post', 'title' => 'Должность', 'value' => $responsible->post])
- @include('partials.submit', ['name' => 'Сохранить', 'delete' => ['form_id' => 'destroy', 'title' => 'Удалить']])
- </div>
- </form>
- </div>
- <div class="visually-hidden d-none">
- <form action="{{ route('responsible.destroy', $responsible) }}" id="destroy" method="post">
- @csrf
- @method('DELETE')
- </form>
- </div>
- @endsection
- @push('scripts')
- <script>
- waitForJQuery(function () {
- const $form = $('form.row[action*="responsible"]');
- const $input = $('#area_search');
- const $dropdown = $('#area_dropdown');
- const $hiddenInput = $('#area_id');
- const $hint = $('#area_hint');
- let currentFocus = -1;
- const areas = @json($areasForSearch ?? []);
- function escapeHtml(text) {
- return String(text)
- .replace(/&/g, '&')
- .replace(/</g, '<')
- .replace(/>/g, '>')
- .replace(/"/g, '"')
- .replace(/'/g, ''');
- }
- function escapeRegex(str) {
- return String(str).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
- }
- function highlightMatch(text, query) {
- if (!text || !query) {
- return escapeHtml(text || '');
- }
- const safeText = escapeHtml(text);
- const regex = new RegExp('(' + escapeRegex(query) + ')', 'gi');
- return safeText.replace(regex, '<strong>$1</strong>');
- }
- function showDropdown(items, query) {
- $dropdown.empty();
- currentFocus = -1;
- if (!items.length) {
- $dropdown.html('<div class="autocomplete-item text-muted">Ничего не найдено</div>');
- $dropdown.show();
- return;
- }
- items.forEach(function (item) {
- const html = '<div class="autocomplete-item" data-id="' + item.id + '" data-name="' + escapeHtml(item.name) + '">' +
- '<div class="article">' + highlightMatch(item.name, query) + '</div>' +
- '</div>';
- $dropdown.append(html);
- });
- $dropdown.show();
- }
- function hideDropdown() {
- $dropdown.hide();
- }
- function selectItem($item) {
- const id = String($item.data('id') || '');
- const name = String($item.data('name') || '');
- $input.val(name);
- $hiddenInput.val(id);
- $hint.html('<i class="bi bi-check-circle text-success"></i> Выбрано: ' + name);
- $input.removeClass('is-invalid');
- hideDropdown();
- }
- function setActive($items) {
- $items.removeClass('active');
- if (currentFocus >= 0 && currentFocus < $items.length) {
- const $active = $items.eq(currentFocus);
- $active.addClass('active');
- $active[0].scrollIntoView({block: 'nearest'});
- }
- }
- function searchAreas(query) {
- const normalized = String(query || '').trim().toLowerCase();
- if (normalized.length < 1) {
- hideDropdown();
- return;
- }
- const items = areas.filter(function (item) {
- return String(item.name).toLowerCase().includes(normalized);
- });
- showDropdown(items.slice(0, 50), normalized);
- }
- $input.on('input', function () {
- $hiddenInput.val('');
- $hint.html('');
- $input.removeClass('is-invalid');
- searchAreas($(this).val());
- });
- $input.on('focus', function () {
- if (!$hiddenInput.val()) {
- searchAreas($(this).val());
- }
- });
- $input.on('keydown', function (e) {
- const $items = $dropdown.find('.autocomplete-item:not(.text-muted)');
- if (e.key === 'ArrowDown') {
- e.preventDefault();
- currentFocus++;
- if (currentFocus >= $items.length) {
- currentFocus = 0;
- }
- setActive($items);
- } else if (e.key === 'ArrowUp') {
- e.preventDefault();
- currentFocus--;
- if (currentFocus < 0) {
- currentFocus = $items.length - 1;
- }
- setActive($items);
- } else if (e.key === 'Enter') {
- if ($items.length > 0 && currentFocus > -1) {
- e.preventDefault();
- selectItem($items.eq(currentFocus));
- }
- } else if (e.key === 'Escape') {
- hideDropdown();
- }
- });
- $dropdown.on('click', '.autocomplete-item:not(.text-muted)', function () {
- selectItem($(this));
- });
- $(document).on('click', function (e) {
- if (!$(e.target).closest('#area_search, #area_dropdown').length) {
- hideDropdown();
- }
- });
- $form.on('submit', function (e) {
- if (!$hiddenInput.val()) {
- e.preventDefault();
- $input.addClass('is-invalid').focus();
- $hint.html('<span class="text-danger">Выберите район из списка</span>');
- }
- });
- const initialAreaId = String($hiddenInput.val() || '');
- const initialArea = areas.find(function (item) {
- return String(item.id) === initialAreaId;
- });
- if (initialArea) {
- $input.val(initialArea.name);
- $hint.html('<i class="bi bi-check-circle text-success"></i> Выбрано: ' + initialArea.name);
- }
- });
- </script>
- @endpush
|