Files
rm-PAGOs/pagos/js/add.js
T
Ricardo Monla b78bd3ecdd Refactor: categorías server-side en add.php, elimina fetch async en add.js
- pagos/add.php: nueva página que renderiza el formulario de alta con las
  categorías ya cargadas desde PHP/SQLite, sin depender de un fetch
  asíncrono a api/categorias.php tras cargar la página.
- pagos/js/add.js: quita cargarCategorias() y la llamada a apiFetch, ya
  innecesarias con el nuevo flujo server-side.
- CLAUDE.md: documentar remote real (Gitea, no GitHub), stack técnico y
  estructura del proyecto.
2026-07-10 13:41:00 -03:00

101 lines
4.1 KiB
JavaScript

document.addEventListener('DOMContentLoaded', () => {
let currentMonto = "0";
let selectedTipo = "gasto";
// Hay dos displays de monto (desktop / mobile) y dos botones guardar
const montoEls = ['ui-monto', 'ui-monto-mobile'].map(id => document.getElementById(id)).filter(Boolean);
const btnGasto = document.getElementById('btn-gasto');
const btnIngreso = document.getElementById('btn-ingreso');
const numpad = document.getElementById('ui-numpad');
const iptFecha = document.getElementById('ui-fecha');
const saveButtons = ['btn-save', 'btn-save-mobile'].map(id => document.getElementById(id)).filter(Boolean);
// Default a hoy
iptFecha.valueAsDate = new Date();
// Categorías ya vienen renderizadas por PHP (add.php)
// Tipo selector
const updateTipoUI = () => {
const isGasto = selectedTipo === 'gasto';
btnGasto.classList.toggle('bg-surface-container-lowest', isGasto);
btnGasto.classList.toggle('text-primary', isGasto);
btnGasto.classList.toggle('shadow-sm', isGasto);
btnGasto.classList.toggle('text-on-surface-variant', !isGasto);
btnIngreso.classList.toggle('bg-surface-container-lowest', !isGasto);
btnIngreso.classList.toggle('text-primary', !isGasto);
btnIngreso.classList.toggle('shadow-sm', !isGasto);
btnIngreso.classList.toggle('text-on-surface-variant', isGasto);
};
btnGasto.addEventListener('click', () => { selectedTipo = 'gasto'; updateTipoUI(); });
btnIngreso.addEventListener('click', () => { selectedTipo = 'ingreso'; updateTipoUI(); });
// Numpad
function applyInput(val) {
if (val === 'backspace') {
currentMonto = currentMonto.slice(0, -1) || "0";
} else if (/^[0-9]$/.test(val)) {
currentMonto = currentMonto === "0" ? val : currentMonto + val;
} else if (val === '.') {
if (!currentMonto.includes('.')) currentMonto += '.';
}
montoEls.forEach(el => el.textContent = currentMonto);
}
numpad.addEventListener('click', (e) => {
const btn = e.target.closest('button');
if (!btn) return;
applyInput(btn.querySelector('[data-icon="backspace"]') ? 'backspace' : btn.textContent.trim());
});
// Teclado físico
document.addEventListener('keydown', (e) => {
if (document.activeElement.tagName === 'INPUT') return;
if (e.key >= '0' && e.key <= '9') applyInput(e.key);
else if (e.key === '.' || e.key === ',') applyInput('.');
else if (e.key === 'Backspace') applyInput('backspace');
else if (e.key === 'Enter') doSave();
});
// Guardar
async function doSave() {
const payload = {
tipo: selectedTipo,
monto: parseFloat(currentMonto),
fecha: iptFecha.value,
notas: document.getElementById('ui-notas').value,
id_categoria: document.getElementById('ui-categoria').value
};
if (isNaN(payload.monto) || payload.monto <= 0) {
rmModal.alert('Ingresá un monto mayor a 0.', 'Monto inválido');
return;
}
saveButtons.forEach(b => { b.disabled = true; b.textContent = 'Guardando…'; });
try {
const r = await apiFetch('api/movimientos.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
if (!r) return;
const data = await r.json();
if (data.status === 'success') {
window.location.href = 'index.html';
} else {
await rmModal.alert(data.message, 'Error al guardar');
saveButtons.forEach(b => { b.disabled = false; b.textContent = 'Guardar Movimiento'; });
}
} catch (err) {
console.error(err);
await rmModal.alert('No se pudo conectar con el servidor.', 'Error de conexión');
saveButtons.forEach(b => { b.disabled = false; b.textContent = 'Guardar Movimiento'; });
}
}
saveButtons.forEach(btn => btn.addEventListener('click', doSave));
});