Fix búsqueda en tiempo real, paginación, OneSignal, bancos/categorías y vistas auth

- ajaxcrud.js: fix race condition en búsqueda, abort de requests en vuelo
- Layout: mover @yield('js') después de app.js para corregir orden de carga
- Paginación: useBootstrapFour() + eliminar wrappers <ul> duplicados en 17 vistas
- OneSignal: migrar de UserTag iChamba_ID a ExternalId en controladores
- API: agregar endpoint GET /api/banks y campos rfc/bank/bank_account/fee en hero()
- Seeders: BanksSeeder (239 bancos) y CategoriesSeeder (100 categorías)
- Auth views: corregir padding/scroll en register, login, password reset

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-16 21:21:44 -06:00
parent fb5caeab6e
commit b34622b289
71 changed files with 3303 additions and 1576 deletions

43
public/js/ajaxcrud.js vendored
View File

@@ -1,8 +1,26 @@
$(document).on('click', 'pagination a', function (event) {
$(document).on('click', '.pagination a', function (event) {
event.preventDefault();
ajaxLoad($(this).attr('href'));
});
$(document).on('submit', 'form[method="GET"]', function (event) {
event.preventDefault();
ajaxLoad($(this).attr('action') + '?' + $(this).serialize());
});
var searchTimer;
$(document).on('keyup', 'input[name="search"]', function () {
var form = $(this).closest('form');
clearTimeout(searchTimer);
if (activeRequest) {
activeRequest.abort();
activeRequest = null;
}
searchTimer = setTimeout(function () {
ajaxLoad(form.attr('action') + '?' + form.serialize());
}, 400);
});
$(document).on('submit', 'form#frm', function (event) {
event.preventDefault();
var form = $(this);
@@ -33,19 +51,36 @@ $(document).on('submit', 'form#frm', function (event) {
return false;
});
var activeRequest = null;
function ajaxLoad(filename, content) {
content = typeof content !== 'undefined' ? content : 'content';
var searchFocused = $('input[name="search"]').is(':focus');
if (activeRequest) {
activeRequest.abort();
}
$('.loading').show();
$.ajax({
activeRequest = $.ajax({
type: "GET",
url: filename,
contentType: false,
headers: {'X-Requested-With': 'XMLHttpRequest'},
success: function (data) {
activeRequest = null;
$("#" + content).html(data);
$('.loading').hide();
if (searchFocused) {
var input = $('input[name="search"]');
input.focus();
var len = input.val().length;
input[0].setSelectionRange(len, len);
}
},
error: function (xhr, status, error) {
alert(xhr.responseText);
if (status !== 'abort') {
alert(xhr.responseText);
}
}
});
}