287 lines
11 KiB
JavaScript
287 lines
11 KiB
JavaScript
$(function () {
|
||
var modalEl = document.getElementById('category-modal');
|
||
|
||
if (!modalEl) {
|
||
return;
|
||
}
|
||
|
||
var modal = new bootstrap.Modal(modalEl);
|
||
var $form = $('#category-form');
|
||
var $error = $('#category-form-error');
|
||
var archiveEl = document.getElementById('category-archive-modal');
|
||
var archiveModal = archiveEl ? new bootstrap.Modal(archiveEl) : null;
|
||
var categoriesModalEl = document.getElementById('categories-modal');
|
||
var categoriesModal = categoriesModalEl ? new bootstrap.Modal(categoriesModalEl) : null;
|
||
|
||
var groupModalEl = document.getElementById('group-modal');
|
||
var groupModal = groupModalEl ? new bootstrap.Modal(groupModalEl) : null;
|
||
var $groupForm = $('#group-form');
|
||
var $groupError = $('#group-form-error');
|
||
|
||
// Внешняя модалка «Статьи» — обычный Bootstrap Modal, открывается поверх страницы /budgets;
|
||
// add/edit (category-modal/group-modal) и архив (category-archive-modal) открываются уже
|
||
// поверх неё — штатный для Bootstrap 5 стек модалок, закрытие/Escape/клик по backdrop у
|
||
// каждой работает независимо через data-bs-dismiss/её собственный bootstrap.Modal instance.
|
||
$(document).on('click', '.js-categories-open', function () {
|
||
if (categoriesModal) {
|
||
categoriesModal.show();
|
||
}
|
||
});
|
||
|
||
function filterGroupOptions(type) {
|
||
$('#category-group option[data-type]').each(function () {
|
||
var match = $(this).data('type') === type;
|
||
$(this).prop('hidden', !match).prop('disabled', !match);
|
||
});
|
||
|
||
var $selected = $('#category-group option:selected');
|
||
if ($selected.data('type') && $selected.data('type') !== type) {
|
||
$('#category-group').val('');
|
||
}
|
||
}
|
||
|
||
function toggleFormulaGroup(type) {
|
||
$('#category-formula-group').toggle(type === 'income');
|
||
}
|
||
|
||
function resetForm() {
|
||
$form[0].reset();
|
||
$form.find('[name=id]').val('');
|
||
$error.hide().text('');
|
||
}
|
||
|
||
$(document).on('click', '.js-category-add', function () {
|
||
var type = $(this).data('type');
|
||
|
||
resetForm();
|
||
$form.data('mode', 'create').attr('action', '/categories/create');
|
||
$('#category-modal-title').text(type === 'income' ? 'Новая статья дохода' : 'Новая статья расхода');
|
||
$('#category-type').val(type);
|
||
filterGroupOptions(type);
|
||
toggleFormulaGroup(type);
|
||
modal.show();
|
||
});
|
||
|
||
$(document).on('click', '.js-category-edit', function (e) {
|
||
e.preventDefault();
|
||
|
||
var $row = $(this).closest('.category-row');
|
||
var type = $row.data('type');
|
||
|
||
resetForm();
|
||
$form.data('mode', 'edit').attr('action', '/categories/edit/' + $row.data('id'));
|
||
$form.find('[name=title]').val($row.data('title'));
|
||
$('#category-type').val(type);
|
||
$('#category-modal-title').text('Редактировать статью');
|
||
filterGroupOptions(type);
|
||
$('#category-group').val($row.data('group_id') || '');
|
||
toggleFormulaGroup(type);
|
||
$('#category-linked').val($row.data('linked') || '');
|
||
$form.find('[name=formula_pct]').val($row.data('pct') || '');
|
||
modal.show();
|
||
});
|
||
|
||
$(document).on('click', '.js-category-archive-open', function () {
|
||
if (archiveModal) {
|
||
archiveModal.show();
|
||
}
|
||
});
|
||
|
||
$(document).on('click', '.js-category-restore', function () {
|
||
var $row = $(this).closest('.archive-row');
|
||
var csrf = $form.find('[name=csrf_token]').val();
|
||
|
||
$.post('/categories/restore/' + $row.data('id'), {csrf_token: csrf})
|
||
.done(function () {
|
||
window.location.reload();
|
||
})
|
||
.fail(function () {
|
||
window.alert('Не удалось восстановить статью');
|
||
});
|
||
});
|
||
|
||
$(document).on('click', '.js-category-delete', function (e) {
|
||
e.preventDefault();
|
||
|
||
var $row = $(this).closest('.category-row');
|
||
var title = $row.data('title');
|
||
var csrf = $form.find('[name=csrf_token]').val();
|
||
|
||
if (!window.confirm('Архивировать статью «' + title + '»?')) {
|
||
return;
|
||
}
|
||
|
||
$.post('/categories/delete/' + $row.data('id'), {csrf_token: csrf})
|
||
.done(function () {
|
||
window.location.reload();
|
||
})
|
||
.fail(function () {
|
||
window.alert('Не удалось архивировать статью');
|
||
});
|
||
});
|
||
|
||
$(document).on('submit', '#category-form', function (e) {
|
||
e.preventDefault();
|
||
$error.hide().text('');
|
||
|
||
$.post($form.attr('action'), $form.serialize())
|
||
.done(function () {
|
||
window.location.reload();
|
||
})
|
||
.fail(function (xhr) {
|
||
var data = xhr.responseJSON;
|
||
|
||
if (data && data.archived) {
|
||
if (window.confirm('Статья «' + data.archived.title + '» уже есть в архиве. Восстановить её вместо создания новой?')) {
|
||
var csrf = $form.find('[name=csrf_token]').val();
|
||
|
||
$.post('/categories/restore/' + data.archived.id, {csrf_token: csrf})
|
||
.done(function () {
|
||
window.location.reload();
|
||
})
|
||
.fail(function () {
|
||
window.alert('Не удалось восстановить статью');
|
||
});
|
||
}
|
||
return;
|
||
}
|
||
|
||
var errors = data && data.errors;
|
||
var message = errors ? Object.values(errors).join(' ') : 'Не удалось сохранить статью';
|
||
|
||
$error.text(message).show();
|
||
});
|
||
});
|
||
|
||
$(document).on('change', '.js-category-move', function () {
|
||
var $select = $(this);
|
||
var newGroup = $select.val();
|
||
|
||
if (newGroup === '') {
|
||
return;
|
||
}
|
||
|
||
var $row = $select.closest('.category-row');
|
||
var csrf = $form.find('[name=csrf_token]').val();
|
||
|
||
$.post('/categories/edit/' + $row.data('id'), {
|
||
csrf_token: csrf,
|
||
title: $row.data('title'),
|
||
type: $row.data('type'),
|
||
group_id: newGroup,
|
||
linked_expense_categorie_id: $row.data('linked') || '',
|
||
formula_pct: $row.data('pct') || ''
|
||
})
|
||
.done(function () {
|
||
window.location.reload();
|
||
})
|
||
.fail(function (xhr) {
|
||
var errors = xhr.responseJSON && xhr.responseJSON.errors;
|
||
var message = errors ? Object.values(errors).join(' ') : 'Не удалось перенести статью';
|
||
|
||
window.alert(message);
|
||
$select.val('');
|
||
});
|
||
});
|
||
|
||
// ---------- группы (App\Controller\CategoryGroupsController) ----------
|
||
|
||
$(document).on('click', '.js-group-add', function () {
|
||
if (!groupModal) {
|
||
return;
|
||
}
|
||
|
||
var type = $(this).data('type');
|
||
|
||
$groupForm[0].reset();
|
||
$groupForm.find('[name=id]').val('');
|
||
$groupError.hide().text('');
|
||
$groupForm.data('mode', 'create').attr('action', '/categorygroups/create');
|
||
$('#group-modal-title').text(type === 'income' ? 'Новая группа доходов' : 'Новая группа расходов');
|
||
$('#group-type').val(type);
|
||
groupModal.show();
|
||
});
|
||
|
||
$(document).on('click', '.js-group-edit', function (e) {
|
||
e.preventDefault();
|
||
|
||
if (!groupModal) {
|
||
return;
|
||
}
|
||
|
||
var $row = $(this).closest('.category-row');
|
||
|
||
$groupForm[0].reset();
|
||
$groupError.hide().text('');
|
||
$groupForm.data('mode', 'edit').attr('action', '/categorygroups/edit/' + $row.data('id'));
|
||
$groupForm.find('[name=title]').val($row.data('title'));
|
||
$('#group-type').val($row.data('type'));
|
||
$('#group-modal-title').text('Редактировать группу');
|
||
groupModal.show();
|
||
});
|
||
|
||
$(document).on('submit', '#group-form', function (e) {
|
||
e.preventDefault();
|
||
$groupError.hide().text('');
|
||
|
||
$.post($groupForm.attr('action'), $groupForm.serialize())
|
||
.done(function () {
|
||
window.location.reload();
|
||
})
|
||
.fail(function (xhr) {
|
||
var data = xhr.responseJSON;
|
||
|
||
if (data && data.archived) {
|
||
if (window.confirm('Группа «' + data.archived.title + '» уже есть в архиве. Восстановить её вместо создания новой?')) {
|
||
var csrf = $groupForm.find('[name=csrf_token]').val();
|
||
|
||
$.post('/categorygroups/restore/' + data.archived.id, {csrf_token: csrf})
|
||
.done(function () { window.location.reload(); })
|
||
.fail(function () { window.alert('Не удалось восстановить группу'); });
|
||
}
|
||
return;
|
||
}
|
||
|
||
var errors = data && data.errors;
|
||
var message = errors ? Object.values(errors).join(' ') : 'Не удалось сохранить группу';
|
||
|
||
$groupError.text(message).show();
|
||
});
|
||
});
|
||
|
||
$(document).on('click', '.js-group-delete', function (e) {
|
||
e.preventDefault();
|
||
|
||
var $row = $(this).closest('.category-row');
|
||
var title = $row.data('title');
|
||
var csrf = $form.find('[name=csrf_token]').val();
|
||
|
||
if (!window.confirm('Архивировать группу «' + title + '»? Статьи внутри останутся, но без группы.')) {
|
||
return;
|
||
}
|
||
|
||
$.post('/categorygroups/delete/' + $row.data('id'), {csrf_token: csrf})
|
||
.done(function () { window.location.reload(); })
|
||
.fail(function () { window.alert('Не удалось архивировать группу'); });
|
||
});
|
||
|
||
$(document).on('click', '.js-group-restore', function () {
|
||
var $row = $(this).closest('.archive-row');
|
||
var csrf = $form.find('[name=csrf_token]').val();
|
||
|
||
$.post('/categorygroups/restore/' + $row.data('id'), {csrf_token: csrf})
|
||
.done(function () { window.location.reload(); })
|
||
.fail(function () { window.alert('Не удалось восстановить группу'); });
|
||
});
|
||
|
||
$(document).on('click', '.room-menu-btn', function () {
|
||
$(this).closest('.room-menu').toggleClass('open');
|
||
});
|
||
|
||
$(document).on('click', function (e) {
|
||
if (!$(e.target).closest('.room-menu').length) {
|
||
$('.room-menu.open').removeClass('open');
|
||
}
|
||
});
|
||
});
|