COOPERATIVA DOS DE MAYO
Visor GIS Ultraliviano
⚡
Iniciando GIS...
📑 Árbol de Capas
▼
👥 10 Vecinos Más Cercanos
Socio Seleccionado
⚡ Mensaje
`); w.document.close(); } async function enviarWhatsAppDesdeMapa(posteId) { let p = listaPostesCriticosCache.find(x => x.id === posteId) || listaTodosLosPostes.find(x => x.id === posteId); if (!p) { alert('Poste no encontrado.'); return; } const cuadrillas = await cargarCuadrillasPostesSiEsNecesario(); const cuad = cuadrillas[2] || cuadrillas[0] || {}; const cod = (p.codigo && p.codigo !== 'NULL') ? p.codigo : `PST-${p.id}`; const nom = (p.nombre && p.nombre !== 'NULL') ? p.nombre : `Poste #${p.id}`; let tel = cuad.telefono_cabecilla || '5493755496011'; const msg = `🚨 *COOPERATIVA DOS DE MAYO - ORDEN DE RECAMBIO DE POSTE* 🚨\n🛠️ *RIESGO CRÍTICO*\n━━━━━━━━━━━━━━━━━━━━━━━\n📋 *Orden:* OT-PST-${p.id}\n🪵 *Poste:* ${nom} (${cod})\n⚡ *Capa:* ${p.capa || 'RED_BT'} | *Material:* ${p.material} (${p.altura_m}m)\n⚠️ *Falla:* ${p.observaciones}\n📍 *GPS:* ${p.lat.toFixed(5)}, ${p.lng.toFixed(5)}\n🧭 *Google Maps:* https://www.google.com/maps?q=${p.lat},${p.lng}\n👷 *Cuadrilla:* ${cuad.nombre || 'Guardia de Redes'}\n🚛 *Móvil:* ${cuad.movil_asignado || 'Camión Grúa'}\n━━━━━━━━━━━━━━━━━━━━━━━\nFavor de intervenir a la brevedad y confirmar para asentar en el sistema.`; tel = tel.replace(/[^0-9]/g, '').replace(/^0+/, ''); if (tel.startsWith('15')) tel = '3755' + tel.slice(2); if (tel.length >= 6 && tel.length <= 7) tel = '3755' + tel; if (!tel.startsWith('549') && tel.startsWith('54')) tel = '549' + tel.slice(2); else if (!tel.startsWith('549') && tel.length >= 8) tel = '549' + tel; const url = tel ? `https://wa.me/${tel}?text=${encodeURIComponent(msg)}` : `https://wa.me/?text=${encodeURIComponent(msg)}`; if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(msg).catch(() => {}); } try { const a = document.createElement('a'); a.href = url; a.target = '_blank'; a.rel = 'noopener noreferrer'; document.body.appendChild(a); a.click(); document.body.removeChild(a); } catch(e) {} try { window.open(url, '_blank', 'noopener,noreferrer'); } catch(e) {} } async function darDeBajaPosteDesdeMapa(posteId) { let p = listaPostesCriticosCache.find(x => x.id === posteId) || listaTodosLosPostes.find(x => x.id === posteId); if (!p) { alert('Poste no encontrado.'); return; } const cuadrillas = await cargarCuadrillasPostesSiEsNecesario(); const selCuad = document.getElementById('bajaMapaCuadrilla'); if (selCuad) { selCuad.innerHTML = cuadrillas.map((c, i) => ` `).join(''); } const cod = (p.codigo && p.codigo !== 'NULL') ? p.codigo : `PST-${p.id}`; const nom = (p.nombre && p.nombre !== 'NULL') ? p.nombre : `Poste #${p.id}`; document.getElementById('bajaMapaPosteId').value = p.id; document.getElementById('bajaMapaInfoPoste').innerHTML = ` Poste: ${nom} (${cod}) • Material anterior: ${p.material} (${p.altura_m}m)
Falla actual: ${p.observaciones} `; onCambioCuadrillaBajaMapa(); const m = document.getElementById('modalBajaPosteMapa'); if (m) m.style.display = 'flex'; } function onCambioCuadrillaBajaMapa() { const sel = document.getElementById('bajaMapaCuadrilla'); if (!sel) return; const opt = sel.options[sel.selectedIndex]; if (!opt) return; const opInput = document.getElementById('bajaMapaOperarios'); const movInput = document.getElementById('bajaMapaMovil'); if (opInput) opInput.value = opt.getAttribute('data-cabecilla') || ''; if (movInput) movInput.value = opt.getAttribute('data-movil') || ''; } function cerrarModalBajaPosteMapa() { const m = document.getElementById('modalBajaPosteMapa'); if (m) m.style.display = 'none'; } async function confirmarBajaPosteMapa() { const posteId = parseInt(document.getElementById('bajaMapaPosteId')?.value); if (!posteId) return; const tipo_trabajo = document.getElementById('bajaMapaTipoTrabajo')?.value || 'RECAMBIO_TOTAL'; const material_nuevo = document.getElementById('bajaMapaMaterialNuevo')?.value || 'HORMIGON'; const altura_m = parseFloat(document.getElementById('bajaMapaAltura')?.value) || 9.0; const cuadrilla = document.getElementById('bajaMapaCuadrilla')?.value || 'Guardia Técnica'; const operarios = document.getElementById('bajaMapaOperarios')?.value || ''; const movil = document.getElementById('bajaMapaMovil')?.value || ''; const materiales_usados = document.getElementById('bajaMapaMateriales')?.value || ''; const observaciones = document.getElementById('bajaMapaObs')?.value || 'Intervención completada.'; try { const res = await fetch(`${API}/api/gis/postes/dar_de_baja_critico`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ poste_id: posteId, tipo_trabajo, material_nuevo, altura_m, cuadrilla, operarios, movil, materiales_usados, observaciones, estado_nuevo: 'BUENO' }) }); const data = await res.json(); if (data.ok) { mostrarToast(`✅ ${data.mensaje}`); cerrarModalBajaPosteMapa(); // Actualizar caches listaPostesCriticosCache = listaPostesCriticosCache.filter(x => x.id !== posteId); renderizarItemsPostesCriticos(listaPostesCriticosCache); // Recargar capa de postes si está activa if (window.postesCargados && window.toggleCapaPostes) { postesCargados = false; toggleCapaPostes(true); } } else { alert(data.error || 'Error al guardar la baja del poste.'); } } catch (e) { alert('Error de conexión con el servidor.'); } } async function verHistorialPosteDesdeMapa(posteId) { const m = document.getElementById('modalHistorialPostesMapa'); const cont = document.getElementById('historialModalPostesContenido'); const tit = document.getElementById('historialModalPostesTitulo'); if (m) m.style.display = 'flex'; if (tit) tit.textContent = posteId ? `📜 Historial del Poste #${posteId}` : '📜 Historial General de Postes'; if (cont) cont.innerHTML = '
Cargando historial de intervenciones...
'; try { const url = posteId ? `${API}/api/gis/postes/historial?poste_id=${posteId}` : `${API}/api/gis/postes/historial`; const res = await fetch(url); const data = await res.json(); const rows = data.historial || []; if (rows.length === 0) { cont.innerHTML = '
No hay registros de recambio para este poste aún.
'; return; } cont.innerHTML = rows.map(h => `
${h.codigo_poste} • ${h.nombre_poste} ${h.tipo_trabajo}
📅 Fecha: ${h.fecha_ejecucion}
👷 Cuadrilla: ${h.cuadrilla}
🚛 Móvil: ${h.movil || 'S/D'}
🪵 Recambio: ${h.material_anterior || 'MADERA'} ➡️ ${h.material_nuevo} (${h.altura_m}m)
${h.materiales_utilizados ? `
Materiales: ${h.materiales_utilizados}
` : ''}
Observaciones: ${h.observaciones}
`).join(''); } catch (e) { if (cont) cont.innerHTML = '
Error al cargar historial.
'; } } function verHistorialGeneralPostesMapa() { verHistorialPosteDesdeMapa(null); } function cerrarModalHistorialPostesMapa() { const m = document.getElementById('modalHistorialPostesMapa'); if (m) m.style.display = 'none'; } // ============================================================================= // CONTROLADOR DE ESTADÍSTICAS GLOBALES & FOTOS GEORREFERENCIADAS EN MAPA.HTML // ============================================================================= let galeriaFotosMapaCache = []; let filtroTipoFotoMapa = 'TODAS'; let filtroTextoFotoMapa = ''; let tempFotoBase64Mapa = null; async function abrirModalEstadisticasYFotos() { const m = document.getElementById('modalEstadisticasYFotosMapa'); if (m) m.style.display = 'flex'; await cargarEstadisticasYFotosModal(); } function cerrarModalEstadisticasYFotos() { const m = document.getElementById('modalEstadisticasYFotosMapa'); if (m) m.style.display = 'none'; } async function cargarEstadisticasYFotosModal() { try { const [resEst, resFotos] = await Promise.all([ fetch(`${API}/api/estadisticas/globales`).then(r => r.json()), fetch(`${API}/api/estadisticas/galeria_fotos`).then(r => r.json()) ]); if (resEst && resEst.ok) { const p = resEst.postes || {}; const elP = document.getElementById('mapaKpiPostesTotal'); if (elP) elP.textContent = p.total || 0; const elB = document.getElementById('mapaKpiPostesBuenos'); if (elB) elB.textContent = p.buenos || 0; const elC = document.getElementById('mapaKpiPostesCriticos'); if (elC) elC.textContent = p.criticos || 0; const t = resEst.transformadores || {}; const elT = document.getElementById('mapaKpiTrafosTotal'); if (elT) elT.textContent = `${t.total || 518} (${(t.kva_total || 26227).toLocaleString('es-AR')} kVA)`; const r = resEst.red_electrica || {}; const elR = document.getElementById('mapaKpiRedTotal'); if (elR) elR.textContent = `${(r.tramos_bt || 775) + (r.tramos_mt || 209)} Tramos`; } galeriaFotosMapaCache = resFotos.fotos || []; const countBadge = document.getElementById('mapaBadgeFotosCount'); if (countBadge) countBadge.textContent = `${galeriaFotosMapaCache.length} fotos`; renderizarFotosMapaModal(); } catch (e) { console.error("Error al cargar estadísticas en mapa:", e); } } function filtrarFotosMapaModal(tipo) { filtroTipoFotoMapa = tipo; document.querySelectorAll('.btn-filtro-mapa-foto').forEach(b => { b.style.background = (b.getAttribute('data-tipo') === tipo) ? '#0284c7' : '#334155'; }); renderizarFotosMapaModal(); } function filtrarTextoFotosMapaModal(txt) { filtroTextoFotoMapa = (txt || '').toLowerCase(); renderizarFotosMapaModal(); } function renderizarFotosMapaModal() { const grid = document.getElementById('gridFotosMapaModal'); if (!grid) return; let items = galeriaFotosMapaCache; if (filtroTipoFotoMapa !== 'TODAS') { items = items.filter(f => f.tipo_foto === filtroTipoFotoMapa); } if (filtroTextoFotoMapa) { const txt = filtroTextoFotoMapa; items = items.filter(f => (f.codigo || '').toLowerCase().includes(txt) || (f.nombre || '').toLowerCase().includes(txt) || (f.descripcion || '').toLowerCase().includes(txt) || (f.operario || '').toLowerCase().includes(txt) ); } if (items.length === 0) { grid.innerHTML = '
No hay fotos con el filtro seleccionado.
'; return; } grid.innerHTML = items.map(f => { const esCritico = f.estado === 'CRITICO' || f.tipo_foto === 'DANO_CRITICO'; const color = esCritico ? '#ef4444' : (f.tipo_foto === 'RECAMBIO_NUEVO' ? '#10b981' : '#f59e0b'); const badgeTxt = esCritico ? '🚨 CRÍTICO' : (f.tipo_foto === 'RECAMBIO_NUEVO' ? '✅ NUEVO' : '⚠️ INSPECCIÓN'); return `
${badgeTxt}
${f.codigo || 'PST-' + f.poste_id} • ${f.nombre || ''}
${f.descripcion}
👷 ${f.operario || 'Guardia'} • ${f.fecha_hora || ''}
📍 GPS: ${f.lat ? f.lat.toFixed(5) : ''}, ${f.lng ? f.lng.toFixed(5) : ''}
🧭 GMaps
`; }).join(''); } function volarAPosteDesdeFotoMapa(lat, lng, posteId) { cerrarModalEstadisticasYFotos(); if (window.mapaObj && lat && lng) { mapaObj.flyTo([lat, lng], 18, { duration: 1.2 }); mostrarToast(`📍 Centrando mapa en poste #${posteId}`); } } async function abrirModalFotosPosteDesdeMapa(posteId) { const m = document.getElementById('modalFotosPosteMapa'); const cont = document.getElementById('contenidoFotosPosteMapa'); const tit = document.getElementById('tituloFotosPosteMapa'); const btnAdd = document.getElementById('btnAgregarFotoDesdeModalPoste'); if (m) m.style.display = 'flex'; if (tit) tit.textContent = `📷 Evidencias Fotográficas del Poste #${posteId}`; if (cont) cont.innerHTML = '
Consultando fotografías registradas...
'; if (btnAdd) { btnAdd.onclick = () => { cerrarModalFotosPosteMapa(); abrirModalSubirFotoPosteDesdeMapa(posteId); }; } try { const res = await fetch(`${API}/api/gis/postes/${posteId}/fotos`); const data = await res.json(); const fotos = data.fotos || []; if (fotos.length === 0) { cont.innerHTML = `
📷
Este poste no tiene fotos adjuntadas aún.
`; return; } cont.innerHTML = `
${fotos.map(f => `
${f.tipo_foto} ${f.fecha_hora}
${f.descripcion}
📍 ${f.lat ? f.lat.toFixed(5) : ''}, ${f.lng ? f.lng.toFixed(5) : ''}
🧭 Abrir en Google Maps
`).join('')}
`; } catch (e) { if (cont) cont.innerHTML = '
Error al consultar fotos.
'; } } function cerrarModalFotosPosteMapa() { const m = document.getElementById('modalFotosPosteMapa'); if (m) m.style.display = 'none'; } async function abrirModalSubirFotoPosteDesdeMapa(posteId) { let p = (listaPostesCriticosCache || []).find(x => x.id === posteId) || (listaTodosLosPostes || []).find(x => x.id === posteId); if (!p) { try { const res = await fetch(`${API}/api/gis/postes_relevamiento?estado=TODOS`); const data = await res.json(); p = (data.postes || []).find(x => x.id === posteId); } catch(e) {} } const cod = p ? (p.codigo || `PST-${posteId}`) : `PST-${posteId}`; const nom = p ? (p.nombre || `Poste #${posteId}`) : `Poste #${posteId}`; const lat = p ? p.lat : ''; const lng = p ? p.lng : ''; document.getElementById('subirFotoMapaPosteId').value = posteId; document.getElementById('subirFotoMapaLat').value = lat; document.getElementById('subirFotoMapaLng').value = lng; document.getElementById('subtituloSubirFotoMapa').textContent = `${nom} (${cod}) • GPS: ${lat ? lat.toFixed(5) : ''}, ${lng ? lng.toFixed(5) : ''}`; document.getElementById('subirFotoMapaDescripcion').value = p ? `Inspección de campo en poste: ${p.observaciones || ''}` : 'Inspección de poste.'; document.getElementById('previewFotoSubirMapa').style.display = 'none'; tempFotoBase64Mapa = null; const m = document.getElementById('modalSubirFotoPosteMapa'); if (m) m.style.display = 'flex'; } function cerrarModalSubirFotoPosteMapa() { const m = document.getElementById('modalSubirFotoPosteMapa'); if (m) m.style.display = 'none'; } function previsualizarArchivoFotoMapa(input) { if (!input.files || !input.files[0]) return; const reader = new FileReader(); reader.onload = (e) => { tempFotoBase64Mapa = e.target.result; const prev = document.getElementById('previewFotoSubirMapa'); if (prev) { prev.src = tempFotoBase64Mapa; prev.style.display = 'block'; } }; reader.readAsDataURL(input.files[0]); } function generarSvgFotoMapa(tipo) { let svgContent = ''; if (tipo === 'CRITICO') { svgContent = `data:image/svg+xml;utf8,🚨 DAÑO CRÍTICOFOTO DE RELEVAMIENTOPeligro inminente de quiebre en base`; document.getElementById('subirFotoMapaTipo').value = 'DANO_CRITICO'; } else { svgContent = `data:image/svg+xml;utf8,✅ RECAMBIO NORMALIZADOHORMIGÓN ARMADO 9MPoste nuevo instalado y tensado`; document.getElementById('subirFotoMapaTipo').value = 'RECAMBIO_NUEVO'; } tempFotoBase64Mapa = svgContent; const prev = document.getElementById('previewFotoSubirMapa'); if (prev) { prev.src = svgContent; prev.style.display = 'block'; } mostrarToast("Muestra fotográfica generada para simulación."); } async function guardarFotoPosteDesdeMapa() { const posteId = parseInt(document.getElementById('subirFotoMapaPosteId')?.value); if (!posteId) { alert("ID de poste no válido."); return; } if (!tempFotoBase64Mapa) { alert("Por favor seleccione un archivo de imagen o presione un botón de muestra técnica."); return; } const tipo_foto = document.getElementById('subirFotoMapaTipo')?.value || 'INSPECCION_CAMPO'; const descripcion = document.getElementById('subirFotoMapaDescripcion')?.value || 'Evidencia fotográfica en mapa'; const operario = document.getElementById('subirFotoMapaOperario')?.value || 'Guardia Técnica'; const lat = parseFloat(document.getElementById('subirFotoMapaLat')?.value) || null; const lng = parseFloat(document.getElementById('subirFotoMapaLng')?.value) || null; try { const res = await fetch(`${API}/api/gis/postes/${posteId}/adjuntar_foto`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ data_base64: tempFotoBase64Mapa, tipo_foto, descripcion, operario, lat, lng, archivo_nombre: `foto_mapa_pst_${posteId}_${Date.now()}.jpg` }) }); const data = await res.json(); if (data.ok) { mostrarToast("✅ Fotografía guardada con éxito en la base de datos."); cerrarModalSubirFotoPosteMapa(); await abrirModalFotosPosteDesdeMapa(posteId); } else { alert("Error: " + (data.error || "No se pudo guardar la foto")); } } catch (e) { alert("Error de conexión al guardar foto."); } }