Менеджеры сгруппированы по подразделениям

Магазин
рендерится до формы в DOM — инициализацию откладываем. function initSubdivisionManagerAutosave() { const form = document.getElementById('managerForm'); if (!form) { return; } const statusEl = document.getElementById('managerSaveStatus'); const tokenInput = form.querySelector('input[name="_token"]'); const csrf = tokenInput ? tokenInput.value : (document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || ''); const checkboxes = () => Array.from(form.querySelectorAll('input[name="manager_ids[]"]')); let chain = Promise.resolve(); function setStatus(text, state) { if (!statusEl) { return; } statusEl.textContent = text; statusEl.dataset.state = state || ''; } function send() { const params = new URLSearchParams(); checkboxes().forEach((box) => { if (box.checked) { params.append('manager_ids[]', box.value); } }); setStatus('Сохранение…', 'pending'); return fetch(form.action, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'X-CSRF-TOKEN': csrf, 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json', }, body: params.toString(), }) .then((r) => r.json().then((data) => ({ ok: r.ok, data }))) .then(({ ok, data }) => { if (!ok || !data.success) { const message = firstError(data) || data.message || 'Не удалось сохранить'; setStatus('Ошибка', 'error'); notifyError(message); return; } setStatus('Сохранено', 'ok'); }) .catch(() => { setStatus('Ошибка', 'error'); notifyError('Не удалось сохранить отметку менеджера'); }); } form.addEventListener('change', (e) => { if (!e.target.matches('input[name="manager_ids[]"]')) { return; } chain = chain.then(send).catch(() => {}); }); // Кнопки submit больше нет; страхуемся от случайной отправки формы. form.addEventListener('submit', (e) => e.preventDefault()); function firstError(data) { if (data && data.errors) { const key = Object.keys(data.errors)[0]; if (key) { return data.errors[key][0]; } } return null; } function notifyError(message) { if (window.toastr) { toastr.error(message); } else { alert(message); } } } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initSubdivisionManagerAutosave); } else { initSubdivisionManagerAutosave(); }