const ICONOS = [
'restaurant','home','directions_car','bolt','movie','shopping_bag',
'local_grocery_store','medical_services','school','flight','sports_esports',
'coffee','fitness_center','pets','phone_android','work','savings','credit_card',
'local_gas_station','music_note','sports_soccer','family_restroom',
'local_pharmacy','computer','child_care','celebration','beach_access',
'attach_money','bar_chart','payments'
];
const COLORES = [
'#005050','#4d6357','#264b5c','#3e4948','#006a6a','#2d6a4f',
'#c0392b','#e67e22','#8b6914','#2980b9','#6c3483','#555555'
];
let editandoId = null;
let iconoSelecto = ICONOS[0];
let colorSelecto = COLORES[0];
// ─── Inicialización ───────────────────────────────────────────────
document.addEventListener('DOMContentLoaded', () => {
renderIconGrid();
renderColorGrid();
document.getElementById('drawer-nombre').addEventListener('input', actualizarPreview);
document.getElementById('drawer-save').addEventListener('click', guardar);
cargarCategorias();
});
// ─── Cargar y renderizar lista ────────────────────────────────────
async function cargarCategorias() {
const r = await apiFetch('api/categorias.php');
if (!r) return;
const data = await r.json();
document.getElementById('ui-loading').classList.add('hidden');
const lista = document.getElementById('ui-lista');
if (!data.categorias.length) {
lista.classList.remove('hidden');
lista.innerHTML = `
`;
return;
}
lista.classList.remove('hidden');
lista.innerHTML = data.categorias.map(c => {
const tieneMovs = parseInt(c.total_movimientos) > 0;
return `
${c.icono}
${c.nombre}
${c.total_movimientos} movimiento${c.total_movimientos != 1 ? 's' : ''}
`;
}).join('');
}
// ─── Drawer ───────────────────────────────────────────────────────
function abrirDrawer(cat) {
editandoId = cat ? cat.id : null;
iconoSelecto = cat ? cat.icono : ICONOS[0];
colorSelecto = cat ? cat.color_hex : COLORES[0];
document.getElementById('drawer-title').textContent = cat ? 'Editar categoría' : 'Nueva categoría';
document.getElementById('drawer-nombre').value = cat ? cat.nombre : '';
actualizarSeleccionIcono();
actualizarSeleccionColor();
actualizarPreview();
document.getElementById('drawer-overlay').classList.remove('hidden');
const drawer = document.getElementById('drawer');
drawer.classList.remove('translate-y-full','md:translate-x-full');
setTimeout(() => document.getElementById('drawer-nombre').focus(), 300);
}
function cerrarDrawer() {
document.getElementById('drawer-overlay').classList.add('hidden');
const drawer = document.getElementById('drawer');
drawer.classList.add('translate-y-full','md:translate-x-full');
}
// ─── Íconos ───────────────────────────────────────────────────────
function renderIconGrid() {
document.getElementById('icon-grid').innerHTML = ICONOS.map(ic => `
`).join('');
}
function seleccionarIcono(ic) {
iconoSelecto = ic;
actualizarSeleccionIcono();
actualizarPreview();
}
function actualizarSeleccionIcono() {
document.querySelectorAll('#icon-grid button').forEach(b => {
const ic = b.id.replace('ico-', '');
b.classList.toggle('bg-primary/10', ic === iconoSelecto);
b.classList.toggle('border-primary', ic === iconoSelecto);
b.querySelector('span').style.color = ic === iconoSelecto ? '#005050' : '';
});
}
// ─── Colores ──────────────────────────────────────────────────────
function renderColorGrid() {
document.getElementById('color-grid').innerHTML = COLORES.map(col => `
`).join('');
}
function seleccionarColor(col) {
colorSelecto = col;
actualizarSeleccionColor();
actualizarPreview();
}
function actualizarSeleccionColor() {
document.querySelectorAll('#color-grid button').forEach(b => {
const col = '#' + b.id.replace('col-', '');
b.style.outline = col === colorSelecto ? `3px solid ${col}` : 'none';
b.style.outlineOffset = '2px';
});
}
// ─── Preview ──────────────────────────────────────────────────────
function actualizarPreview() {
const nombre = document.getElementById('drawer-nombre').value.trim() || 'Vista previa';
document.getElementById('preview-nombre').textContent = nombre;
document.getElementById('preview-icono').style.background = colorSelecto;
document.getElementById('preview-icono-sym').textContent = iconoSelecto;
}
// ─── Guardar ──────────────────────────────────────────────────────
async function guardar() {
const nombre = document.getElementById('drawer-nombre').value.trim();
if (!nombre) {
rmModal.alert('El nombre de la categoría no puede estar vacío.', 'Campo requerido');
return;
}
const btn = document.getElementById('drawer-save');
btn.disabled = true; btn.textContent = 'Guardando…';
const payload = { nombre, icono: iconoSelecto, color_hex: colorSelecto };
const method = editandoId ? 'PUT' : 'POST';
if (editandoId) payload.id = editandoId;
try {
const r = await apiFetch('api/categorias.php', {
method,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
if (!r) return;
const data = await r.json();
if (data.status === 'success') {
cerrarDrawer();
rmModal.toast(editandoId ? 'Categoría actualizada' : 'Categoría creada');
await cargarCategorias();
} else {
await rmModal.alert(data.message, 'Error');
}
} catch {
await rmModal.alert('Error de conexión', 'Error');
} finally {
btn.disabled = false; btn.textContent = 'Guardar';
}
}
// ─── Eliminar ─────────────────────────────────────────────────────
async function eliminar(id, nombre) {
const ok = await rmModal.confirm(`¿Eliminar la categoría "${nombre}"?`, 'Eliminar categoría');
if (!ok) return;
const r = await apiFetch('api/categorias.php', {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ id })
});
if (!r) return;
const data = await r.json();
if (data.status === 'success') {
rmModal.toast('Categoría eliminada');
await cargarCategorias();
} else {
rmModal.toast(data.message, 'error');
}
}