- Configuración + Configuración Avanzada
Selecciona una provincia
Selecciona una zona
@@ -123,7 +123,7 @@Selecciona una zona
'; loadZones(id); } @@ -197,19 +198,19 @@ const list = document.getElementById('listZones'); list.innerHTML = ""; - if(data.zones.length === 0) list.innerHTML = 'No hay zonas. Crea una.
'; + if(data.zones.length === 0) list.innerHTML = 'No hay zonas definidas en esta provincia.
'; data.zones.forEach(z => { const div = document.createElement('div'); - div.className = "p-3 border border-gray-100 rounded hover:border-blue-300 cursor-pointer bg-white mb-2 zone-item"; - let townsText = z.towns_names && z.towns_names.length > 0 ? z.towns_names.join(", ") : "Sin poblaciones"; + div.className = "p-3 border border-gray-100 rounded hover:border-blue-300 hover:shadow-sm cursor-pointer bg-white zone-item transition-all"; + let townsText = z.towns_names && z.towns_names.length > 0 ? z.towns_names.join(", ") : "Sin poblaciones asignadas"; div.innerHTML = ` -${townsText}
+${townsText}
`; div.onclick = () => selectZone(z.id, div); list.appendChild(div); @@ -221,16 +222,15 @@ if(!currentProvId) return; document.getElementById('newZoneName').value = ""; - // Cargar pueblos const res = await fetch(`${API_URL}/provinces/${currentProvId}/towns`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } }); const data = await res.json(); const list = document.getElementById('townsList'); list.innerHTML = ""; - if(data.towns.length === 0) list.innerHTML = 'No hay poblaciones cargadas.
'; + if(data.towns.length === 0) list.innerHTML = 'No hay poblaciones disponibles para esta provincia.
'; data.towns.forEach(t => { - list.innerHTML += ``; + list.innerHTML += ``; }); document.getElementById('zoneModal').classList.remove('hidden'); } @@ -240,46 +240,74 @@ const checks = document.querySelectorAll('.town-check:checked'); const townIds = Array.from(checks).map(c => c.value); - if(!name) { alert("Pon un nombre"); return; } + if(!name) { alert("Debes poner un nombre a la zona"); return; } - await fetch(`${API_URL}/zones`, { - method: 'POST', - headers: { "Content-Type": "application/json", "Authorization": `Bearer ${localStorage.getItem("token")}` }, - body: JSON.stringify({ province_id: currentProvId, name, town_ids: townIds }) - }); - - document.getElementById('zoneModal').classList.add('hidden'); - loadZones(currentProvId); + try { + const res = await fetch(`${API_URL}/zones`, { + method: 'POST', + headers: { "Content-Type": "application/json", "Authorization": `Bearer ${localStorage.getItem("token")}` }, + body: JSON.stringify({ province_id: currentProvId, name, town_ids: townIds }) + }); + if(res.ok) { + showToast("Zona creada correctamente"); + document.getElementById('zoneModal').classList.add('hidden'); + loadZones(currentProvId); + } else { showToast("Error al crear zona", true); } + } catch(e) { showToast("Error de conexión", true); } } - async function deleteZone(id) { - if(!confirm("¿Borrar zona?")) return; - await fetch(`${API_URL}/zones/${id}`, { method: 'DELETE', headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } }); - loadZones(currentProvId); + async function deleteZone(event, id) { + event.stopPropagation(); // Evita seleccionar la zona al borrar + if(!confirm("¿Estás seguro de borrar esta zona? Esta acción no se puede deshacer.")) return; + + try { + const res = await fetch(`${API_URL}/zones/${id}`, { method: 'DELETE', headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } }); + if(res.ok) { + showToast("Zona eliminada"); + loadZones(currentProvId); + // Resetear panel de operarios si estaba seleccionada esa zona + if(currentZoneId === id) { + document.getElementById('colOperators').classList.add('opacity-50', 'pointer-events-none'); + document.getElementById('listOperators').innerHTML = 'Selecciona una zona
'; + } + } else { showToast("No se pudo borrar", true); } + } catch(e) { showToast("Error de conexión", true); } } async function selectZone(id, el) { currentZoneId = id; - document.querySelectorAll('.zone-item').forEach(d => d.classList.remove('border-blue-500', 'bg-blue-50')); - el.classList.add('border-blue-500', 'bg-blue-50'); + document.querySelectorAll('.zone-item').forEach(d => d.classList.remove('border-blue-500', 'bg-blue-50', 'ring-1', 'ring-blue-500')); + el.classList.add('border-blue-500', 'bg-blue-50', 'ring-1', 'ring-blue-500'); document.getElementById('colOperators').classList.remove('opacity-50', 'pointer-events-none'); loadOperatorsForZone(id); } async function loadOperatorsForZone(zoneId) { + const list = document.getElementById('listOperators'); + list.innerHTML = 'Cargando operarios...
'; + const resOps = await fetch(`${API_URL}/operators`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } }); const dataOps = await resOps.json(); const resAssigned = await fetch(`${API_URL}/zones/${zoneId}/operators`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } }); - const dataAssigned = await resAssigned.json(); + const dataAssigned = await resAssigned.json(); const assignedSet = new Set(dataAssigned.assignedIds); - const list = document.getElementById('listOperators'); list.innerHTML = ""; + if(dataOps.operators.length === 0) { + list.innerHTML = 'No hay operarios registrados en el sistema.
'; + return; + } + dataOps.operators.forEach(op => { const checked = assignedSet.has(op.id) ? 'checked' : ''; - list.innerHTML += ``; + list.innerHTML += ` + + `; }); } @@ -292,8 +320,8 @@ headers: { "Content-Type": "application/json", "Authorization": `Bearer ${localStorage.getItem("token")}` }, body: JSON.stringify({ operator_ids: ids }) }); - showToast("Asignación guardada ✅"); - } catch(e) { showToast("Error al guardar", true); } + showToast("Asignación guardada correctamente ✅"); + } catch(e) { showToast("Error al guardar asignación", true); } } function showToast(msg, isError = false) {