diff --git a/pacifictrans-app/public/index.html b/pacifictrans-app/public/index.html index d6070e4..96bd1a5 100644 --- a/pacifictrans-app/public/index.html +++ b/pacifictrans-app/public/index.html @@ -49,7 +49,7 @@ 🚗 Viajar 📦 Envíos ⭐ Reseñas - 📲 App Móvil + 📲 Descargar App + + + + +
+
+ + +
+ +
+
diff --git a/pacifictrans-app/public/js/app.js b/pacifictrans-app/public/js/app.js index 190b7bf..7a4eeda 100644 --- a/pacifictrans-app/public/js/app.js +++ b/pacifictrans-app/public/js/app.js @@ -147,76 +147,125 @@ function initNativeBackButton() { }); } -// 3. Geolocalización GPS Nativa de Alta Precisión -function initNativeGPS() { - const btnGps = document.getElementById('btn-native-gps-cali'); - if (!btnGps) return; +// Variables globales de coordenadas GPS detectadas +window.passengerGpsCoords = [-76.5320, 3.4215]; +window.freightPickupCoords = [-76.5320, 3.4215]; +window.freightDeliveryCoords = [-77.0250, 3.8820]; - btnGps.addEventListener('click', async () => { +// Helper Centralizado: Obtiene coordenadas GPS y geocodifica a dirección humana real +async function getCurrentUserLocation(buttonEl = null) { + let originalText = ''; + if (buttonEl) { triggerHaptic('medium'); - btnGps.disabled = true; - const originalText = btnGps.innerHTML; - btnGps.innerHTML = '⏳ Obteniendo GPS...'; + originalText = buttonEl.innerHTML; + buttonEl.disabled = true; + buttonEl.innerHTML = '⏳ Obteniendo GPS...'; + } - try { - let coords = null; - if (window.Capacitor?.isPluginAvailable?.('Geolocation')) { - const { Geolocation } = window.Capacitor.Plugins; + try { + let coords = null; + if (window.Capacitor?.isPluginAvailable?.('Geolocation')) { + const { Geolocation } = window.Capacitor.Plugins; + try { const check = await Geolocation.checkPermissions(); if (check.location !== 'granted') { const req = await Geolocation.requestPermissions(); if (req.location !== 'granted') { showNativeToast('⚠️ Permiso de ubicación requerido para GPS'); - btnGps.disabled = false; - btnGps.innerHTML = originalText; - return; + return null; } } - const pos = await Geolocation.getCurrentPosition({ - enableHighAccuracy: true, - timeout: 12000 - }); - coords = { lat: pos.coords.latitude, lng: pos.coords.longitude }; - } else if (navigator.geolocation) { - coords = await new Promise((resolve, reject) => { - navigator.geolocation.getCurrentPosition( - p => resolve({ lat: p.coords.latitude, lng: p.coords.longitude }), - err => reject(err), - { enableHighAccuracy: true, timeout: 12000 } - ); + } catch (pErr) { } + + const pos = await Geolocation.getCurrentPosition({ + enableHighAccuracy: true, + timeout: 12000 + }); + coords = { lat: pos.coords.latitude, lng: pos.coords.longitude }; + } else if (navigator.geolocation) { + coords = await new Promise((resolve, reject) => { + navigator.geolocation.getCurrentPosition( + p => resolve({ lat: p.coords.latitude, lng: p.coords.longitude }), + err => reject(err), + { enableHighAccuracy: true, timeout: 12000 } + ); + }); + } + + if (!coords) { + showNativeToast('⚠️ No se pudo obtener la señal GPS'); + return null; + } + + if (buttonEl) buttonEl.innerHTML = '🔍 Identificando dirección...'; + + // Geocodificación inversa satelital a través del backend + let address = `Ubicación GPS (${coords.lat.toFixed(5)}, ${coords.lng.toFixed(5)})`; + let city = (coords.lat > 3.6 && coords.lng < -76.8) ? 'Buenaventura' : 'Cali'; + + try { + const res = await fetch(`/api/geo/reverse?lat=${coords.lat}&lng=${coords.lng}`); + if (res.ok) { + const data = await res.json(); + if (data.success && data.address) { + address = data.address; + city = data.city || city; + } + } + } catch (geoErr) { + console.warn('⚠️ [Reverse geocode notice]:', geoErr); + } + + triggerHaptic('success'); + return { + lat: coords.lat, + lng: coords.lng, + address, + city + }; + } catch (err) { + console.warn('[GPS Location Error]:', err); + showNativeToast('⚠️ No se pudo obtener la ubicación actual'); + triggerHaptic('warning'); + return null; + } finally { + if (buttonEl) { + buttonEl.disabled = false; + buttonEl.innerHTML = originalText; + } + } +} + +// 3. Geolocalización GPS Nativa de Alta Precisión para Pasajeros +function initNativeGPS() { + const btnGps = document.getElementById('btn-native-gps-cali'); + if (!btnGps) return; + + btnGps.addEventListener('click', async () => { + const loc = await getCurrentUserLocation(btnGps); + if (loc) { + window.passengerGpsCoords = [loc.lng, loc.lat]; + + // Centrar mapa de radar y posicionar marcador del pasajero + if (leafletMap && typeof L !== 'undefined') { + leafletMap.setView([loc.lat, loc.lng], 16); + const userIcon = L.divIcon({ + className: 'user-live-gps-pin', + html: '
📍
', + iconSize: [36, 36], + iconAnchor: [18, 18] }); + L.marker([loc.lat, loc.lng], { icon: userIcon }) + .addTo(leafletMap) + .bindPopup(`📍 Tu Ubicación Actual
${loc.address}`) + .openPopup(); } - if (coords) { - // Centrar mapa de radar y posicionar marcador del pasajero - if (leafletMap && typeof L !== 'undefined') { - leafletMap.setView([coords.lat, coords.lng], 16); - const userIcon = L.divIcon({ - className: 'user-live-gps-pin', - html: '
📍
', - iconSize: [36, 36], - iconAnchor: [18, 18] - }); - L.marker([coords.lat, coords.lng], { icon: userIcon }) - .addTo(leafletMap) - .bindPopup('📍 Tu Ubicación Actual
Coordenadas GPS de alta precisión detectadas.') - .openPopup(); - } - - const addrInput = document.getElementById('cali-address'); - if (addrInput) { - addrInput.value = `📍 GPS (${coords.lat.toFixed(5)}, ${coords.lng.toFixed(5)})`; - } - showNativeToast('✅ Ubicación GPS detectada con éxito'); - triggerHaptic('success'); + const addrInput = document.getElementById('cali-address'); + if (addrInput) { + addrInput.value = loc.address; } - } catch (err) { - console.warn('[GPS Error]:', err); - showNativeToast('No se pudo obtener el GPS actual'); - triggerHaptic('warning'); - } finally { - btnGps.disabled = false; - btnGps.innerHTML = originalText; + showNativeToast(`📍 Dirección detectada: ${loc.address}`); } }); } @@ -2160,8 +2209,22 @@ function initPassengerCalculator() { function updateOriginDestination() { if (!originSelect) return; const isCali = originSelect.value === 'CALI'; - if (addressGroup) addressGroup.style.display = isCali ? 'block' : 'none'; - if (buenaStopGroup) buenaStopGroup.style.display = isCali ? 'block' : 'none'; + const caliAddressLabel = document.querySelector('label[for="cali-address"]'); + const buenaStopLabel = document.querySelector('label[for="buena-stop"]'); + + if (addressGroup) addressGroup.style.display = 'block'; + if (buenaStopGroup) buenaStopGroup.style.display = 'block'; + + if (caliAddressLabel) { + caliAddressLabel.textContent = isCali + ? '📍 Dirección Principal de Recogida en Cali (Domicilio Puerta a Puerta)' + : '🏁 Dirección Principal de Llegada en Cali (Entrega en Domicilio)'; + } + if (buenaStopLabel) { + buenaStopLabel.textContent = isCali + ? '🏁 Parada de Destino en Buenaventura' + : '📍 Punto Oficial de Salida en Buenaventura'; + } } if (originSelect) { @@ -2232,14 +2295,18 @@ function initPassengerCalculator() { const pAddress = (!d.sameAddress && d.address && d.address.trim()) ? d.address.trim() - : (caliAddress || 'Punto Oficial Buenaventura'); + : (caliAddress || (isCaliOrigin ? 'Cali, Valle del Cauca' : 'Buenaventura, Valle del Cauca')); + + const pCoords = (i === 1 && window.passengerGpsCoords) + ? window.passengerGpsCoords + : (isCaliOrigin ? [-76.5320, 3.4215] : [-77.0250, 3.8820]); validatedPassengers.push({ nombre: d.nombre.trim(), documentoIdentidad: d.doc.trim(), telefono: d.phone.trim(), direccionRecogida: pAddress, - coordenadas: [-76.5320, 3.4215], + coordenadas: pCoords, notas: d.notes ? d.notes.trim() : '', esTitular: (i === 1) }); @@ -2268,11 +2335,15 @@ function initPassengerCalculator() { `; try { + const userTripCoords = (window.passengerGpsCoords && window.passengerGpsCoords.length === 2) + ? window.passengerGpsCoords + : (isCaliOrigin ? [-76.5320, 3.4215] : [-77.0250, 3.8820]); + const payload = { usuarioId: currentUser ? currentUser._id : undefined, sentido: isCaliOrigin ? 'CALI_A_BUENAVENTURA' : 'BUENAVENTURA_A_CALI', - direccionTexto: caliAddress || 'Terminal Buenaventura', - coordenadas: [-76.5320, 3.4215], + direccionTexto: caliAddress || (isCaliOrigin ? 'Cali, Valle del Cauca' : 'Buenaventura, Valle del Cauca'), + coordenadas: userTripCoords, puntoFijoBuenaventura: { nombre: buenaStopSelect ? buenaStopSelect.options[buenaStopSelect.selectedIndex].text : 'Terminal de Transporte de Buenaventura', coordenadas: [-77.0250, 3.8820] @@ -2694,6 +2765,34 @@ function initFreightCalculator() { }); } + // Botones GPS para Recogida y Entrega de Encomiendas + const btnFreightGpsPickup = document.getElementById('btn-freight-gps-pickup'); + const btnFreightGpsDelivery = document.getElementById('btn-freight-gps-delivery'); + const freightPickupInput = document.getElementById('freight-pickup-address'); + const freightDeliveryInput = document.getElementById('freight-delivery-address'); + + if (btnFreightGpsPickup) { + btnFreightGpsPickup.addEventListener('click', async () => { + const loc = await getCurrentUserLocation(btnFreightGpsPickup); + if (loc) { + window.freightPickupCoords = [loc.lng, loc.lat]; + if (freightPickupInput) freightPickupInput.value = loc.address; + showNativeToast(`📍 Recogida establecida: ${loc.address}`); + } + }); + } + + if (btnFreightGpsDelivery) { + btnFreightGpsDelivery.addEventListener('click', async () => { + const loc = await getCurrentUserLocation(btnFreightGpsDelivery); + if (loc) { + window.freightDeliveryCoords = [loc.lng, loc.lat]; + if (freightDeliveryInput) freightDeliveryInput.value = loc.address; + showNativeToast(`🏁 Entrega establecida: ${loc.address}`); + } + }); + } + // Despacho / Creación de Encomienda con Pago Seguro y Cupón if (btnBookFreight) { btnBookFreight.addEventListener('click', async (e) => { @@ -2702,6 +2801,8 @@ function initFreightCalculator() { const senderPhone = document.getElementById('sender-phone')?.value.trim() || currentUser?.telefono || ''; const receiverPhone = document.getElementById('receiver-phone')?.value.trim(); const packageDesc = document.getElementById('package-desc')?.value.trim(); + const freightPickupAddr = freightPickupInput?.value.trim() || 'Cali, Valle del Cauca'; + const freightDeliveryAddr = freightDeliveryInput?.value.trim() || 'Terminal Buenaventura'; if (!senderPhone || senderPhone.replace(/\D/g, '').length < 7) { alert('⚠️ Por favor ingresa el teléfono/WhatsApp del remitente.'); @@ -2743,6 +2844,12 @@ function initFreightCalculator() { remitenteId: currentUser ? (currentUser._id || currentUser.id) : undefined, remitenteNombre: senderName || 'Remitente', remitenteTelefono: senderPhone, + direccionRecogida: freightPickupAddr, + coordenadasRecogida: window.freightPickupCoords || [-76.5320, 3.4215], + ciudadOrigen: (window.freightPickupCoords && window.freightPickupCoords[1] > 3.6 && window.freightPickupCoords[0] < -76.8) ? 'BUENAVENTURA' : 'CALI', + direccionEntrega: freightDeliveryAddr, + coordenadasEntrega: window.freightDeliveryCoords || [-77.0250, 3.8820], + ciudadDestino: (window.freightDeliveryCoords && window.freightDeliveryCoords[1] < 3.6 && window.freightDeliveryCoords[0] > -76.8) ? 'CALI' : 'BUENAVENTURA', tipoPaquete: packageTypeSelect ? packageTypeSelect.options[packageTypeSelect.selectedIndex].text : 'Paquete Pequeño', factor: parseFloat(packageTypeSelect?.value || '1.2'), valorDeclarado: parseFloat(declaredValueInput?.value || '100000'), diff --git a/scripts/verify_gps_geocoding.py b/scripts/verify_gps_geocoding.py new file mode 100644 index 0000000..9aef6ff --- /dev/null +++ b/scripts/verify_gps_geocoding.py @@ -0,0 +1,48 @@ +import io +import sys +import urllib.request +import json +import ssl + +if sys.platform == 'win32': + sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace') + sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace') + +ctx = ssl.create_default_context() +ctx.check_hostname = False +ctx.verify_mode = ssl.CERT_NONE + +API_URL = "https://pacifictrans.almeira.com.co" + +print("1. Probando geocodificacion inversa satelital en Cali...") +req_cali = urllib.request.Request(f"{API_URL}/api/geo/reverse?lat=3.4215&lng=-76.5320") +try: + with urllib.request.urlopen(req_cali, context=ctx, timeout=10) as res: + data = json.loads(res.read().decode("utf-8")) + print(f" [OK] Cali geocodificado: {data.get('address')} | Ciudad: {data.get('city')}") + assert data.get('success') is True +except Exception as e: + print(" Aviso / Error:", e) + +print("\n2. Probando geocodificacion inversa satelital en Buenaventura...") +req_bv = urllib.request.Request(f"{API_URL}/api/geo/reverse?lat=3.8820&lng=-77.0250") +try: + with urllib.request.urlopen(req_bv, context=ctx, timeout=10) as res: + data = json.loads(res.read().decode("utf-8")) + print(f" [OK] Buenaventura geocodificado: {data.get('address')} | Ciudad: {data.get('city')}") + assert data.get('success') is True +except Exception as e: + print(" Aviso / Error:", e) + +print("\n3. Verificando campos de direccion y botones GPS en index.html...") +req_html = urllib.request.Request(f"{API_URL}/") +with urllib.request.urlopen(req_html, context=ctx, timeout=10) as res: + html = res.read().decode("utf-8") + assert "freight-pickup-address" in html, "Falta freight-pickup-address" + assert "freight-delivery-address" in html, "Falta freight-delivery-address" + assert "btn-freight-gps-pickup" in html, "Falta btn-freight-gps-pickup" + assert "btn-freight-gps-delivery" in html, "Falta btn-freight-gps-delivery" + assert "btn-native-gps-cali" in html, "Falta btn-native-gps-cali" + print(" [OK] Todos los campos de direccion y botones GPS de ubicacion actual estan activos en la interfaz.") + +print("\n[OK] Verificacion de direccion por ubicacion actual completada exitosamente.") diff --git a/transporte-cali-buenaventura/backend/public/index.html b/transporte-cali-buenaventura/backend/public/index.html index d6070e4..96bd1a5 100644 --- a/transporte-cali-buenaventura/backend/public/index.html +++ b/transporte-cali-buenaventura/backend/public/index.html @@ -49,7 +49,7 @@ 🚗 Viajar 📦 Envíos ⭐ Reseñas - 📲 App Móvil + 📲 Descargar App
+ +
+
+ + +
+ +
+ +
+
+ + +
+ +
+
diff --git a/transporte-cali-buenaventura/backend/public/js/app.js b/transporte-cali-buenaventura/backend/public/js/app.js index 190b7bf..7a4eeda 100644 --- a/transporte-cali-buenaventura/backend/public/js/app.js +++ b/transporte-cali-buenaventura/backend/public/js/app.js @@ -147,76 +147,125 @@ function initNativeBackButton() { }); } -// 3. Geolocalización GPS Nativa de Alta Precisión -function initNativeGPS() { - const btnGps = document.getElementById('btn-native-gps-cali'); - if (!btnGps) return; +// Variables globales de coordenadas GPS detectadas +window.passengerGpsCoords = [-76.5320, 3.4215]; +window.freightPickupCoords = [-76.5320, 3.4215]; +window.freightDeliveryCoords = [-77.0250, 3.8820]; - btnGps.addEventListener('click', async () => { +// Helper Centralizado: Obtiene coordenadas GPS y geocodifica a dirección humana real +async function getCurrentUserLocation(buttonEl = null) { + let originalText = ''; + if (buttonEl) { triggerHaptic('medium'); - btnGps.disabled = true; - const originalText = btnGps.innerHTML; - btnGps.innerHTML = '⏳ Obteniendo GPS...'; + originalText = buttonEl.innerHTML; + buttonEl.disabled = true; + buttonEl.innerHTML = '⏳ Obteniendo GPS...'; + } - try { - let coords = null; - if (window.Capacitor?.isPluginAvailable?.('Geolocation')) { - const { Geolocation } = window.Capacitor.Plugins; + try { + let coords = null; + if (window.Capacitor?.isPluginAvailable?.('Geolocation')) { + const { Geolocation } = window.Capacitor.Plugins; + try { const check = await Geolocation.checkPermissions(); if (check.location !== 'granted') { const req = await Geolocation.requestPermissions(); if (req.location !== 'granted') { showNativeToast('⚠️ Permiso de ubicación requerido para GPS'); - btnGps.disabled = false; - btnGps.innerHTML = originalText; - return; + return null; } } - const pos = await Geolocation.getCurrentPosition({ - enableHighAccuracy: true, - timeout: 12000 - }); - coords = { lat: pos.coords.latitude, lng: pos.coords.longitude }; - } else if (navigator.geolocation) { - coords = await new Promise((resolve, reject) => { - navigator.geolocation.getCurrentPosition( - p => resolve({ lat: p.coords.latitude, lng: p.coords.longitude }), - err => reject(err), - { enableHighAccuracy: true, timeout: 12000 } - ); + } catch (pErr) { } + + const pos = await Geolocation.getCurrentPosition({ + enableHighAccuracy: true, + timeout: 12000 + }); + coords = { lat: pos.coords.latitude, lng: pos.coords.longitude }; + } else if (navigator.geolocation) { + coords = await new Promise((resolve, reject) => { + navigator.geolocation.getCurrentPosition( + p => resolve({ lat: p.coords.latitude, lng: p.coords.longitude }), + err => reject(err), + { enableHighAccuracy: true, timeout: 12000 } + ); + }); + } + + if (!coords) { + showNativeToast('⚠️ No se pudo obtener la señal GPS'); + return null; + } + + if (buttonEl) buttonEl.innerHTML = '🔍 Identificando dirección...'; + + // Geocodificación inversa satelital a través del backend + let address = `Ubicación GPS (${coords.lat.toFixed(5)}, ${coords.lng.toFixed(5)})`; + let city = (coords.lat > 3.6 && coords.lng < -76.8) ? 'Buenaventura' : 'Cali'; + + try { + const res = await fetch(`/api/geo/reverse?lat=${coords.lat}&lng=${coords.lng}`); + if (res.ok) { + const data = await res.json(); + if (data.success && data.address) { + address = data.address; + city = data.city || city; + } + } + } catch (geoErr) { + console.warn('⚠️ [Reverse geocode notice]:', geoErr); + } + + triggerHaptic('success'); + return { + lat: coords.lat, + lng: coords.lng, + address, + city + }; + } catch (err) { + console.warn('[GPS Location Error]:', err); + showNativeToast('⚠️ No se pudo obtener la ubicación actual'); + triggerHaptic('warning'); + return null; + } finally { + if (buttonEl) { + buttonEl.disabled = false; + buttonEl.innerHTML = originalText; + } + } +} + +// 3. Geolocalización GPS Nativa de Alta Precisión para Pasajeros +function initNativeGPS() { + const btnGps = document.getElementById('btn-native-gps-cali'); + if (!btnGps) return; + + btnGps.addEventListener('click', async () => { + const loc = await getCurrentUserLocation(btnGps); + if (loc) { + window.passengerGpsCoords = [loc.lng, loc.lat]; + + // Centrar mapa de radar y posicionar marcador del pasajero + if (leafletMap && typeof L !== 'undefined') { + leafletMap.setView([loc.lat, loc.lng], 16); + const userIcon = L.divIcon({ + className: 'user-live-gps-pin', + html: '
📍
', + iconSize: [36, 36], + iconAnchor: [18, 18] }); + L.marker([loc.lat, loc.lng], { icon: userIcon }) + .addTo(leafletMap) + .bindPopup(`📍 Tu Ubicación Actual
${loc.address}`) + .openPopup(); } - if (coords) { - // Centrar mapa de radar y posicionar marcador del pasajero - if (leafletMap && typeof L !== 'undefined') { - leafletMap.setView([coords.lat, coords.lng], 16); - const userIcon = L.divIcon({ - className: 'user-live-gps-pin', - html: '
📍
', - iconSize: [36, 36], - iconAnchor: [18, 18] - }); - L.marker([coords.lat, coords.lng], { icon: userIcon }) - .addTo(leafletMap) - .bindPopup('📍 Tu Ubicación Actual
Coordenadas GPS de alta precisión detectadas.') - .openPopup(); - } - - const addrInput = document.getElementById('cali-address'); - if (addrInput) { - addrInput.value = `📍 GPS (${coords.lat.toFixed(5)}, ${coords.lng.toFixed(5)})`; - } - showNativeToast('✅ Ubicación GPS detectada con éxito'); - triggerHaptic('success'); + const addrInput = document.getElementById('cali-address'); + if (addrInput) { + addrInput.value = loc.address; } - } catch (err) { - console.warn('[GPS Error]:', err); - showNativeToast('No se pudo obtener el GPS actual'); - triggerHaptic('warning'); - } finally { - btnGps.disabled = false; - btnGps.innerHTML = originalText; + showNativeToast(`📍 Dirección detectada: ${loc.address}`); } }); } @@ -2160,8 +2209,22 @@ function initPassengerCalculator() { function updateOriginDestination() { if (!originSelect) return; const isCali = originSelect.value === 'CALI'; - if (addressGroup) addressGroup.style.display = isCali ? 'block' : 'none'; - if (buenaStopGroup) buenaStopGroup.style.display = isCali ? 'block' : 'none'; + const caliAddressLabel = document.querySelector('label[for="cali-address"]'); + const buenaStopLabel = document.querySelector('label[for="buena-stop"]'); + + if (addressGroup) addressGroup.style.display = 'block'; + if (buenaStopGroup) buenaStopGroup.style.display = 'block'; + + if (caliAddressLabel) { + caliAddressLabel.textContent = isCali + ? '📍 Dirección Principal de Recogida en Cali (Domicilio Puerta a Puerta)' + : '🏁 Dirección Principal de Llegada en Cali (Entrega en Domicilio)'; + } + if (buenaStopLabel) { + buenaStopLabel.textContent = isCali + ? '🏁 Parada de Destino en Buenaventura' + : '📍 Punto Oficial de Salida en Buenaventura'; + } } if (originSelect) { @@ -2232,14 +2295,18 @@ function initPassengerCalculator() { const pAddress = (!d.sameAddress && d.address && d.address.trim()) ? d.address.trim() - : (caliAddress || 'Punto Oficial Buenaventura'); + : (caliAddress || (isCaliOrigin ? 'Cali, Valle del Cauca' : 'Buenaventura, Valle del Cauca')); + + const pCoords = (i === 1 && window.passengerGpsCoords) + ? window.passengerGpsCoords + : (isCaliOrigin ? [-76.5320, 3.4215] : [-77.0250, 3.8820]); validatedPassengers.push({ nombre: d.nombre.trim(), documentoIdentidad: d.doc.trim(), telefono: d.phone.trim(), direccionRecogida: pAddress, - coordenadas: [-76.5320, 3.4215], + coordenadas: pCoords, notas: d.notes ? d.notes.trim() : '', esTitular: (i === 1) }); @@ -2268,11 +2335,15 @@ function initPassengerCalculator() { `; try { + const userTripCoords = (window.passengerGpsCoords && window.passengerGpsCoords.length === 2) + ? window.passengerGpsCoords + : (isCaliOrigin ? [-76.5320, 3.4215] : [-77.0250, 3.8820]); + const payload = { usuarioId: currentUser ? currentUser._id : undefined, sentido: isCaliOrigin ? 'CALI_A_BUENAVENTURA' : 'BUENAVENTURA_A_CALI', - direccionTexto: caliAddress || 'Terminal Buenaventura', - coordenadas: [-76.5320, 3.4215], + direccionTexto: caliAddress || (isCaliOrigin ? 'Cali, Valle del Cauca' : 'Buenaventura, Valle del Cauca'), + coordenadas: userTripCoords, puntoFijoBuenaventura: { nombre: buenaStopSelect ? buenaStopSelect.options[buenaStopSelect.selectedIndex].text : 'Terminal de Transporte de Buenaventura', coordenadas: [-77.0250, 3.8820] @@ -2694,6 +2765,34 @@ function initFreightCalculator() { }); } + // Botones GPS para Recogida y Entrega de Encomiendas + const btnFreightGpsPickup = document.getElementById('btn-freight-gps-pickup'); + const btnFreightGpsDelivery = document.getElementById('btn-freight-gps-delivery'); + const freightPickupInput = document.getElementById('freight-pickup-address'); + const freightDeliveryInput = document.getElementById('freight-delivery-address'); + + if (btnFreightGpsPickup) { + btnFreightGpsPickup.addEventListener('click', async () => { + const loc = await getCurrentUserLocation(btnFreightGpsPickup); + if (loc) { + window.freightPickupCoords = [loc.lng, loc.lat]; + if (freightPickupInput) freightPickupInput.value = loc.address; + showNativeToast(`📍 Recogida establecida: ${loc.address}`); + } + }); + } + + if (btnFreightGpsDelivery) { + btnFreightGpsDelivery.addEventListener('click', async () => { + const loc = await getCurrentUserLocation(btnFreightGpsDelivery); + if (loc) { + window.freightDeliveryCoords = [loc.lng, loc.lat]; + if (freightDeliveryInput) freightDeliveryInput.value = loc.address; + showNativeToast(`🏁 Entrega establecida: ${loc.address}`); + } + }); + } + // Despacho / Creación de Encomienda con Pago Seguro y Cupón if (btnBookFreight) { btnBookFreight.addEventListener('click', async (e) => { @@ -2702,6 +2801,8 @@ function initFreightCalculator() { const senderPhone = document.getElementById('sender-phone')?.value.trim() || currentUser?.telefono || ''; const receiverPhone = document.getElementById('receiver-phone')?.value.trim(); const packageDesc = document.getElementById('package-desc')?.value.trim(); + const freightPickupAddr = freightPickupInput?.value.trim() || 'Cali, Valle del Cauca'; + const freightDeliveryAddr = freightDeliveryInput?.value.trim() || 'Terminal Buenaventura'; if (!senderPhone || senderPhone.replace(/\D/g, '').length < 7) { alert('⚠️ Por favor ingresa el teléfono/WhatsApp del remitente.'); @@ -2743,6 +2844,12 @@ function initFreightCalculator() { remitenteId: currentUser ? (currentUser._id || currentUser.id) : undefined, remitenteNombre: senderName || 'Remitente', remitenteTelefono: senderPhone, + direccionRecogida: freightPickupAddr, + coordenadasRecogida: window.freightPickupCoords || [-76.5320, 3.4215], + ciudadOrigen: (window.freightPickupCoords && window.freightPickupCoords[1] > 3.6 && window.freightPickupCoords[0] < -76.8) ? 'BUENAVENTURA' : 'CALI', + direccionEntrega: freightDeliveryAddr, + coordenadasEntrega: window.freightDeliveryCoords || [-77.0250, 3.8820], + ciudadDestino: (window.freightDeliveryCoords && window.freightDeliveryCoords[1] < 3.6 && window.freightDeliveryCoords[0] > -76.8) ? 'CALI' : 'BUENAVENTURA', tipoPaquete: packageTypeSelect ? packageTypeSelect.options[packageTypeSelect.selectedIndex].text : 'Paquete Pequeño', factor: parseFloat(packageTypeSelect?.value || '1.2'), valorDeclarado: parseFloat(declaredValueInput?.value || '100000'), diff --git a/transporte-cali-buenaventura/backend/src/index.ts b/transporte-cali-buenaventura/backend/src/index.ts index 4b71bba..46d1913 100644 --- a/transporte-cali-buenaventura/backend/src/index.ts +++ b/transporte-cali-buenaventura/backend/src/index.ts @@ -123,6 +123,65 @@ const server = http.createServer(async (req, res) => { return authService.verifyRole(token, allowedRoles); }; + // 1.1. Geocodificación inversa satelital (Dirección por ubicación actual) + if (pathname === '/api/geo/reverse' && req.method === 'GET') { + const lat = parseFloat(url.searchParams.get('lat') || ''); + const lng = parseFloat(url.searchParams.get('lng') || url.searchParams.get('lon') || ''); + if (isNaN(lat) || isNaN(lng)) { + return sendJson(400, { success: false, error: 'Coordenadas lat y lng inválidas' }); + } + + try { + const nominatimUrl = `https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${lat}&lon=${lng}&zoom=18&addressdetails=1`; + const fetchRes = await fetch(nominatimUrl, { + headers: { + 'User-Agent': 'PacificTransGO/2.0 (admin@pacifictrans.co)', + 'Accept-Language': 'es', + }, + }); + + if (fetchRes.ok) { + const data = await fetchRes.json(); + const addr = data.address || {}; + + // Formatear dirección al estilo colombiano + const parts: string[] = []; + if (addr.road) { + let roadPart = addr.road; + if (addr.house_number) roadPart += ` #${addr.house_number}`; + parts.push(roadPart); + } + if (addr.neighbourhood || addr.suburb) { + parts.push(`Barrio ${addr.neighbourhood || addr.suburb}`); + } + const city = addr.city || addr.town || addr.municipality || (lat > 3.6 ? 'Buenaventura' : 'Cali'); + parts.push(city); + if (addr.state) parts.push(addr.state); + + const formattedAddress = parts.length > 0 ? parts.join(', ') : data.display_name; + + return sendJson(200, { + success: true, + address: formattedAddress, + city, + coordinates: [lng, lat], + raw: addr, + }); + } + } catch (err: any) { + console.warn('⚠️ [Nominatim Reverse Geocode Warning]:', err.message); + } + + // Fallback inteligente si la red satelital o Nominatim no responde + const inferredCity = (lat > 3.7 && lng < -76.8) ? 'Buenaventura' : 'Cali'; + return sendJson(200, { + success: true, + address: `Ubicación GPS (${lat.toFixed(5)}, ${lng.toFixed(5)}), ${inferredCity}`, + city: inferredCity, + coordinates: [lng, lat], + }); + } + // 2. Pooling inteligente (Transporte) if (pathname === '/api/trips/pool' && req.method === 'POST') { const body = await getJsonBody(); @@ -619,15 +678,38 @@ const server = http.createServer(async (req, res) => { }; // Descarga directa del APK Oficial Android - if (pathname === '/PacifictransGo.apk' || pathname === '/download/apk') { + if ( + pathname === '/PacifictransGo.apk' || + pathname === '/download/apk' || + pathname === '/apk' || + pathname === '/app' || + pathname === '/descarga-apk' || + pathname === '/descargar-apk' + ) { const localApk = path.join(PUBLIC_DIR, 'PacifictransGo.apk'); const fallbackApk = path.resolve(__dirname, '../../../pacifictrans-app/public/PacifictransGo.apk'); const vpsApk = '/home/carlos/apps/dripzone-app/public/PacifictransGo.apk'; const targetApk = fs.existsSync(localApk) ? localApk : (fs.existsSync(fallbackApk) ? fallbackApk : vpsApk); - if (serveStaticFile(targetApk, MIME_TYPES['.apk'])) return; + if (fs.existsSync(targetApk)) { + try { + const stat = fs.statSync(targetApk); + res.writeHead(200, { + 'Content-Type': 'application/vnd.android.package-archive', + 'Content-Length': stat.size, + 'Content-Disposition': 'attachment; filename="PacifictransGo.apk"', + 'Cache-Control': 'no-cache', + 'Access-Control-Allow-Origin': '*', + }); + fs.createReadStream(targetApk).pipe(res); + return; + } catch (e) { + console.error('Error serving APK:', e); + } + } } + // Archivo estático directo (HTML, CSS, JS, Imágenes) let relativePath = pathname === '/' ? 'index.html' : pathname.replace(/^\//, ''); let targetPath = path.join(PUBLIC_DIR, relativePath);