Bicycle/App/media/js/categories.js
2026-08-15 10:39:22 +03:00

287 lines
11 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

$(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');
}
});
});