# GeoDelix - continuidad del proyecto

Este documento resume el estado actual de GeoDelix para retomar el trabajo sin reconstruir contexto.

## Integracion ERP - entrega basica sin ubicacion - 2026-07-11

El receptor `mapas-box/central/api/agregar-entrega-erp.php` ahora acepta `latlong`
vacio u omitido para poder crear una entrega basica con factura y cliente. La
ubicacion se completa luego al editar la entrega desde GeoDelix dentro del ERP.

La validacion compartida de alta conserva el control de formato: si se envia un
`latlong` no vacio, debe seguir teniendo formato `latitud, longitud`. Las entregas
sin coordenadas no se dibujan en los mapas hasta que se complete la ubicacion.
En la tabla de Entregas, mientras el campo este vacio se muestra `Sin ubicacion`
en lugar de dejar la celda sin texto.

En el formulario compartido de nueva/editar entrega, `Direccion` aparece antes de
`Ubicacion Google Maps`. Si la direccion esta vacia y hay coordenadas validas,
`central.js` consulta Mapbox Geocoding v6 cuando el campo de ubicacion pierde el
foco y completa la direccion en espanol. Nunca reemplaza una direccion ya escrita
y envia las coordenadas a Mapbox en orden longitud/latitud.

La vista ERP reutiliza el listado de Central, pero las firmas se sirven desde
`mapas-box/central/firmas/`. `geodelix_base_url()` normaliza las solicitudes que
entran por `/mapas-box/erp/` hacia la URL absoluta `/mapas-box/central`, evitando
previews rotas que apunten incorrectamente a `/mapas-box/erp/firmas/`.

La tabla de Entregas reemplazo la columna `Creada` por `Modificada`, mostrando
`fecha_actualizado` o `Sin modificar`. Todo el listado se ordena primero por la
modificacion mas reciente; las filas nunca modificadas quedan despues y se ordenan
entre si por `fecha_creado` descendente.

En la columna `Factura`, las entregas cuyo origen es ERP muestran una segunda
linea con referencia cruzada en formato `#ID_GEODELIX - ERP ID_ERP`, por ejemplo
`#14 - ERP 12516`. Las entregas manuales no muestran esa linea. Factura,
`origen_id`, cliente y telefono forman parte de la busqueda rapida de la tabla.
El placeholder visible es `Buscar...`; `origen_id` se compara como texto completo,
por lo que una parte numerica como `1234` encuentra `ERP-12345` sin escribir el
prefijo.

El auto-refresh de la tabla conserva la pagina cliente actual mediante un valor
de un solo uso en `sessionStorage`: antes de recargar guarda la pagina y al cargar
la restaura y borra la clave. Si la cantidad de paginas disminuye, el paginador la
ajusta a la ultima disponible. `central.js` quedo en `v=2.4`.

En Cliente, la ficha de la entrega muestra `referencia_entrega` en una card
destacada inmediatamente debajo de `Ruta sugerida`. La card se oculta cuando no
hay referencia. El endpoint compartido expone el dato como `frontend.reference`
y `mapa-cliente.js` quedo versionado como `v=5.6`. En mobile la card ocupa todo
el ancho del grid, igual que `Ruta sugerida`. La ficha mobile no limita su altura,
asi el fondo blanco acompana referencias de varias lineas y mantiene margen abajo;
el CSS quedo en `v=5.4`.

Al iniciar navegacion, la card flotante `En trayecto` tambien mantiene visible la
misma referencia debajo de distancia y tiempo. Ocupa todo el ancho del panel y se
oculta si la entrega no tiene referencia. Assets: CSS `v=5.5`, JS `v=5.7`.

Para evitar que Safari/iOS conserve un `mapa-cliente.html` anterior, el login
redirige a `mapa-cliente.html?v=5.7`, `login-chofer.js` quedo en `v=1.1` y el
manifest en `v=1.2`. Un `.htaccess` de Cliente marca HTML y webmanifest como
`no-cache, no-store`, mientras CSS/JS siguen usando sus versiones de asset.

## Central integrada al ERP - 2026-07-11

Se creo una entrada especifica para incrustar GeoDelix dentro del ERP:

```text
https://mobilex.fenixdev.uno/mapas-box/erp/
```

La entrada `mapas-box/erp/index.php` activa el modo ERP y reutiliza directamente
`mapas-box/central/index.php`; no existe una copia paralela de la logica ni de las
pantallas.

Comportamiento del modo ERP:

- conserva la marca y el rediseno completo de GeoDelix,
- conserva Panel, Entregas y Choferes dentro del iframe del ERP,
- oculta el acceso a `Mapa chofer`,
- incorpora `Mapa Central` a la navegacion interna,
- el mapa central se muestra dentro del panel ERP y no abre una pestana externa,
- el boton de regreso del mapa vuelve al Panel dentro del iframe,
- se evita cargar el auto-refresh del admin sobre la vista de mapa para no reiniciar el mapa mientras se usa.

La central independiente conserva el comportamiento anterior:

```text
https://mobilex.fenixdev.uno/mapas-box/central/index.php
```

Pendiente de validacion visual: probar la nueva URL dentro del iframe real del ERP
y ajustar solamente alturas o espacios si el contenedor de ScriptCase lo requiere.

## Corte de continuidad - 2026-07-11

Ultimos ajustes en `mapas-box/central/index.php`:

- la tabla de Entregas ahora muestra la columna `Origen`, con el valor en mayusculas (`MANUAL`, `ERP`, etc.),
- el encabezado de la primera columna se cambio de `Pedido` a `Factura`,
- cuando una entrega no tiene chofer, `Sin asignar` aparece como una etiqueta roja suave,
- se ajusto la vista compacta de la tabla y se incremento la version del CSS a `central.css?v=3.1`.

Estado inmediato para retomar:

- el usuario va a enviar una entrega con datos reales desde los formularios del ERP,
- despues del envio hay que revisar como quedo registrada en GeoDelix,
- la proteccion contra duplicados por `origen_id` ya esta implementada,
- antes de produccion todavia falta API key.

## Integracion ERP - endpoint inicial de alta - 2026-07-10

Se creo un endpoint independiente para comenzar pruebas desde el ERP construido en ScriptCase:

```text
POST /mapas-box/central/api/agregar-entrega-erp.php
https://mobilex.fenixdev.uno/mapas-box/central/api/agregar-entrega-erp.php
```

Comportamiento inicial:

- acepta JSON y tambien campos POST tradicionales de ScriptCase,
- `cliente_nombre` es obligatorio; `latlong` puede enviarse vacio u omitirse,
- usa `origen = erp` si no se envia otro origen,
- reutiliza `geodelix_create_delivery()` y las validaciones vigentes,
- devuelve HTTP 201 con `ok`, `id`, `created` y `message`,
- registra evento adicional `creada_erp`.

Estado y pendientes:

- listo para pruebas iniciales desde el ERP,
- `origen_id` es obligatorio y un reenvio devuelve la fila existente con `created: false`,
- falta implementar API key antes de produccion.

El evento real del boton de la grilla ScriptCase esta en
`mapas-box/scriptcase/evento_envio_entrega.php`. Todos los resultados se muestran
con `sc_ajax_message()`. El archivo no usa `echo` ni `exit`: ejecuta un unico bloque
`do...while(false)` y corta cada rama con `break`, permitiendo que ScriptCase termine
de construir la respuesta Ajax y muestre el mensaje. Controla lookup,
validaciones, JSON, conexion cURL, HTTP y respuesta del receptor. Si recibe
`created: false`, muestra `GeoDelix - entrega duplicada` con `origen_id` y el ID
existente; cuando crea, informa el nuevo ID de GeoDelix.
Los mensajes finales de creada y duplicada usan la referencia combinada
`#ID_GEODELIX - ERP-ID_ERP`, igual que la tabla de Entregas.
`serie` y `numero` se leen como valores opcionales: si ambos estan vacios se envia
`factura_numero` vacio, que GeoDelix admite. El evento completo esta protegido con
`try/catch` para convertir excepciones de preparacion en `sc_ajax_message` y evitar
la ventana tecnica de errores de ScriptCase.
Los mensajes usan el tercer parametro real de `sc_ajax_message()` con
`type=error|warning|success&button=Y`; no se pasa el literal `String_toast`, que
era el nombre documental del quinto parametro y podia impedir la visualizacion.

Validacion realizada:

```text
php -l mapas-box/central/api/agregar-entrega-erp.php
```

## Integracion ERP - Blank emisor ScriptCase - 2026-07-10

Se dejo un archivo fuente para crear la app Blank de ScriptCase que envia una entrega del ERP hacia GeoDelix:

```text
mapas-box/scriptcase/blanck_envio_entrega.php
```

Uso previsto:

- crear/editar una Blank en ScriptCase llamada `blanck_envio_entrega`,
- pegar/adaptar ese codigo en el evento principal de la Blank,
- llamar la Blank con `?id=123` o enviar `POST id=123`,
- el codigo lee la fila del ERP con `sc_lookup()`,
- arma el JSON y lo envia por cURL a:

```text
https://mobilex.fenixdev.uno/mapas-box/central/api/agregar-entrega-erp.php
```

Bloque que probablemente hay que adaptar en el ERP real:

```text
LECTURA ERP
tabla/campos del SELECT
```

El ejemplo usa como base la tabla historica `geodelix_entregas` y envia:

```text
origen, origen_id, factura_numero, cliente_nombre, cliente_telefono,
direccion_entrega, referencia_entrega, latlong, prioridad, horario_entrega
```

Estado:

- listo como plantilla inicial para pruebas desde ScriptCase,
- falta probar desde el ERP real,
- falta definir si el ERP guardara el `geodelix_id` devuelto,
- la idempotencia por `origen_id` ya esta activa en el receptor,
- falta agregar API key antes de produccion.

## Ajuste mobile - GPS visual separado del recalculo de ruta - 2026-07-10

Problema informado en prueba de calle:

- la flecha del chofer seguia moviendose con tirones,
- el tiron coincidia especialmente con `Actualizando llegada...` y la llegada de una nueva ruta,
- la camara cortaba su animacion anterior en cada lectura GPS.

Ajuste aplicado en `mapas-box/cliente/mapa-cliente.js`:

```text
driverVisualTransitionMs: 900
mapa-cliente.js?v=5.5
```

Comportamiento:

- `driverPosition` conserva inmediatamente la posicion GPS real para backend, rumbo, cercania y disparo de Directions,
- la flecha usa una posicion visual independiente que interpola suavemente entre puntos GPS,
- la camara de navegacion acompana esa posicion visual en cada frame,
- el recálculo de distancia/tiempo puede actualizar la card y reemplazar la geometria sin mover directamente la flecha,
- se elimino el `map.stop()` del seguimiento de navegacion para no cortar una animacion cada vez que llega otro punto.

Validacion:

```text
node --check mapas-box/cliente/mapa-cliente.js
```

Estado actual:

- validacion tecnica completada,
- **pendiente test real en ruta**, no considerar el ajuste aprobado todavia,
- durante la prueba observar fluidez de la flecha y la camara cuando la card cambia de `Actualizando llegada...` a la nueva distancia/tiempo,
- si persiste el tiron, continuar desde esta separacion y ajustar primero `driverVisualTransitionMs` o la interpolacion visual sin volver a unir el marcador con Directions.

## Corte actual validado - 2026-07-09 - `mapas-box` listo para prueba en calle

El usuario valido en navegador/mobile el flujo principal de la rama independiente Mapbox:

- central funcionando con mapa y choferes,
- app mobile de chofer funcionando con login,
- puntos de entrega, filtros, detalle, ruta, navegacion y firma,
- confirmacion de entrega actualizando backend,
- entrega cerrada deshabilitando navegacion y nuevo cierre,
- experiencia visual aprobada para salir a probar en calle.

Rama activa para seguir migrando:

```text
mapas-box/
```

La version estable original queda intacta en:

```text
mapas/
```

Entradas vigentes:

```text
https://mobilex.fenixdev.uno/mapas-box/central/index.php
https://mobilex.fenixdev.uno/mapas-box/central/mapa-central.html
https://mobilex.fenixdev.uno/mapas-box/cliente/
```

### Estado tecnico vigente

`mapas-box` esta aislado de `mapas`:

- base clonada propia configurada en `mapas-box/central/config.php`,
- endpoints JS apuntando a `/mapas-box/central/api/`,
- sesion local de chofer usando `geodelix_box_chofer`,
- firmas bajo `mapas-box/central/firmas/`,
- token publico Mapbox en `mapas-box/cliente/mapbox-config.js`,
- cache actual mobile: `mapa-cliente.css?v=4.4` y `mapa-cliente.js?v=4.4`.

Archivos principales del flujo mobile:

```text
mapas-box/cliente/mapa-cliente.html
mapas-box/cliente/mapa-cliente.js
mapas-box/cliente/mapa-cliente.css
mapas-box/cliente/mapbox-config.js
```

### UX mobile validada

Mapa del chofer:

- Mapbox GL JS reemplazo a Leaflet/OpenStreetMap en `mapas-box/cliente/`.
- Marcadores de entrega y chofer siguen usando HTML/CSS propios para conservar identidad visual.
- Los popups de Mapbox se ocultan en mobile; la seleccion se trabaja desde la barra/card propia.
- El boton de ubicacion es un control cuadrado con icono Font Awesome `fa-location-crosshairs`, ubicado a la izquierda sobre los controles de zoom.
- La etiqueta textual debajo del boton de ubicacion fue eliminada.

Filtros:

- se elimino la card inferior de `Estados`,
- las cards superiores `Entregas`, `Pendientes` y `Hechas` filtran el mapa,
- `Entregas` vuelve a mostrar todo,
- el filtro activo se marca con color suave,
- aparece un chip compacto inferior derecho solo cuando hay filtro activo para volver a `Todos`.

Seleccion de entrega:

- tocar un punto abre/actualiza una card superior compacta,
- muestra estado, horario, distancia y resumen de ruta,
- si la entrega esta cerrada muestra `Entrega cerrada.` y no habilita acciones.

Acciones de ruta:

- los botones grandes `Como llegar` e `Iniciar` viven en el dock flotante inferior,
- `Como llegar` calcula ruta con Mapbox Directions,
- `Iniciar` calcula la ruta primero si hace falta,
- al iniciar trayecto se oculta la card de datos y queda el mapa en modo navegacion.

Modo trayecto:

- aparece una card limpia arriba con `En trayecto`, distancia restante y minutos restantes,
- esa card se alimenta con Mapbox Directions y se actualiza cuando se recalcula la ruta,
- el mapa hace zoom/pitch y sigue al chofer,
- el dock inferior cambia a boton unico `Entregar`.

Entrega:

- `Entregar` abre el formulario real de firma,
- al confirmar, se actualiza backend,
- se cancela/limpia la ruta activa,
- el punto pasa a entregado,
- la entrega queda bloqueada para nueva navegacion o nueva firma desde el flujo de trayecto.

### Rutas y recalculo

Configuracion actual en `mapas-box/cliente/mapa-cliente.js`:

```text
routeProfile: "mapbox/driving"
routeRefreshMs: 30000
routeRefreshMeters: 55
```

Comportamiento:

- la ruta se pide a Mapbox Directions API (`/directions/v5/mapbox/driving`),
- se solicita geometria GeoJSON con `overview=full`,
- se dibuja dentro del mapa con capas propias,
- en modo trayecto se recalcula automaticamente si paso el intervalo configurado o si el chofer se movio mas que el umbral configurado,
- se evita recalcular cada segundo para cuidar consumo de API y fluidez.

### Validaciones realizadas

Ultima validacion tecnica:

```text
node --check mapas-box/cliente/mapa-cliente.js
```

Validacion funcional informada por el usuario:

- login mobile correcto,
- mapa central y mobile correctos,
- filtros y detalle funcionando,
- ruta marcada y navegacion iniciada,
- card de trayecto visible con distancia/tiempo,
- boton `Entregar` abre formulario,
- firma y cierre actualizan backend,
- entrega cerrada queda sin navegacion ni entrega repetida.

### Proximo paso sugerido

El siguiente paso es prueba real en calle:

- confirmar precision del GPS en movimiento,
- revisar si `routeRefreshMs=30000` y `routeRefreshMeters=55` se sienten bien,
- observar si la card de trayecto queda en buena posicion con sol/movimiento,
- revisar consumo/limites de Mapbox luego de pruebas reales,
- ajustar comportamiento de camara si hace falta.

### Mejoras de navegacion pendientes para despues de la prueba en calle

Prioridad acordada:

1. Instrucciones visuales proximas dentro de la app.
2. Aviso de `Llegando a destino`.
3. Vibracion en mobile para alertas importantes.
4. Voz de navegacion como ultima etapa.

Nota tecnica:

- para instrucciones paso a paso hay que pedir a Mapbox Directions con `steps=true`,
- con esos pasos se puede mostrar la proxima maniobra en una card/chip de navegacion,
- la voz podria implementarse mas adelante con `speechSynthesis`, pero no es prioridad inmediata.

### Ajuste post prueba en calle - GPS mas fluido

Primer feedback real:

- la posicion se sentia con tirones,
- el calculo/recalculo de ruta se sentia lento.

Ajuste aplicado en `mapas-box/cliente/mapa-cliente.js`:

```text
routeRefreshMs: 15000
routeRefreshMeters: 25
driverLocationBackendRefreshMs: 5000
driverLocationMaximumAgeMs: 1000
driverLocationTimeoutMs: 8000
```

Cambio de comportamiento:

- se reemplazo el seguimiento principal por `navigator.geolocation.watchPosition`,
- `getCurrentPosition` queda para lectura puntual/manual y fallback,
- el marcador local del chofer se actualiza con cada punto GPS recibido,
- el envio al backend central queda limitado a un maximo aproximado de cada 5 segundos,
- la camara en modo navegacion usa una animacion mas corta para reducir sensacion de salto,
- el recalculo de Mapbox Directions ahora se dispara antes: 15 segundos o 25 metros.

Cache vigente despues de este ajuste:

```text
mapa-cliente.js?v=4.5
```

### Ajuste fino post calle - ruta mas rapida y menos tiron

Segundo feedback real:

- la precision del GPS mejoro,
- el seguimiento todavia puede sentirse mas rapido,
- el calculo de ruta sigue algo lento,
- se perciben tirones de camara.

Ajuste aplicado:

```text
routeRefreshMs: 8000
routeRefreshMeters: 12
routeRequestTimeoutMs: 7000
```

Comportamiento:

- la ruta puede recalcular mucho antes: 8 segundos o 12 metros,
- Directions tiene timeout propio de 7 segundos para no quedar esperando una respuesta lenta,
- sigue habiendo una sola solicitud de ruta en curso para no saturar Mapbox,
- la camara corta animaciones anteriores con `map.stop()` antes de recentrar,
- la animacion de seguimiento en modo navegacion baja a 120 ms,
- el golpe inicial de camara al iniciar trayecto baja de 650 ms a 420 ms,
- durante recalculo se mantiene la ultima distancia visible y solo se marca que esta actualizando.

Cache vigente:

```text
mapa-cliente.js?v=4.6
```

### Ajuste visual de navegacion - rotacion e inclinacion

Pedido posterior:

- el mapa necesitaba rotar siguiendo el rumbo del vehiculo,
- la navegacion necesitaba un poco mas de inclinacion para sentirse mas real.

Ajuste aplicado:

```text
navigationPitch: 58
mapa-cliente.js?v=4.7
```

Comportamiento:

- en modo trayecto la camara usa `pitch` 58,
- si el GPS entrega `heading`, el mapa rota con ese rumbo,
- si no hay `heading`, se usa el rumbo calculado entre posiciones cuando el vehiculo se movio lo suficiente,
- al cancelar/cerrar la ruta se vuelve a `pitch: 0` y `bearing: 0` para regresar al mapa normal.

### Ajuste marcador de vehiculo - flecha tipo navegador

Feedback posterior:

- el punto con flechita podia quedar apuntando hacia un lado contrario al sentido real,
- en algunos tramos el `heading` del GPS parecia llegar invertido o tardio,
- al rotar el mapa, la flecha no debia rotar otra vez completa contra la pantalla.

Ajuste aplicado:

```text
mapa-cliente.css?v=4.8
mapa-cliente.js?v=4.8
```

Comportamiento:

- se reemplazo el punto/flechita por un icono Font Awesome `fa-location-arrow`,
- en movimiento se prefiere el rumbo calculado entre posiciones sobre el `heading` crudo del GPS,
- si no hay movimiento suficiente se conserva el ultimo rumbo confiable,
- en modo navegacion la flecha queda apuntando hacia adelante y el mapa rota con el rumbo,
- fuera de navegacion, con mapa normal, la flecha rota segun el rumbo.

### Ajuste visual de ruta - flechas de direccion

Pedido posterior:

- mostrar dentro de la ruta algunas flechas para entender el sentido del trayecto.

Ajuste aplicado:

```text
mapa-cliente.js?v=5.0
```

Comportamiento:

- la ruta sigue usando la fuente GeoJSON `active-route`,
- conserva la linea con borde blanco y trazo verde,
- se agrego la capa `active-route-arrows` de tipo `symbol`,
- las flechas se repiten sobre la linea y siguen la direccion de la geometria de Mapbox Directions.

### Ajuste marcador sobre ruta - snap visual

Feedback posterior:

- la ruta seguia bien la calle,
- la flecha del vehiculo quedaba un poco corrida hacia la derecha de la linea.

Ajuste aplicado:

```text
routeSnapMaxMeters: 40
mapa-cliente.js?v=5.2
```

Comportamiento:

- en modo navegacion se guarda la geometria activa de Mapbox Directions,
- el GPS real se sigue usando para backend, distancia, rumbo y recalculo,
- solo el marcador visual y la camara se proyectan al punto mas cercano de la ruta,
- si el GPS esta a mas de 40 metros de la linea, no se fuerza el snap y se muestra la posicion real para no mentir cuando hay desvio fuerte.

### Mapa central - orden operativo de entregas

Pedido posterior:

- usar el mapa central para organizar entregas manualmente desde los puntos,
- mostrar la ficha mas angosta y con datos hacia abajo,
- permitir cambiar `Orden de entrega` desde la card del mapa,
- mantener tambien el campo visible en el formulario interno.

Ajuste aplicado:

```text
mapas-box/central/mapa-central.css?v=1.5
mapas-box/central/mapa-central.js?v=2.1
```

Comportamiento:

- `prioridad` pasa a usarse como `Orden de entrega`,
- la card del mapa central queda mas angosta y vertical,
- muestra telefono, estado, horario, chofer y orden de entrega,
- el orden se puede guardar desde la card con `PATCH /mapas-box/central/api/entregas.php`,
- el marcador de entrega muestra el orden si es mayor que 0; si no, conserva el id,
- el formulario interno de entrega muestra `Orden de entrega` como campo editable,
- la tabla interna muestra el orden junto al pedido,
- el listado ordena pendientes primero y luego `prioridad` ascendente, dejando orden 0 al final.

Correccion posterior:

- el guardado desde mapa central se cambio de `PATCH` a `POST` con `action: "update_priority"` para mayor compatibilidad con el servidor,
- se quito el autoguardado porque molestaba al escribir o usar el stepper del input,
- el campo `Orden de entrega` ahora guarda solo con boton `Guardar` o tecla Enter,
- debajo del control muestra mensaje verde del estilo `Esta entrega queda en posicion 4.`,
- mientras el input esta enfocado el refresco periodico no pisa el numero que se esta escribiendo,
- cache vigente: `mapa-central.css?v=1.7` y `mapa-central.js?v=2.3`.

### Identidad visual GeoDelix - variables azules

Paleta definida para administracion y mapa central:

```text
Tipografia principal: Montserrat
Color principal: #007BFF
Color secundario: #00A8FF
Color oscuro corporativo: #0B1F5E
Fondo: #F4F8FC
```

Variables agregadas en:

```text
mapas-box/central/assets/central.css
mapas-box/central/mapa-central.css
```

Variables principales:

```text
--geodelix-primary
--geodelix-secondary
--geodelix-dark
--geodelix-bg
--geodelix-primary-rgb
--geodelix-secondary-rgb
--geodelix-dark-rgb
--font-primary
--brand
--brand-secondary
--brand-dark
--brand-soft
--brand-line
```

Alcance:

- se aplico primero a administracion y mapa central,
- el verde corporativo heredado se reemplazo por azul GeoDelix,
- los colores semanticos se mantienen: verde para entregado, rojo/alerta cuando corresponda,
- la app del chofer queda sin migrar de paleta por ahora para no tocar lo validado en calle.

Cache vigente:

```text
assets/central.css?v=2.6
mapa-central.css?v=1.7
```

### Admin entregas - mapita en vista de detalle

Pedido posterior:

- en la tabla de entregas, al abrir la vista con el ojito, mostrar debajo de `Ubicacion` un mapa chico de Mapbox,
- por ahora solo en modo vista, no en editar,
- debe ser interactivo para zoom y arrastre, solo para verificar posicion.

Ajuste aplicado:

```text
assets/central.css?v=2.7
assets/central.js?v=1.8
```

Comportamiento:

- el admin carga Mapbox GL JS y el token publico ya existente,
- la vista de entrega agrega `viewLocationMapWrap` y `viewLocationMap`,
- si `latlong` es valido, renderiza un mapa `streets-v12` centrado en la ubicacion,
- agrega un marcador azul en la posicion,
- permite zoom/arrastre con controles Mapbox,
- si no hay coordenadas validas, el bloque queda oculto.

### Admin entregas - mapita en alta/edicion

Pedido posterior:

- agregar el mismo mapa chico debajo de `Ubicacion Google Maps` en el formulario de entrega,
- como en alta la entrega todavia no existe en base, el mapa debe aparecer apenas el campo `latlong` tenga coordenadas validas,
- mantenerlo como vista interactiva de posicion, sin cambiar todavia la forma de elegir ubicacion.

Ajuste aplicado:

- el form agrega `deliveryLocationMapWrap` y `deliveryLocationMap`,
- `central.js` reutiliza el render generico de Mapbox para vista y formulario,
- al abrir el drawer carga el mapa si ya hay coordenadas,
- al escribir, pegar o cambiar el campo `latlong`, el mapa aparece/se actualiza,
- si el campo esta vacio o invalido, el bloque queda oculto.

### Admin entregas - buscador instantaneo

Pedido posterior:

- en la tabla del admin agregar un buscador por cliente o celular,
- filtrar a medida que se escribe,
- mantener los filtros existentes de estado, chofer y fecha.

Ajuste aplicado:

```text
assets/central.css?v=2.8
assets/central.js?v=1.9
```

Comportamiento:

- el buscador `deliveryQuickSearch` filtra las filas ya cargadas en pantalla,
- cada fila expone `data-search` con cliente y telefono,
- la busqueda ignora mayusculas/acentos y permite buscar telefono solo por numeros,
- si no hay coincidencias muestra `No hay entregas para esa busqueda`,
- mientras el buscador tiene foco o texto, el auto-refresh no recarga la tabla.

### Mapa central - ruta sugerida por orden de entrega

Pedido posterior:

- desde la card del mapa central donde se cambia `Orden de entrega`, agregar `Mostrar ruta`,
- construir un trayecto visual siguiendo el orden asignado a las entregas,
- que la linea marque direccion y ayude al admin a validar si el reparto tiene sentido.

Ajuste aplicado:

```text
mapa-central.css?v=1.8
mapa-central.js?v=2.4
```

Comportamiento:

- la card del punto suma bloque `Ruta sugerida` con boton `Mostrar ruta` y boton compacto para limpiar,
- toma entregas pendientes con coordenadas validas y `prioridad > 0`,
- si la entrega seleccionada tiene chofer, arma la ruta solo para ese chofer,
- si no tiene chofer, usa las entregas ordenadas pendientes disponibles,
- ordena por `prioridad` y luego por `id`, por lo que admite prioridades duplicadas durante ajustes,
- calcula ruta real por calles con Mapbox Directions,
- dibuja linea azul con borde blanco y flechas sobre el trayecto,
- muestra cantidad de paradas, distancia y tiempo estimado,
- limita a 25 paradas por la restriccion de Mapbox Directions.

### Reversion UX - orden visible y ruta manual fuera del admin/central

Decision posterior:

- no conviene basar el flujo real en un orden fijo porque la posicion del chofer cambia,
- se mantiene como mejor decision que el mapa del chofer marque en rojo la entrega pendiente mas cercana segun su posicion actual,
- el admin/central debe quedar simple y no empujar una ruta fija desde el escritorio.

Ajuste aplicado:

```text
assets/central.js?v=2.0
mapa-central.css?v=1.9
mapa-central.js?v=2.5
```

Comportamiento:

- en la ficha del mapa central se quitaron `Orden de entrega`, `Ruta sugerida` y el trazado de recorrido,
- se elimino del JS central el llamado a Mapbox Directions para ruta planificada,
- los marcadores del mapa central vuelven a etiquetarse por id de entrega, no por prioridad,
- en admin se quito `Prioridad` de la vista con ojito,
- en el formulario de alta/edicion `prioridad` queda como campo oculto para preservar el dato interno sin mostrarlo,
- en la tabla se quito el texto visible `Orden ...` del detalle del pedido.

### Mapa central - etiqueta de precision GPS

Pedido posterior:

- en la card lateral de choferes, el dato `5 m`, `14 m`, etc. debe explicar que tan buena es la precision.

Ajuste aplicado:

```text
mapa-central.js?v=2.6
```

Comportamiento:

- `<= 10 m`: `Buena precision`,
- `<= 25 m`: `Normal`,
- `<= 75 m`: `Aproximada`,
- `> 75 m`: `Imprecisa`,
- si no viene precision: `Sin precision`.

### Mapa central - cards superiores como filtros

Pedido posterior:

- copiar el modelo del mobile: las cards superiores filtran el mapa,
- cambiar `Hechas` por `Entregadas`,
- quitar la card inferior de estados,
- dejar abajo a la derecha solo la card/lista de choferes conectados, que sigue filtrando al tocar un chofer.

Ajuste aplicado:

```text
mapa-central.css?v=2.0
mapa-central.js?v=2.7
```

Comportamiento:

- `Entregas` muestra todas las entregas,
- `Pendientes` filtra pendientes,
- `Entregadas` filtra entregadas,
- la card de estados inferior se elimino,
- el panel de choferes muestra el conteo y cada chofer sigue actuando como filtro,
- los conteos de entregas se calculan sobre el conjunto completo para no cambiar al filtrar.

### Mobile chofer - cancelar navegacion desde card superior

Pedido posterior:

- en modo navegacion, la card superior de progreso tenia un icono de ruta a la derecha,
- cambiarlo por una X y usarlo para cancelar la navegacion actual sin tener que tocar el punto.

Ajuste aplicado:

```text
mapa-cliente.css?v=5.1
mapa-cliente.js?v=5.3
```

Comportamiento:

- `navigationProgressCard` ahora muestra un boton `navigationProgressCancel`,
- el boton usa icono Font Awesome `xmark`,
- al tocarlo ejecuta `clearRoute()`,
- cancela ruta, oculta progreso/dock y devuelve el mapa a pitch/bearing normal.

Ajuste posterior:

```text
mapa-cliente.js?v=5.4
```

- la X de la card superior ahora llama `cancelNavigationAndResetMap()`,
- ademas de limpiar la ruta, borra `selectedDelivery`,
- oculta la ficha de entrega,
- fuerza el dock inferior a `hidden` para que no queden `Como llegar` / `Iniciar` sin punto seleccionado.

### Mobile chofer - paleta GeoDelix azul

Pedido posterior:

- aplicar en mobile los mismos estilos visuales azules usados en admin y mapa central.

Ajuste aplicado:

```text
mapa-cliente.css?v=5.2
```

Comportamiento:

- `mapa-cliente.css` ahora define las mismas variables corporativas:
  `#007BFF`, `#00A8FF`, `#0B1F5E`, `#F4F8FC`,
- `--brand`, `--brand-dark`, `--bg`, `--text` y sombras usan esas variables,
- se retiraron restos del teal anterior `#0f8b8d` / `#0a6567`,
- los focos, bordes y sombras de ruta usan `--geodelix-primary-rgb`,
- `theme-color` del HTML paso a `#F4F8FC`.

### Admin entregas - paginacion de tabla

Pedido posterior:

- agregar paginacion a la tabla de entregas,
- mostrar 5 filas por pagina,
- formato visual: total de registros, controles `|< < N > >|`, pagina actual.

Ajuste aplicado:

```text
assets/central.css?v=3.0
assets/central.js?v=2.1
```

Comportamiento:

- la paginacion es client-side sobre las filas ya cargadas,
- funciona junto con el buscador instantaneo,
- al escribir en el buscador vuelve a pagina 1,
- el total mostrado corresponde a las filas filtradas por la busqueda actual,
- si no hay coincidencias se oculta la paginacion y se muestra el mensaje de busqueda vacia.

## Corte actualizado - 2026-07-09 - rama Mapbox independiente

Se creo una copia completa e independiente de la app estable:

```text
mapas-box/
```

Objetivo:

- mantener `mapas/` como version estable y funcional,
- usar `mapas-box/` como base de migracion a Mapbox,
- no compartir endpoints, sesion de chofer ni conexion de base con la version estable.

Entradas de `mapas-box`:

```text
https://mobilex.fenixdev.uno/mapas-box/central/index.php
https://mobilex.fenixdev.uno/mapas-box/central/mapa-central.html
https://mobilex.fenixdev.uno/mapas-box/cliente/
```

Estado de aislamiento:

- `mapas-box/central/config.php` apunta a la base clonada nueva.
- Los endpoints JS de cliente y central apuntan a `/mapas-box/central/api/`.
- El manifest y metadatos sociales apuntan a `/mapas-box/cliente/`.
- La sesion local de chofer usa `geodelix_box_chofer` para no mezclarse con `mapas/`.
- Las firmas clonadas existen en `mapas-box/central/firmas/`.
- La salida de entregas usa `firma_archivo` para reconstruir URL bajo `/mapas-box/central/firmas/`, aunque la base clonada conserve `firma_url` historicas con `/mapas/`.

Validaciones realizadas:

```text
node --check mapas-box/cliente/mapa-cliente.js
node --check mapas-box/cliente/login-chofer.js
node --check mapas-box/central/mapa-central.js
php -l mapas-box/central/lib/bootstrap.php
php -l mapas-box/central/lib/deliveries.php
php -l mapas-box/central/lib/drivers.php
php -l mapas-box/central/index.php
REQUEST_METHOD=GET SCRIPT_NAME=/mapas-box/central/api/entregas.php HTTP_HOST=mobilex.fenixdev.uno HTTPS=on php mapas-box/central/api/entregas.php
REQUEST_METHOD=GET SCRIPT_NAME=/mapas-box/central/api/ubicacion-chofer.php HTTP_HOST=mobilex.fenixdev.uno HTTPS=on php mapas-box/central/api/ubicacion-chofer.php
```

Resultado de smoke test:

- `entregas.php` respondio `ok:true` con 4 entregas desde la base clonada.
- `ubicacion-chofer.php` respondio `ok:true` con 0 choferes en vivo.
- El panel renderizo correctamente por CLI contra la nueva base.

Proximo paso:

- abrir `mapas-box` en navegador y validar flujo visual completo,
- luego comenzar el cambio gradual de Google Maps a Mapbox dentro de `mapas-box` solamente.

### Primer paso Mapbox en chofer - 2026-07-09

Se cargo el token publico de Mapbox en:

```text
mapas-box/cliente/mapbox-config.js
```

Alcance aplicado:

- solo se migro el mapa del chofer (`mapas-box/cliente/mapa-cliente.html`, `.js`, `.css`),
- se reemplazo Leaflet/OpenStreetMap por Mapbox GL JS,
- se mantuvieron las mismas APIs de `mapas-box/central/api/`,
- se conservaron los marcadores HTML existentes (`delivery-marker`, `driver-marker`) para no cambiar la UX aprobada,
- la ubicacion viva del chofer sigue reportando a `ubicacion-chofer.php`,
- la confirmacion con firma no se modifico,
- el mapa central todavia no fue migrado a Mapbox.

Validaciones:

```text
node --check mapas-box/cliente/mapa-cliente.js
REQUEST_METHOD=GET SCRIPT_NAME=/mapas-box/central/api/entregas.php HTTP_HOST=mobilex.fenixdev.uno HTTPS=on php mapas-box/central/api/entregas.php
```

Resultado:

- JS sin errores de sintaxis,
- API de entregas siguio respondiendo `ok:true` con 4 entregas.

### Segundo paso Mapbox en central - 2026-07-09

Se migro tambien el mapa central de `mapas-box`:

```text
mapas-box/central/mapa-central.html
mapas-box/central/mapa-central.js
```

Alcance aplicado:

- se reemplazo Leaflet/OpenStreetMap por Mapbox GL JS,
- se reutilizo `mapas-box/cliente/mapbox-config.js` para no duplicar el token publico,
- se mantuvieron las APIs propias de `mapas-box/central/api/entregas.php` y `ubicacion-chofer.php`,
- se conservaron los marcadores HTML de entregas y choferes,
- se mantuvieron filtros por estado, filtro de solo choferes y filtro por chofer,
- se mantuvo el refresco de entregas cada 30 segundos y choferes cada 3 segundos.

Validaciones:

```text
node --check mapas-box/central/mapa-central.js
REQUEST_METHOD=GET SCRIPT_NAME=/mapas-box/central/api/entregas.php HTTP_HOST=mobilex.fenixdev.uno HTTPS=on php mapas-box/central/api/entregas.php
REQUEST_METHOD=GET SCRIPT_NAME=/mapas-box/central/api/ubicacion-chofer.php HTTP_HOST=mobilex.fenixdev.uno HTTPS=on php mapas-box/central/api/ubicacion-chofer.php
```

Resultado:

- JS sin errores de sintaxis,
- no quedaron referencias a Leaflet en `mapa-central`,
- entregas respondio `ok:true` con 4 entregas,
- ubicacion de choferes respondio `ok:true` con choferes en vivo cuando habia sesion activa.

### Tercer paso Mapbox en mobile - rutas dentro de la app - 2026-07-09

Se agrego el primer modo de rutas propio dentro del mapa del chofer:

```text
mapas-box/cliente/mapa-cliente.html
mapas-box/cliente/mapa-cliente.js
mapas-box/cliente/mapa-cliente.css
```

Comportamiento:

- al tocar una entrega, la ficha muestra boton `Ver ruta`,
- `Ver ruta` usa Mapbox Directions API (`/directions/v5/mapbox/driving`) con `geometries=geojson`,
- se dibuja la linea de ruta dentro del mapa con dos capas: borde blanco y linea principal verde,
- se muestra resumen de distancia y tiempo estimado,
- aparece boton `Comenzar` para activar seguimiento del chofer sobre la ruta,
- Google queda como respaldo con un boton secundario,
- al cambiar de entrega se limpia la ruta anterior,
- si la entrega se confirma, se limpia la ruta activa,
- en modo trayecto se recalcula la ruta como maximo cada 30 segundos o si el chofer se movio mas de 55 metros.

Validaciones:

```text
node --check mapas-box/cliente/mapa-cliente.js
REQUEST_METHOD=GET SCRIPT_NAME=/mapas-box/central/api/entregas.php HTTP_HOST=mobilex.fenixdev.uno HTTPS=on php mapas-box/central/api/entregas.php
```

Resultado:

- JS sin errores de sintaxis,
- API de entregas siguio respondiendo `ok:true` con 4 entregas,
- se valido Mapbox Directions con coordenadas publicas de ejemplo para no enviar datos operativos reales desde consola.

Correccion posterior:

- el boton `Comenzar` inicialmente activaba seguimiento pero era poco visible si el mapa ya estaba centrado,
- ahora cambia el resumen a `En trayecto`,
- cambia el boton a `Siguiendo`,
- deja `Recalcular` disponible,
- activa seguimiento y mueve la camara con zoom alto y pitch para que el inicio de ruta se note.

Correccion de UX posterior:

- el panel de entrega en mobile dejo de comportarse como bottom sheet porque tapaba demasiado el mapa,
- ahora la informacion de la entrega seleccionada se muestra como barra superior compacta,
- al tocar un punto se actualiza esa barra con cliente, estado, horario, distancia, ruta y acciones,
- la barra superior permite seguir usando `Ver ruta`, `Comenzar`, `Recalcular`, `Google` y `Entregado`,
- la leyenda y el panel de ubicacion ya no se ocultan por abrir una entrega.

Ajuste posterior de barra mobile:

- las celdas `Estado`, `Horario` y `Distancia` se redujeron en altura,
- debajo de esas celdas quedan dos botones principales: `Como llegar` e `Iniciar`,
- `Iniciar` puede calcular la ruta primero si todavia no se habia tocado `Como llegar`,
- en mobile se ocultan `Entregado` y `Google` dentro de esa barra para priorizar navegacion.

Ajuste de cierre de trayecto:

- cuando se entra en modo trayecto se oculta la card superior,
- se oculta `Recalcular`/`Como llegar` del flujo visible,
- aparece un boton flotante `Entregar`,
- `Entregar` abre el formulario de firma y cierre del pedido,
- al confirmar la entrega se limpia/cancela la ruta activa.

Regla posterior:

- una entrega con estado `done`/`Entregado` no permite iniciar navegacion,
- no muestra boton `Iniciar`,
- no abre el formulario de firma desde el flujo de trayecto,
- la barra indica `Entrega cerrada`.

## Corte actualizado - 2026-07-09

GeoDelix cerro el dia con una version de producto mucho mas completa y aprobada visualmente por el usuario. La app ya tiene admin con dashboard, mapa central, mapa de chofer instalable en Android, ubicacion viva de choferes y control de sesion unica por chofer.

### Entradas actuales

Admin:

```text
https://mobilex.fenixdev.uno/mapas/central/index.php
```

La primera pantalla del admin ahora es `Panel`:

```text
mapas/central/index.php?view=panel
```

Mapa central:

```text
https://mobilex.fenixdev.uno/mapas/central/mapa-central.html
```

Login/mapa de chofer:

```text
https://mobilex.fenixdev.uno/mapas/cliente/
```

### Estado aprobado del admin

- `index.php` acepta vistas `panel`, `entregas` y `choferes`.
- La vista por defecto es `panel`.
- El logo/nombre `GeoDelix` del header vuelve al Panel.
- Menu superior:
  - `Panel` con icono Font Awesome de grafico,
  - `Entregas`,
  - `Choferes`,
  - `Mapa chofer`,
  - `Mapa Central`.
- `Mapa chofer` y `Mapa Central` abren en pestana nueva con `target="_blank"` para no cerrar el panel.
- El Panel muestra:
  - entregas de hoy,
  - cumplimiento general,
  - entregas sin asignar,
  - choferes en vivo,
  - donut de estado general,
  - grafico de ultimos 7 dias,
  - carga por chofer,
  - calidad operativa.
- El Panel usa consultas SQL agregadas, no `SELECT *`, para evitar cargar pesado el admin.
- El conteo de `Choferes en vivo` usa `geodelix_list_driver_locations()`, la misma verdad que usa el mapa central.
- El Panel esta envuelto defensivamente: si fallan sus metricas, el admin sigue cargando y muestra aviso.
- En el form de entregas se quito el campo visible `Prioridad`; queda hidden para compatibilidad.
- Junto al campo `Ubicacion Google Maps` hay un boton con icono Font Awesome de mapa:
  - si el input esta vacio abre Google Maps,
  - si tiene coordenadas abre Google Maps buscando ese punto.
- Las altas/ediciones de entrega vuelven a `view=entregas` para no mandar al usuario al Panel luego de guardar.

### Estado aprobado del mapa central

Archivos:

```text
mapas/central/mapa-central.html
mapas/central/mapa-central.css
mapas/central/mapa-central.js
```

Comportamiento:

- muestra todas las entregas sin filtrar por chofer,
- muestra choferes en vivo con ubicacion reportada en los ultimos 2 minutos,
- refresca entregas cada 30 segundos,
- refresca choferes cada 3 segundos,
- la card `Estados` filtra el mapa:
  - click en `Pendiente` muestra pendientes,
  - click en `Entregado` muestra entregadas,
  - click en `Choferes` muestra solo choferes,
  - segundo click desactiva el filtro,
- la card `Choferes` permite filtrar por chofer:
  - click en un chofer filtra,
  - segundo click desactiva y vuelve a todos,
- la posicion de la card de choferes fue ajustada visualmente y quedo aprobada.

### Estado aprobado del mapa de chofer

Archivos:

```text
mapas/cliente/index.html
mapas/cliente/mapa-cliente.html
mapas/cliente/login-chofer.js
mapas/cliente/mapa-cliente.js
mapas/cliente/mapa-cliente.css
mapas/cliente/manifest.webmanifest
mapas/cliente/GeoDelix.png
mapas/cliente/GeoDelixW.jpg
mapas/cliente/GeoDelixS.jpg
```

Comportamiento:

- login por documento + clave,
- sesion local bajo `localStorage` con clave `geodelix_chofer`,
- la sesion ahora incluye `sesion_token`,
- no se permite el mismo chofer en dos dispositivos a la vez mientras su sesion esta activa,
- si un dispositivo queda con token viejo, el mapa lo saca al login,
- al loguearse, el chofer empieza a enviar ubicacion cada 3 segundos,
- al desloguearse:
  - se detiene el intervalo GPS,
  - se limpia ubicacion central,
  - se libera sesion/token,
- si no desloguea, el mapa central deja de mostrarlo cuando su ubicacion supera 2 minutos de antiguedad,
- el chofer solo ve entregas asignadas a su `chofer_id`,
- la card `Estados` tambien filtra:
  - `Pendiente`,
  - `Entregado`,
  - segundo click desactiva,
- el boton `Mi ubicacion` / `Centrar mapa` quedo ajustado visualmente,
- la card `Estados` quedo posicionada y aprobada.

### PWA / instalar en Android / compartir

La version chofer quedo preparada para `Agregar a pantalla principal`.

Metadatos en:

```text
mapas/cliente/index.html
mapas/cliente/mapa-cliente.html
mapas/cliente/manifest.webmanifest
```

Reglas actuales:

- titulo visible de la app: `GeoDelix`,
- `name` y `short_name` del manifest: `GeoDelix`,
- icono de instalacion/splash: `GeoDelixS.jpg`,
- fondo del splash: blanco (`#ffffff`),
- imagen para compartir por WhatsApp/Open Graph: `GeoDelixW.jpg`,
- logo interno visual de la app: `GeoDelix.png`.

El usuario confirmo que Android ofrecio instalar al toque y que el icono de pantalla principal quedo bien. Luego se cambio el icono del splash a `GeoDelixS.jpg` por bordes negros en la pantalla de arranque.

### Base de datos / schema nuevo

`geodelix_ensure_schema()` ahora agrega columnas en `geodelix_choferes` para ubicacion viva y sesion unica:

```text
ubicacion_latlong
ubicacion_latitud
ubicacion_longitud
ubicacion_precision
ubicacion_rumbo
ubicacion_actualizada
sesion_token
sesion_iniciada
sesion_actualizada
```

Reglas:

- `ubicacion_actualizada >= DATE_SUB(NOW(), INTERVAL 2 MINUTE)` define chofer en vivo.
- `sesion_token` evita login simultaneo del mismo chofer.
- la sesion activa se considera vigente por actividad reciente.
- logout limpia ubicacion y token.

### APIs actuales nuevas/importantes

Login chofer:

```text
POST /mapas/central/api/login-chofer.php
```

Devuelve `sesion_token` dentro de `chofer`.

Ubicacion chofer:

```text
GET  /mapas/central/api/ubicacion-chofer.php
POST /mapas/central/api/ubicacion-chofer.php
```

`GET` devuelve choferes activos con ubicacion viva para mapa central.

`POST` actualiza ubicacion del chofer. Payload usado por frontend:

```json
{
  "chofer_id": 1,
  "documento": "40808038",
  "sesion_token": "token",
  "latlong": "-33.8699962,-57.3680378",
  "latitud": -33.8699962,
  "longitud": -57.3680378,
  "precision": 20,
  "rumbo": null
}
```

Logout/desconexion:

```json
{
  "accion": "desconectar",
  "chofer_id": 1,
  "documento": "40808038",
  "sesion_token": "token"
}
```

### Proximo trabajo pedido por el usuario

Al retomar este proyecto, el siguiente bloque es integracion ERP + version embebible para ScriptCase Blank.

Tareas recomendadas en orden:

1. Revisar el endpoint actual de alta:

```text
POST /mapas/central/api/entregas.php
```

Hoy ya crea entregas, pero falta endurecerlo para ERP real.

2. Definir y aplicar seguridad para integracion ERP:
   - API key/token,
   - header recomendado: por ejemplo `X-Geodelix-Api-Key`,
   - rechazo de requests anonimos,
   - no exponer secretos en frontend.

3. Convertir alta en sincronizacion idempotente:
   - regla recomendada: `origen` + `origen_id`,
   - alternativa: `factura_numero` si el ERP garantiza unicidad,
   - si llega una entrega ya existente, actualizar campos operativos sin duplicar.

4. Definir respuesta ERP:

```json
{
  "ok": true,
  "id": 123,
  "created": true,
  "updated": false
}
```

5. Crear endpoint de consulta de estado para ERP:
   - por `origen` + `origen_id`,
   - o por `factura_numero`,
   - devolver `estado`, `fecha_entregado`, `recibido_por`, `firma_url`, `chofer_id`, `chofer_nombre`.

6. Crear version para cargar dentro de una Blank de ScriptCase del mapa central:
   - puede ser un HTML/PHP embebible liviano,
   - probablemente sin header/admin y sin navegacion superior,
   - pensado para iframe o include dentro de Blank,
   - reutilizar datos/API de `mapa-central.html`,
   - decidir si necesita auth/API key o si corre solo dentro del ERP.

7. Al documentar esa integracion, actualizar este mismo archivo.

### Validaciones usadas al final del dia

```bash
php -l mapas/central/index.php
php -l mapas/central/lib/bootstrap.php
php -l mapas/central/lib/drivers.php
php -l mapas/central/api/login-chofer.php
php -l mapas/central/api/ubicacion-chofer.php
node --check mapas/central/assets/central.js
node --check mapas/central/mapa-central.js
node --check mapas/cliente/login-chofer.js
node --check mapas/cliente/mapa-cliente.js
python -m json.tool mapas/cliente/manifest.webmanifest
```

Notas:

- El comando PHP por CLI puede mostrar problemas de conexion MySQL por sandbox/host local; no confundir eso con error de sintaxis.
- Para validar sintaxis usar `php -l`.
- El admin ya se rompio una vez por una version pesada del Panel usando `SELECT *`; evitar volver a calcular dashboard cargando todas las filas.

## Corte actualizado - 2026-07-08

GeoDelix quedo encaminado como aplicacion independiente casi lista para endurecer hacia produccion. El usuario aprobo visualmente el admin y el mapa de chofer como base de producto.

### Entrada actual

Admin:

```text
https://mobilex.fenixdev.uno/mapas/central/index.php
```

Login/mapa de chofer:

```text
https://mobilex.fenixdev.uno/mapas/cliente/
```

El archivo de entrada del chofer es:

```text
mapas/cliente/index.html
```

Si el chofer ya tiene sesion local, `index.html` redirige al mapa. Si entra directo al mapa sin sesion, `mapa-cliente.js` redirige al login.

### Flujo actual aprobado

Admin central:

- menu superior derecho con `Entregas`, `Choferes` y `Mapa chofer`,
- vista `Entregas` con metricas, tabla y acciones por fila,
- barra unica de filtros en entregas:
  - `Chofer: Todos`,
  - fecha desde,
  - fecha hasta,
  - tags `Pendientes`, `Entregadas`, `Todas`,
  - boton `+ Nuevo`,
- filtros combinables por URL (`estado`, `chofer_id`, `fecha_desde`, `fecha_hasta`),
- si se elige una sola fecha se filtra ese dia exacto,
- si se eligen dos fechas se filtra rango inclusivo usando `fecha_creado`,
- acciones por entrega:
  - ojo Font Awesome para ficha de solo lectura,
  - lapiz Font Awesome para editar,
- la ficha de solo lectura abre en side-in derecho y muestra todos los datos de la entrega,
- la firma en la ficha de lectura ocupa el ancho del panel,
- el visor ampliado de firma queda por encima del side-in,
- el ojo ya no dispara accidentalmente el visor de firma,
- el divisor inferior de la celda de acciones quedo alineado con el resto de la tabla,
- vista `Choferes` con tabla, alta y edicion en side-in derecho,
- formularios de alta/edicion tipo side-in desde la derecha.

Mapa de chofer:

- login separado en `mapas/cliente/index.html`,
- logo grande centrado y form limpio,
- login por documento + clave contra `mapas/central/api/login-chofer.php`,
- sesion local en `localStorage` bajo `geodelix_chofer`,
- mapa solo carga si hay chofer logueado,
- lectura de entregas filtrada por `chofer_id`,
- el chofer ve solo sus entregas asignadas,
- header del mapa con logo, 3 tarjetas en linea y tarjeta chica de salir con icono Font Awesome.

### Archivos actuales importantes

Admin:

```text
mapas/central/index.php
mapas/central/assets/central.css
mapas/central/assets/central.js
mapas/central/lib/bootstrap.php
mapas/central/lib/deliveries.php
mapas/central/lib/drivers.php
mapas/central/api/entregas.php
mapas/central/api/confirmar-entrega.php
mapas/central/api/login-chofer.php
```

Chofer:

```text
mapas/cliente/index.html
mapas/cliente/login-chofer.css
mapas/cliente/login-chofer.js
mapas/cliente/mapa-cliente.html
mapas/cliente/mapa-cliente.css
mapas/cliente/mapa-cliente.js
```

### Base de datos actual

Tablas principales:

```text
geodelix_entregas
geodelix_entrega_eventos
geodelix_choferes
```

`geodelix_choferes` se crea automaticamente si falta desde `geodelix_ensure_schema()`:

```text
id
nombre
documento
clave_hash
activo
fecha_creado
fecha_actualizado
```

Columnas nuevas en `geodelix_entregas`:

```text
chofer_id
chofer_nombre
```

Se mantiene compatibilidad con el dato historico:

```text
repartidor_nombre
```

Regla actual:

- `chofer_id` es la asignacion nueva,
- `chofer_nombre` guarda el nombre visible al momento de asignar,
- `repartidor_nombre` queda como compatibilidad para entregas antiguas y consumidores viejos.

### API actual

Lectura para mapa/consumidores:

```text
GET /mapas/central/api/entregas.php
```

Parametros vigentes:

```text
estado
chofer_id
```

`chofer_id` es usado por el mapa del chofer para traer solo sus entregas.

Alta por API:

```text
POST /mapas/central/api/entregas.php
```

Payload vigente recomendado:

```json
{
  "origen": "erp",
  "origen_id": "ERP-123",
  "factura_numero": "FAC-1062",
  "cliente_nombre": "Cliente",
  "cliente_telefono": "099123456",
  "cliente_documento": "12345678",
  "direccion_entrega": "Direccion visible",
  "referencia_entrega": "Referencia",
  "latlong": "-33.8699962, -57.3680378",
  "prioridad": 1,
  "horario_entrega": "Urgente",
  "chofer_id": 1
}
```

Confirmacion desde mapa:

```text
POST /mapas/central/api/confirmar-entrega.php
```

Login chofer:

```text
POST /mapas/central/api/login-chofer.php
```

Payload:

```json
{
  "documento": "40808038",
  "clave": "clave"
}
```

### Proximo paso recomendado

El siguiente bloque de trabajo deberia ser la integracion ERP -> GeoDelix.

Objetivo:

- crear/endurecer el API de consumo para que el ERP cree o sincronice entregas en GeoDelix,
- decidir regla de upsert por `origen` + `origen_id` o por `factura_numero`,
- evitar duplicados si el ERP reenvia la misma entrega,
- devolver el `id` interno de GeoDelix al ERP,
- definir endpoint de consulta de estado para que el ERP pueda sincronizar entregadas,
- agregar API key para que el ERP no publique entregas anonimamente.

Pendientes concretos para retomar:

1. Disenar contrato ERP -> GeoDelix:
   - campos obligatorios,
   - campos opcionales,
   - clave de idempotencia (`origen` + `origen_id` recomendado),
   - respuesta de exito/error.

2. Mejorar `POST /mapas/central/api/entregas.php`:
   - validar API key,
   - hacer upsert,
   - actualizar chofer si viene `chofer_id`,
   - registrar evento `creada_api` o `actualizada_api`.

3. Crear endpoint de estado para ERP:
   - buscar por `id`,
   - buscar por `origen` + `origen_id`,
   - devolver estado, firma_url, recibido_por, fecha_entregado y observaciones.

4. Seguridad:
   - login para central,
   - API key para ERP,
   - revisar exposicion publica de firmas.

> Nota: las secciones anteriores de este documento quedan como historial. Si contradicen este corte actualizado, tomar como fuente vigente esta seccion.

## Cambio de plan

GeoDelix dejo de ser solo una miniapp conectada directamente a ScriptCase. El nuevo rumbo es una aplicacion independiente con vida propia:

- `mapas/central/` es el backend/admin propio de GeoDelix.
- `mapas/cliente/` es la miniapp del repartidor.
- ScriptCase/ERP pasara a ser un integrador por API, no el centro del sistema.
- Las entregas se cargan y operan desde GeoDelix Central.
- La miniapp lee y confirma contra endpoints propios de GeoDelix.
- La confirmacion actual vuelve a ser con firma real, guardada como PNG.

La idea de confirmar por Documento/RUT queda pausada como opcion futura configurable.

## Ubicaciones

Miniapp cliente:

```text
/home/fenixdev/public_html/mobilex.fenixdev.uno/mapas/cliente/
```

Backend/admin propio:

```text
/home/fenixdev/public_html/mobilex.fenixdev.uno/mapas/central/
```

URLs actuales:

```text
https://mobilex.fenixdev.uno/mapas/central/index.php
https://mobilex.fenixdev.uno/mapas/cliente/mapa-cliente.html
```

## Archivos principales

Cliente repartidor:

```text
mapas/cliente/mapa-cliente.html
mapas/cliente/mapa-cliente.css
mapas/cliente/mapa-cliente.js
mapas/cliente/GeoDelix.png
mapas/cliente/Isotipo.png
```

Central:

```text
mapas/central/index.php
mapas/central/config.php
mapas/central/lib/bootstrap.php
mapas/central/lib/deliveries.php
mapas/central/api/entregas.php
mapas/central/api/confirmar-entrega.php
mapas/central/assets/central.css
mapas/central/assets/central.js
mapas/central/firmas/
```

Legado/referencia ScriptCase:

```text
mapas/cliente/endpoint-geodelix-entregas.php
mapas/cliente/endpoint-geodelix-confirma-entrega.php
```

Esos endpoints quedan como referencia historica para ScriptCase, pero el flujo activo ya usa GeoDelix Central.

## Estado logrado

GeoDelix Central ya funciona:

- dashboard con total, pendientes, entregadas y canceladas,
- alta manual de entregas,
- grilla administrativa,
- grilla responsive compacta en mobile,
- en mobile se muestran columnas minimas y un boton Ver,
- el boton Ver abre un bottom sheet con todo el detalle de la entrega,
- preview chica de firma en la grilla,
- click sobre firma para verla ampliada,
- refresco automatico cada 30 segundos,
- el refresco no corre si se esta escribiendo en el form,
- el refresco no corre si hay una firma ampliada abierta,
- endpoint JSON de lectura,
- endpoint JSON de confirmacion con firma,
- guardado de firma como PNG fisico,
- proteccion basica en `firmas/.htaccess` para no listar carpeta ni ejecutar PHP.

Miniapp repartidor ya funciona:

- mapa Leaflet con OpenStreetMap,
- lectura de entregas desde GeoDelix Central,
- refresco de entregas cada 30 segundos,
- ubicacion del repartidor cada 3 segundos,
- puntos pendientes amarillos,
- puntos entregados verdes,
- entrega pendiente mas cercana destacada en negro con halo,
- ficha desktop flotante,
- ficha mobile tipo bottom sheet,
- botones WhatsApp, llamada, Entregado e Iniciar trayecto,
- modal de confirmacion con nombre de quien recibe,
- canvas de firma,
- observaciones,
- POST real contra GeoDelix Central,
- cambio visual inmediato a entregado,
- refresco posterior desde backend.

## Configuracion activa del cliente

En `mapas/cliente/mapa-cliente.js`:

```js
const GEODELIX_CONFIG = {
    deliveriesEndpoint: "https://mobilex.fenixdev.uno/mapas/central/api/entregas.php",
    confirmDeliveryEndpoint: "https://mobilex.fenixdev.uno/mapas/central/api/confirmar-entrega.php",
    confirmDeliveryEnabled: true,
    deliveriesRefreshMs: 30000
};
```

Frecuencias:

```text
Entregas desde backend: 30000 ms
Ubicacion repartidor: 3000 ms
```

## Base de datos

La DB propia de GeoDelix esta configurada en:

```text
mapas/central/config.php
```

El archivo esta en formato texto simple y `mapas/central/lib/bootstrap.php` lo interpreta para crear la conexion PDO.

Tablas actuales:

```text
geodelix_entregas
geodelix_entrega_eventos
```

Campos relevantes de `geodelix_entregas`:

```text
id
origen
origen_id
factura_id
factura_numero
cliente_id
cliente_nombre
cliente_telefono
cliente_documento
direccion_entrega
referencia_entrega
latlong
latitud
longitud
estado
prioridad
horario_entrega
repartidor_id
repartidor_nombre
recibido_por
documento_receptor
observaciones_entrega
firma_archivo
firma_url
fecha_entregado
fecha_creado
fecha_actualizado
```

Estados:

```text
pendiente
entregado
cancelado
```

Decision actual:

- Se guarda `latlong` como texto pegado desde Google Maps.
- Al crear entrega, GeoDelix parsea `latlong` y guarda tambien `latitud`/`longitud`.
- La firma no se guarda como BLOB ni como base64 en DB.
- La firma se guarda como PNG en `mapas/central/firmas/`.
- La DB guarda `firma_archivo` y `firma_url`.

## Endpoint de lectura

URL:

```text
https://mobilex.fenixdev.uno/mapas/central/api/entregas.php
```

Metodo:

```text
GET
```

Respuesta:

```json
{
  "ok": true,
  "total": 1,
  "entregas": [
    {
      "id": 5,
      "factura_numero": "FAC-1062",
      "cliente_nombre": "Barraca Martinez Elizondo",
      "cliente_telefono": "099456123",
      "cliente_documento_pista": "4567****",
      "direccion_entrega": "Barraca Martinez Elizondo",
      "latlong": "-33.8699962, -57.3680378",
      "latitud": -33.8699962,
      "longitud": -57.3680378,
      "estado": "Pendiente",
      "horario_entrega": "Urgente",
      "prioridad": 1,
      "firma_url": null,
      "frontend": {
        "id": "5",
        "customer": "FAC-1062",
        "address": "Barraca Martinez Elizondo",
        "phone": "099456123",
        "coordinates": [-33.8699962, -57.3680378],
        "status": "pending",
        "window": "Urgente",
        "documentHint": "4567****"
      }
    }
  ]
}
```

El cliente usa preferentemente `entregas[].frontend`. Los campos planos quedan disponibles para integraciones.

Tambien acepta alta por API:

```text
POST /mapas/central/api/entregas.php
```

Payload base:

```json
{
  "origen": "api",
  "origen_id": "ERP-123",
  "factura_numero": "FAC-1062",
  "cliente_nombre": "Cliente",
  "cliente_telefono": "099123456",
  "cliente_documento": "12345678",
  "direccion_entrega": "Direccion visible",
  "referencia_entrega": "Referencia",
  "latlong": "-33.8699962, -57.3680378",
  "prioridad": 1,
  "horario_entrega": "Urgente",
  "repartidor_nombre": "Opcional"
}
```

## Endpoint de confirmacion

URL:

```text
https://mobilex.fenixdev.uno/mapas/central/api/confirmar-entrega.php
```

Metodo:

```text
POST
```

Payload:

```json
{
  "id": 5,
  "recibido_por": "Juan Perez",
  "observaciones_entrega": "Recibido en mostrador",
  "firma_base64": "data:image/png;base64,..."
}
```

Comportamiento:

- valida `id`,
- valida nombre de quien recibe,
- valida firma PNG base64,
- decodifica la firma,
- guarda PNG en `mapas/central/firmas/`,
- actualiza `estado = 'entregado'`,
- guarda `recibido_por`,
- guarda `observaciones_entrega`,
- guarda `firma_archivo`,
- guarda `firma_url`,
- guarda `fecha_entregado`,
- registra evento en `geodelix_entrega_eventos`.

Respuesta esperada:

```json
{
  "ok": true,
  "id": 5,
  "estado": "Entregado",
  "firma_url": "https://mobilex.fenixdev.uno/mapas/central/firmas/firma_entrega_5_20260708_164719.png",
  "message": "Entrega confirmada correctamente."
}
```

## Firma y bug mobile corregido

El modal de entrega usa canvas.

Problema encontrado:

- En mobile, despues de firmar, al tocar Observaciones se abria el teclado.
- El teclado disparaba `visualViewport.resize`.
- Ese resize llamaba a `resizeSignaturePad()`.
- Redimensionar el canvas borraba la firma.

Solucion aplicada:

- `resizeSignaturePad(true)` solo se usa al abrir el modal para arrancar limpio.
- Si `hasSignature` ya esta activo, un resize posterior no redimensiona ni reinicia el canvas.
- La firma ya no se borra al tocar Observaciones.

Funciones relevantes:

```text
setupSignatureContext()
resizeSignaturePad(reset = false)
clearSignaturePad()
confirmSelectedDelivery()
```

## Admin auto-refresh

Archivo:

```text
mapas/central/assets/central.js
```

Comportamiento:

- `autoRefreshMs = 30000`,
- recarga la pagina cada 30 segundos,
- no recarga si la pestana esta oculta,
- no recarga si el formulario fue tocado,
- no recarga si el foco esta dentro del formulario,
- no recarga si la firma ampliada esta abierta.

Esto mantiene la grilla viva sin interrumpir cargas manuales ni inspeccion de firmas.

## Entrega mas cercana

El cliente:

1. obtiene posicion GPS del repartidor,
2. recorre entregas no entregadas,
3. calcula distancia con Haversine,
4. marca la pendiente mas cercana,
5. la muestra en negro con halo pulsante.

El backend no calcula cercania porque depende de la ubicacion actual del repartidor.

## Documento/RUT

La idea de confirmar por Documento/RUT se converso y se preparo parcialmente en concepto, pero no es el flujo activo.

Decision actual:

- El flujo activo es firma real.
- `cliente_documento` queda en la tabla para uso futuro.
- `documento_receptor` queda en la tabla para posible auditoria futura.
- Si se retoma Documento/RUT, la validacion debe hacerse en backend.
- No se debe confiar en el documento completo expuesto al frontend.
- Como pista visual se puede devolver solo algo enmascarado tipo `4567****`.

Payload futuro posible:

```json
{
  "id": 5,
  "documento_receptor": "12345678",
  "observaciones_entrega": "Recibido en mostrador"
}
```

## ScriptCase / ERP

El flujo activo ya no depende de ScriptCase.

Objetivo futuro:

- ScriptCase envia entregas a GeoDelix por API.
- GeoDelix administra, muestra, entrega y guarda firma.
- ScriptCase consulta o recibe el estado final para sincronizar el ERP.

Endpoints de referencia ScriptCase anteriores:

```text
mapas/cliente/endpoint-geodelix-entregas.php
mapas/cliente/endpoint-geodelix-confirma-entrega.php
```

No usar `php -l` sobre esos archivos porque contienen macros de ScriptCase.

## Seguridad pendiente

Todavia falta implementar seguridad.

Pendientes recomendados:

- login para `mapas/central/index.php`,
- API key/token para endpoints,
- control de origen/integrador,
- control de repartidor,
- evitar confirmaciones anonimas desde cualquier origen,
- decidir si las firmas publicas por URL necesitan proteccion adicional.

## Validaciones usadas

JS cliente:

```bash
node --check mapas/cliente/mapa-cliente.js
```

JS central:

```bash
node --check mapas/central/assets/central.js
```

PHP central:

```bash
php -l mapas/central/lib/bootstrap.php
php -l mapas/central/lib/deliveries.php
php -l mapas/central/api/entregas.php
php -l mapas/central/api/confirmar-entrega.php
php -l mapas/central/index.php
```

API lectura probada:

```text
GET /mapas/central/api/entregas.php
```

Resultado esperado:

```json
{"ok":true,"total":0,"entregas":[]}
```

El usuario probo el flujo real y confirmo:

- central visual correcta,
- alta y grilla funcionando,
- miniapp leyendo entregas,
- firma guardada,
- firma preview chica en grilla,
- click para ampliar firma funcionando,
- correccion mobile de firma funcionando.

## Donde estamos parados

GeoDelix ya es una aplicacion independiente funcional en primera version.

Ya se logro:

- central operativa,
- DB propia,
- endpoints propios,
- miniapp conectada a central,
- confirmacion con firma real,
- guardado de firma como PNG,
- preview de firma en admin,
- auto-refresh de grilla,
- bug mobile del canvas corregido.

Ultimo ajuste realizado:

- la central quedo responsive,
- se descarto la vista mobile como cards largas porque iba a crecer demasiado hacia abajo,
- en mobile la grilla queda compacta con columnas minimas,
- se agrego boton `Ver`,
- `Ver` abre un bottom sheet estilo Glide con el detalle completo,
- desde ese detalle se puede ver/ampliar la firma si existe.

El estado actual fue probado visualmente por el usuario y quedo aprobado como base para seguir puliendo ideas mas adelante.

## Proximos pasos recomendados

1. Seguridad basica:
   - login simple para la central,
   - API key para endpoints.

2. Mejoras operativas de central:
   - filtros por estado,
   - busqueda por factura/cliente,
   - boton editar entrega,
   - boton cancelar entrega,
   - vista detalle de entrega.

3. Integracion con ScriptCase:
   - endpoint para que ERP cree/sincronice entregas,
   - endpoint para consultar estado por `origen` + `origen_id` o `factura_numero`,
   - definir si ScriptCase tira datos a GeoDelix o si GeoDelix consulta al ERP.

4. Producto:
   - usuarios/repartidores,
   - roles,
   - asignacion de entregas,
   - historial/eventos visible,
   - posible central con mapa de monitoreo.

## Corte actualizado - 2026-07-09 - UX navegacion Mapbox chofer

En `mapas-box/cliente/` quedo validado el flujo completo de ruta y entrega:

- tocar una entrega pendiente muestra la barra superior con estado, horario, distancia y ruta sugerida;
- los botones grandes `Como llegar` e `Iniciar` viven en el dock flotante inferior;
- `Como llegar` calcula y dibuja la ruta con Mapbox Directions;
- `Iniciar` oculta la barra superior, inclina/centra el mapa y cambia el dock inferior al boton unico `Entregar`;
- `Entregar` abre el formulario real de firma y confirmacion;
- al confirmar, se actualiza backend, se cancela la ruta activa, el punto pasa a entregado y ya no permite navegar ni entregar de nuevo;
- una entrega cerrada muestra `Entrega cerrada.` en la barra superior y no habilita acciones inferiores.
- la card inferior de `Estados` se retiro para liberar mapa;
- las cards superiores `Entregas`, `Pendientes` y `Hechas` ahora filtran el mapa;
- el filtro activo se marca con color suave en la card superior y deja un chip compacto inferior derecho para volver a `Todos`.
- al iniciar trayecto aparece una card limpia de navegacion con distancia y minutos restantes;
- esa card se actualiza cada vez que Mapbox recalcula la ruta y se oculta al cancelar/cerrar la entrega.

Archivos principales:

```text
mapas-box/cliente/mapa-cliente.html
mapas-box/cliente/mapa-cliente.js
mapas-box/cliente/mapa-cliente.css
```

Validacion:

```text
node --check mapas-box/cliente/mapa-cliente.js
```
