feat: Añadir modo de revisión y mejorar la retroalimentación en el panel

This commit is contained in:
Naiel
2026-02-24 12:17:26 +00:00
parent 09a9a95df0
commit 382e31158a
2 changed files with 51 additions and 102 deletions

View File

@@ -5,8 +5,6 @@ PAGES.pagos = {
icon: 'static/appico/credit_cards.png',
AccessControl: true,
Title: 'Pagos',
CajaCafeID: 'caja_cafe',
CajaCafeNombre: 'Caja Café',
__getVisiblePersonas: function () {
return Object.fromEntries(
@@ -14,70 +12,6 @@ PAGES.pagos = {
);
},
__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: function (prefilledData = {}) {
if (!checkRole('pagos:edit')) {
@@ -104,8 +38,6 @@ PAGES.pagos = {
sessionStorage.removeItem('pagos_scanned_persona');
}
PAGES.pagos.__ensureCajaCafePersona();
var field_tipo = safeuuid();
var field_monto = safeuuid();
var field_persona = safeuuid();
@@ -577,13 +509,7 @@ PAGES.pagos = {
var shouldUpdateBalance = !(tipo === 'Gasto' && metodo === 'Efectivo');
function finalizeTransactionSave() {
if (tipo === 'Gasto') {
PAGES.pagos.__creditCajaCafeForGasto(personaId, monto, () => {
saveTransaction(ticketId, transactionData);
});
} else {
saveTransaction(ticketId, transactionData);
}
saveTransaction(ticketId, transactionData);
}
if (shouldUpdateBalance) {
@@ -1017,14 +943,7 @@ PAGES.pagos = {
});
} else if (tipo === 'Gasto') {
revertWalletBalance(personaId, 'Ingreso', monto, () => {
var cajaId = PAGES.pagos.CajaCafeID;
if (personaId === cajaId) {
deleteTransaction(tid);
return;
}
revertWalletBalance(cajaId, 'Gasto', monto, () => {
deleteTransaction(tid);
});
deleteTransaction(tid);
});
} else if (tipo === 'Transferencia') {
var destinoId = data.PersonaDestino;
@@ -1089,8 +1008,6 @@ PAGES.pagos = {
return;
}
PAGES.pagos.__ensureCajaCafePersona();
var btn_datafono = safeuuid();
var total_ingresos = safeuuid();
var total_gastos = safeuuid();
@@ -1373,8 +1290,6 @@ PAGES.pagos = {
return;
}
PAGES.pagos.__ensureCajaCafePersona();
var field_tipo = safeuuid();
var field_monto = safeuuid();
var field_persona = safeuuid();

View File

@@ -276,6 +276,8 @@ PAGES.panel = {
answers: {},
score: 0,
feedback: '',
feedbackType: '',
reviewMode: false,
};
function saveResult() {
@@ -299,16 +301,36 @@ PAGES.panel = {
.map((option, i) => {
var oid = safeuuid();
var checked = selected === option ? 'checked' : '';
var disabled = state.reviewMode ? 'disabled' : '';
var optionStyle =
'display:block;margin: 8px 0;padding: 8px;border: 1px solid #ccc;border-radius: 6px;cursor:pointer;max-width: 150px;text-align: center;';
if (state.reviewMode) {
if (option === q.correct) {
optionStyle =
'display:block;margin: 8px 0;padding: 8px;border: 2px solid #2ed573;background:#eafff1;border-radius: 6px;cursor:pointer;max-width: 150px;text-align: center;';
} else if (option === selected && option !== q.correct) {
optionStyle =
'display:block;margin: 8px 0;padding: 8px;border: 2px solid #ff4757;background:#ffecec;border-radius: 6px;cursor:pointer;max-width: 150px;text-align: center;';
}
}
var optionContent = PAGES.panel.__renderOptionContent(q, option);
return `
<label class="panel-option" for="${oid}" style="display:block;margin: 8px 0;padding: 8px;border: 1px solid #ccc;border-radius: 6px;cursor:pointer;max-width: 150px;text-align: center;">
<input id="${oid}" type="radio" name="panel-question" value="${option.replace(/"/g, '&quot;')}" ${checked} />
<label class="panel-option" for="${oid}" style="${optionStyle}">
<input id="${oid}" type="radio" name="panel-question" value="${option.replace(/"/g, '&quot;')}" ${checked} ${disabled} />
${optionContent}
</label>
`;
})
.join('');
var feedbackColor = '#555';
if (state.feedbackType === 'ok') feedbackColor = '#1f8f4a';
if (state.feedbackType === 'bad') feedbackColor = '#c0392b';
var nextButtonText = state.reviewMode ? 'Continuar' : 'Comprobar';
target.innerHTML = html`
<fieldset style="max-width: 800px;">
<legend>Pregunta ${state.idx + 1} de ${questions.length}</legend>
@@ -318,9 +340,9 @@ PAGES.panel = {
${ctx.comedor.postre || '—'}
</small>
<div style="margin-top: 10px; display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 8px;">${optionsHtml}</div>
<div id="panel-feedback" style="margin-top: 12px;"><i>${state.feedback || ''}</i></div>
<div id="panel-feedback" style="margin-top: 12px; color:${feedbackColor};"><i>${state.feedback || ''}</i></div>
<div style="margin-top: 12px; display:flex; gap:8px;">
<button class="btn5" id="panel-next">Comprobar y continuar</button>
<button class="btn5" id="panel-next">${nextButtonText}</button>
<button id="panel-cancel">Salir</button>
</div>
</fieldset>
@@ -328,9 +350,26 @@ PAGES.panel = {
document.getElementById('panel-cancel').onclick = () => setUrlHash('index');
document.getElementById('panel-next').onclick = () => {
if (state.reviewMode) {
state.reviewMode = false;
state.feedback = '';
state.feedbackType = '';
if (state.idx < questions.length - 1) {
state.idx++;
renderCurrent();
return;
}
saveResult();
renderFinal();
return;
}
var checked = document.querySelector('input[name="panel-question"]:checked');
if (!checked) {
state.feedback = 'Selecciona una opción antes de continuar.';
state.feedbackType = 'bad';
renderCurrent();
return;
}
@@ -342,21 +381,14 @@ PAGES.panel = {
if (wasCorrect) {
state.score++;
state.feedback = '✅ ' + q.ok;
state.feedbackType = 'ok';
} else {
state.feedback = '❌ ' + q.bad + ' Respuesta esperada: ' + q.correct;
state.feedbackType = 'bad';
}
if (state.idx < questions.length - 1) {
state.idx++;
setTimeout(() => {
state.feedback = '';
renderCurrent();
}, 350);
return;
}
saveResult();
renderFinal();
state.reviewMode = true;
renderCurrent();
};
}
@@ -383,6 +415,8 @@ PAGES.panel = {
state.answers = {};
state.score = 0;
state.feedback = '';
state.feedbackType = '';
state.reviewMode = false;
renderCurrent();
};
document.getElementById('panel-home').onclick = () => setUrlHash('index');