Refactor manejo de URL para eliminar parámetros de búsqueda en la navegación y mejorar la visibilidad de personas en formularios

This commit is contained in:
Naiel
2026-02-23 12:38:28 +00:00
parent 9ab0472e2a
commit 75947d3468
8 changed files with 133 additions and 22 deletions

View File

@@ -52,7 +52,7 @@ function setUrlHash(hash) {
} }
} }
window.onhashchange = () => { window.onhashchange = () => {
open_page(location.hash.replace('#', '')); open_page(location.hash.replace('#', '').split("?")[0]);
}; };
function download(filename, text) { function download(filename, text) {

View File

@@ -621,7 +621,8 @@ function addCategory_Personas(
change_cb = () => {}, change_cb = () => {},
label = 'Persona', label = 'Persona',
open_default = false, open_default = false,
default_empty_text = '- Lista Vacia -' default_empty_text = '- Lista Vacia -',
show_hidden = false,
) { ) {
var details_0 = document.createElement('details'); // children: img_0, summary_0 var details_0 = document.createElement('details'); // children: img_0, summary_0
//details_0.open = true; //details_0.open = true;
@@ -670,6 +671,7 @@ function addCategory_Personas(
.map((entry) => { .map((entry) => {
var key = entry['_key']; var key = entry['_key'];
var value = entry; var value = entry;
if (value.Oculto == true && !show_hidden) { return; }
if (lastreg != value.Region.toUpperCase()) { if (lastreg != value.Region.toUpperCase()) {
lastreg = value.Region.toUpperCase(); lastreg = value.Region.toUpperCase();
var h3_0 = document.createElement('h2'); var h3_0 = document.createElement('h2');
@@ -1218,6 +1220,7 @@ function TS_IndexElement(
id="${searchKeyInput}" id="${searchKeyInput}"
placeholder="🔍 Buscar..." placeholder="🔍 Buscar..."
style="width: calc(100% - 18px); padding: 8px; border: 1px solid #ccc; border-radius: 4px; background-color: rebeccapurple; color: white;" style="width: calc(100% - 18px); padding: 8px; border: 1px solid #ccc; border-radius: 4px; background-color: rebeccapurple; color: white;"
value=""
/> />
</th> </th>
</tr> </tr>
@@ -1237,7 +1240,11 @@ function TS_IndexElement(
// Add search functionality // Add search functionality
const searchKeyEl = document.getElementById(searchKeyInput); const searchKeyEl = document.getElementById(searchKeyInput);
searchKeyEl.addEventListener('input', () => debounce(debounce_search, render, 200, [rows])); searchKeyEl.addEventListener('input', () => debounce(debounce_search, render, 200, [rows]));
// If there is a preset search value in URL, apply it
var hashQuery = new URLSearchParams(window.location.hash.split('?')[1]);
if (hashQuery.has('search')) {
searchKeyEl.value = hashQuery.get('search');
}
function searchInData(data, searchValue, config) { function searchInData(data, searchValue, config) {
if (!searchValue) return true; if (!searchValue) return true;
@@ -1846,7 +1853,7 @@ var BootIntervalID = setInterval(() => {
SUB_LOGGED_IN = true; SUB_LOGGED_IN = true;
localStorage.setItem('TELESEC_BYPASS_ID', SUB_LOGGED_IN_ID); localStorage.setItem('TELESEC_BYPASS_ID', SUB_LOGGED_IN_ID);
SetPages(); SetPages();
open_page(location.hash.replace('#', '')); open_page(location.hash.replace('#', '').split("?")[0]);
} }
if (!data) { if (!data) {
const persona = { Nombre: 'Admin (bypass)', Roles: 'ADMIN,' }; const persona = { Nombre: 'Admin (bypass)', Roles: 'ADMIN,' };
@@ -1883,7 +1890,7 @@ var BootIntervalID = setInterval(() => {
} }
} else { } else {
SetPages(); SetPages();
open_page(location.hash.replace('#', '')); open_page(location.hash.replace('#', '').split("?")[0]);
} }
clearInterval(BootIntervalID); clearInterval(BootIntervalID);
} }

View File

@@ -82,7 +82,7 @@ if (urlParams.get('couch') != null) {
history.replaceState( history.replaceState(
null, null,
'', '',
location.pathname + (urlParams.toString() ? '?' + urlParams.toString() : '') + location.hash location.pathname + (urlParams.toString() ? '?' + urlParams.toString() : '') + location.hash.split("?")[0]
); );
console.log('CouchDB auto-configured from URL parameter'); console.log('CouchDB auto-configured from URL parameter');

View File

@@ -456,7 +456,7 @@ Cargando...</pre
setUrlHash('index'); setUrlHash('index');
return; return;
} }
var item = location.hash.replace('#', '').split(',')[2]; var item = location.hash.replace('#', '').split("?")[0].split(',')[2];
if (!item) { if (!item) {
// No item, show section // No item, show section
switch (section) { switch (section) {

View File

@@ -634,7 +634,7 @@ PAGES.cajas = {
} }
// Check for special routes // Check for special routes
var parts = location.hash.split(','); var parts = location.hash.split("?")[0].split(',');
if (parts[2] === 'movimientos' && parts[3] === '_nuevo') { if (parts[2] === 'movimientos' && parts[3] === '_nuevo') {
PAGES.cajas.nuevo_movimiento(parts[1]); PAGES.cajas.nuevo_movimiento(parts[1]);
return; return;

View File

@@ -421,11 +421,11 @@ PAGES.login = {
SUB_LOGGED_IN_DETAILS = SC_Personas[SUB_LOGGED_IN_ID]; SUB_LOGGED_IN_DETAILS = SC_Personas[SUB_LOGGED_IN_ID];
SUB_LOGGED_IN = true; SUB_LOGGED_IN = true;
SetPages(); SetPages();
if (location.hash.replace('#', '').startsWith('login')) { if (location.hash.replace('#', '').split("?")[0].startsWith('login')) {
open_page('index'); open_page('index');
setUrlHash('index'); setUrlHash('index');
} else { } else {
open_page(location.hash.replace('#', '')); open_page(location.hash.replace('#', '').split("?")[0]);
} }
}; };

View File

@@ -5,6 +5,78 @@ PAGES.pagos = {
icon: 'static/appico/credit_cards.png', icon: 'static/appico/credit_cards.png',
AccessControl: true, AccessControl: true,
Title: 'Pagos', Title: 'Pagos',
CajaCafeID: 'caja_cafe',
CajaCafeNombre: 'Caja Café',
__getVisiblePersonas: function () {
return Object.fromEntries(
Object.entries(SC_Personas).filter(([_, persona]) => !(persona && persona.Oculto === true))
);
},
__ensureCajaCafePersona: function () {
var cajaId = PAGES.pagos.CajaCafeID;
var cajaNombre = PAGES.pagos.CajaCafeNombre;
var existing = SC_Personas[cajaId];
if (existing && existing.Nombre === cajaNombre && existing.Oculto === true) {
return Promise.resolve(cajaId);
}
var data = {
Nombre: cajaNombre,
Region: 'Sistema',
Roles: '',
SC_Anilla: '',
markdown: 'Monedero interno de cafetería',
Monedero_Balance: parseFloat((existing && existing.Monedero_Balance) || 0) || 0,
Monedero_Notas: (existing && existing.Monedero_Notas) || '',
Oculto: true,
};
return DB.put('personas', cajaId, data)
.then(() => {
SC_Personas[cajaId] = data;
return cajaId;
})
.catch((e) => {
console.warn('DB.put error', e);
return null;
});
},
__creditCajaCafeForGasto: function (personaOrigenId, monto, callback) {
var cajaId = PAGES.pagos.CajaCafeID;
if (personaOrigenId === cajaId) {
if (callback) callback();
return;
}
PAGES.pagos.__ensureCajaCafePersona().then((resolvedCajaId) => {
if (!resolvedCajaId) {
if (callback) callback();
return;
}
var caja = SC_Personas[resolvedCajaId];
if (!caja) {
if (callback) callback();
return;
}
var currentBalance = parseFloat(caja.Monedero_Balance || 0);
caja.Monedero_Balance = fixfloat(currentBalance + monto);
DB.put('personas', resolvedCajaId, caja)
.then(() => {
if (callback) callback();
})
.catch((e) => {
console.warn('DB.put error', e);
if (callback) callback();
});
});
},
// Datafono view for creating/processing transactions // Datafono view for creating/processing transactions
datafono: function (prefilledData = {}) { datafono: function (prefilledData = {}) {
@@ -32,6 +104,8 @@ PAGES.pagos = {
sessionStorage.removeItem('pagos_scanned_persona'); sessionStorage.removeItem('pagos_scanned_persona');
} }
PAGES.pagos.__ensureCajaCafePersona();
var field_tipo = safeuuid(); var field_tipo = safeuuid();
var field_monto = safeuuid(); var field_monto = safeuuid();
var field_persona = safeuuid(); var field_persona = safeuuid();
@@ -413,9 +487,10 @@ PAGES.pagos = {
var container = document.querySelector('#personaSelector'); var container = document.querySelector('#personaSelector');
container.innerHTML = ''; container.innerHTML = '';
document.getElementById(field_persona).value = selectedPersona; document.getElementById(field_persona).value = selectedPersona;
var visiblePersonas = PAGES.pagos.__getVisiblePersonas();
addCategory_Personas( addCategory_Personas(
container, container,
SC_Personas, visiblePersonas,
selectedPersona, selectedPersona,
(personaId) => { (personaId) => {
document.getElementById(field_persona).value = personaId; document.getElementById(field_persona).value = personaId;
@@ -431,9 +506,10 @@ PAGES.pagos = {
var container = document.querySelector('#personaDestinoSelector'); var container = document.querySelector('#personaDestinoSelector');
container.innerHTML = ''; container.innerHTML = '';
document.getElementById(field_persona_destino).value = selectedPersonaDestino; document.getElementById(field_persona_destino).value = selectedPersonaDestino;
var visiblePersonas = PAGES.pagos.__getVisiblePersonas();
addCategory_Personas( addCategory_Personas(
container, container,
SC_Personas, visiblePersonas,
selectedPersonaDestino, selectedPersonaDestino,
(personaId) => { (personaId) => {
document.getElementById(field_persona_destino).value = personaId; document.getElementById(field_persona_destino).value = personaId;
@@ -498,20 +574,30 @@ PAGES.pagos = {
// Don't update balance for Efectivo Gastos (paying with cash) // Don't update balance for Efectivo Gastos (paying with cash)
var shouldUpdateBalance = !(tipo === 'Gasto' && metodo === 'Efectivo'); var shouldUpdateBalance = !(tipo === 'Gasto' && metodo === 'Efectivo');
if (shouldUpdateBalance) { function finalizeTransactionSave() {
updateWalletBalance(personaId, tipo, monto, () => { if (tipo === 'Gasto') {
if (tipo === 'Transferencia') { PAGES.pagos.__creditCajaCafeForGasto(personaId, monto, () => {
var destinoId = transactionData.PersonaDestino;
updateWalletBalance(destinoId, 'Ingreso', monto, () => {
saveTransaction(ticketId, transactionData); saveTransaction(ticketId, transactionData);
}); });
} else { } else {
saveTransaction(ticketId, transactionData); saveTransaction(ticketId, transactionData);
} }
}
if (shouldUpdateBalance) {
updateWalletBalance(personaId, tipo, monto, () => {
if (tipo === 'Transferencia') {
var destinoId = transactionData.PersonaDestino;
updateWalletBalance(destinoId, 'Ingreso', monto, () => {
finalizeTransactionSave();
});
} else {
finalizeTransactionSave();
}
}); });
} else { } else {
// Skip balance update for Efectivo Gastos // Skip balance update for Efectivo Gastos
saveTransaction(ticketId, transactionData); finalizeTransactionSave();
} }
} }
@@ -666,7 +752,7 @@ PAGES.pagos = {
return; return;
} }
var tid = ftid.split(',')[0]; var tid = ftid.split(',')[0];
var tid2 = location.hash.split(','); var tid2 = location.hash.split("?")[0].split(',');
if (tid == 'datafono') { if (tid == 'datafono') {
PAGES.pagos.datafono(); PAGES.pagos.datafono();
return; return;
@@ -929,7 +1015,14 @@ PAGES.pagos = {
}); });
} else if (tipo === 'Gasto') { } else if (tipo === 'Gasto') {
revertWalletBalance(personaId, 'Ingreso', monto, () => { revertWalletBalance(personaId, 'Ingreso', monto, () => {
var cajaId = PAGES.pagos.CajaCafeID;
if (personaId === cajaId) {
deleteTransaction(tid); deleteTransaction(tid);
return;
}
revertWalletBalance(cajaId, 'Gasto', monto, () => {
deleteTransaction(tid);
});
}); });
} else if (tipo === 'Transferencia') { } else if (tipo === 'Transferencia') {
var destinoId = data.PersonaDestino; var destinoId = data.PersonaDestino;
@@ -994,6 +1087,8 @@ PAGES.pagos = {
return; return;
} }
PAGES.pagos.__ensureCajaCafePersona();
var btn_datafono = safeuuid(); var btn_datafono = safeuuid();
var total_ingresos = safeuuid(); var total_ingresos = safeuuid();
var total_gastos = safeuuid(); var total_gastos = safeuuid();
@@ -1276,6 +1371,8 @@ PAGES.pagos = {
return; return;
} }
PAGES.pagos.__ensureCajaCafePersona();
var field_tipo = safeuuid(); var field_tipo = safeuuid();
var field_monto = safeuuid(); var field_monto = safeuuid();
var field_persona = safeuuid(); var field_persona = safeuuid();
@@ -1440,9 +1537,10 @@ PAGES.pagos = {
var container = document.querySelector('#personaSelector'); var container = document.querySelector('#personaSelector');
container.innerHTML = ''; container.innerHTML = '';
document.getElementById(field_persona).value = selectedPersona; document.getElementById(field_persona).value = selectedPersona;
var visiblePersonas = PAGES.pagos.__getVisiblePersonas();
addCategory_Personas( addCategory_Personas(
container, container,
SC_Personas, visiblePersonas,
selectedPersona, selectedPersona,
(personaId) => { (personaId) => {
document.getElementById(field_persona).value = personaId; document.getElementById(field_persona).value = personaId;
@@ -1458,9 +1556,10 @@ PAGES.pagos = {
var container = document.querySelector('#personaDestinoSelector'); var container = document.querySelector('#personaDestinoSelector');
container.innerHTML = ''; container.innerHTML = '';
document.getElementById(field_persona_destino).value = selectedPersonaDestino; document.getElementById(field_persona_destino).value = selectedPersonaDestino;
var visiblePersonas = PAGES.pagos.__getVisiblePersonas();
addCategory_Personas( addCategory_Personas(
container, container,
SC_Personas, visiblePersonas,
selectedPersonaDestino, selectedPersonaDestino,
(personaId) => { (personaId) => {
document.getElementById(field_persona_destino).value = personaId; document.getElementById(field_persona_destino).value = personaId;

View File

@@ -17,6 +17,7 @@ PAGES.personas = {
var field_notas = safeuuid(); var field_notas = safeuuid();
var field_anilla = safeuuid(); var field_anilla = safeuuid();
var field_foto = safeuuid(); var field_foto = safeuuid();
var field_oculto = safeuuid();
var render_foto = safeuuid(); var render_foto = safeuuid();
var field_monedero_balance = safeuuid(); var field_monedero_balance = safeuuid();
var field_monedero_notas = safeuuid(); var field_monedero_notas = safeuuid();
@@ -35,7 +36,6 @@ PAGES.personas = {
Zona<br> Zona<br>
<input type="text" id="${field_zona}"><br><br> <input type="text" id="${field_zona}"><br><br>
</label> </label>
</label>
<details> <details>
<summary>Permisos</summary> <summary>Permisos</summary>
<form id="${permisosdet}"> <form id="${permisosdet}">
@@ -50,7 +50,10 @@ PAGES.personas = {
<img id="${render_foto}" height="100px" style="border: 3px inset; min-width: 7px;" src="static/ico/user_generic.png"> <img id="${render_foto}" height="100px" style="border: 3px inset; min-width: 7px;" src="static/ico/user_generic.png">
<input type="file" accept="image/*" id="${field_foto}" style="display: none;"><br><br> <input type="file" accept="image/*" id="${field_foto}" style="display: none;"><br><br>
</label> </label>
<label>
Ocultar persona?<br>
<input type="checkbox" id="${field_oculto}"><br><br>
</label>
<details style="background: #e3f2fd; border: 2px solid #2196f3; border-radius: 8px; padding: 10px; margin: 15px 0;"> <details style="background: #e3f2fd; border: 2px solid #2196f3; border-radius: 8px; padding: 10px; margin: 15px 0;">
<summary style="cursor: pointer; font-weight: bold; color: #1976d2;">💳 Tarjeta Monedero</summary> <summary style="cursor: pointer; font-weight: bold; color: #1976d2;">💳 Tarjeta Monedero</summary>
<div style="padding: 15px;"> <div style="padding: 15px;">
@@ -110,6 +113,7 @@ PAGES.personas = {
document.getElementById(field_nombre).value = data['Nombre'] || ''; document.getElementById(field_nombre).value = data['Nombre'] || '';
document.getElementById(field_zona).value = data['Region'] || ''; document.getElementById(field_zona).value = data['Region'] || '';
document.getElementById(field_anilla).value = data['SC_Anilla'] || ''; document.getElementById(field_anilla).value = data['SC_Anilla'] || '';
document.getElementById(field_oculto).checked = data['Oculto'] || false;
// set fallback image immediately // set fallback image immediately
document.getElementById(render_foto).src = data['Foto'] || 'static/ico/user_generic.png'; document.getElementById(render_foto).src = data['Foto'] || 'static/ico/user_generic.png';
resized = data['Foto'] || 'static/ico/user_generic.png'; resized = data['Foto'] || 'static/ico/user_generic.png';
@@ -166,6 +170,7 @@ PAGES.personas = {
Region: document.getElementById(field_zona).value, Region: document.getElementById(field_zona).value,
Roles: dt.getAll('perm').join(',') + ',', Roles: dt.getAll('perm').join(',') + ',',
SC_Anilla: document.getElementById(field_anilla).value, SC_Anilla: document.getElementById(field_anilla).value,
Oculto: document.getElementById(field_oculto).checked,
// Foto moved to PouchDB attachment named 'foto' // Foto moved to PouchDB attachment named 'foto'
markdown: document.getElementById(field_notas).value, markdown: document.getElementById(field_notas).value,
Monedero_Balance: parseFloat(document.getElementById(field_monedero_balance).value) || 0, Monedero_Balance: parseFloat(document.getElementById(field_monedero_balance).value) || 0,
@@ -204,7 +209,7 @@ PAGES.personas = {
}); });
}; };
document.getElementById(btn_ver_monedero).onclick = () => { document.getElementById(btn_ver_monedero).onclick = () => {
setUrlHash('pagos'); // Navigate to pagos and show transactions for this person setUrlHash('pagos?search=' + encodeURIComponent(document.getElementById(field_nombre).value)); // Navigate to pagos and show transactions for this person
}; };
document.getElementById(btn_borrar).onclick = () => { document.getElementById(btn_borrar).onclick = () => {
if (confirm('¿Quieres borrar esta persona?') == true) { if (confirm('¿Quieres borrar esta persona?') == true) {