+
+
+
+
diff --git a/app/views/operacoes_dashboard/index.html.erb b/app/views/operacoes_dashboard/index.html.erb
index a0fa2bb..3612f7c 100644
--- a/app/views/operacoes_dashboard/index.html.erb
+++ b/app/views/operacoes_dashboard/index.html.erb
@@ -24,6 +24,8 @@
.flatpickr-months .flatpickr-prev-month svg, .flatpickr-months .flatpickr-next-month svg { fill: #f97316; }
/* O mapa do Leaflet usa fundo claro — moldura escura ao redor */
.leaflet-container { background: #1a1a1a; }
+ /* Realça ruas e nomes no tile escuro (CARTO dark_all tem baixo contraste) */
+ .tiles-escuro-contraste { filter: brightness(1.45) contrast(1.2) saturate(0.9); }
<% end %>
@@ -356,6 +358,7 @@
linha('📍', p.endereco) +
linha('🏥', p.unidade) +
linha('🚚', p.motorista) +
+ linha('🚗', p.veiculo) +
linha('🕒', p.checkout) +
foto +
'
';
@@ -389,7 +392,8 @@
// Camadas base (todas grátis, sem chave): escuro (padrão, combina com o
// tema), claro e satélite.
const escuro = L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', {
- attribution: '© OpenStreetMap © CARTO', subdomains: 'abcd', maxZoom: 20
+ attribution: '© OpenStreetMap © CARTO', subdomains: 'abcd', maxZoom: 20,
+ className: 'tiles-escuro-contraste'
});
const claro = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap', maxZoom: 19
@@ -412,21 +416,26 @@
// O popup é uma FUNÇÃO, então o HTML da foto só é montado/baixado quando
// o balão é clicado — nada de imagem é requisitado ao carregar o mapa.
let marcadores = null;
+ let entradas = []; // [{ marker, p }] — para a busca filtrar sem recriar
+ const resultadosBusca = L.layerGroup();
function construirMarcadores() {
if (marcadores) return marcadores;
marcadores = L.layerGroup();
pontos.forEach(function (p) {
- L.marker([p.lat, p.lng], { icon: ICONE })
- .bindPopup(function () { return popupHtml(p); }, { maxWidth: 260 })
- .addTo(marcadores);
+ const marker = L.marker([p.lat, p.lng], { icon: ICONE })
+ .bindPopup(function () { return popupHtml(p); }, { maxWidth: 260 });
+ marker.addTo(marcadores);
+ entradas.push({ marker: marker, p: p });
});
return marcadores;
}
// Começa no Calor (cai para Pontos se não houver calor)
+ let vistaAtual = heatLayer ? 'heat' : 'pontos';
(heatLayer || construirMarcadores()).addTo(mapa);
function mostrar(view) {
+ vistaAtual = view;
if (heatLayer) mapa.removeLayer(heatLayer);
if (marcadores) mapa.removeLayer(marcadores);
if (view === 'pontos') { construirMarcadores().addTo(mapa); }
@@ -441,9 +450,62 @@
}
box.querySelectorAll('.map-toggle button').forEach(function (b) {
- b.addEventListener('click', function () { mostrar(b.dataset.view); });
+ b.addEventListener('click', function () {
+ const inputBusca = box.querySelector('.mapa-busca');
+ if (inputBusca && inputBusca.value) { inputBusca.value = ''; }
+ limparBusca();
+ mostrar(b.dataset.view);
+ });
});
+ // ── Busca por NF / paciente / veículo ──
+ const inputBusca = box.querySelector('.mapa-busca');
+ const infoBusca = box.querySelector('.mapa-busca-info');
+
+ function limparBusca() {
+ mapa.removeLayer(resultadosBusca);
+ resultadosBusca.clearLayers();
+ if (infoBusca) infoBusca.textContent = '';
+ }
+
+ function aplicarBusca(termo) {
+ const q = String(termo || '').trim().toLowerCase();
+ if (!q) {
+ limparBusca();
+ mostrar(vistaAtual); // restaura a visão padrão (Calor ou Pontos)
+ return;
+ }
+ construirMarcadores();
+ if (heatLayer) mapa.removeLayer(heatLayer);
+ if (marcadores) mapa.removeLayer(marcadores);
+ resultadosBusca.clearLayers();
+
+ const casa = function (v) { return String(v == null ? '' : v).toLowerCase().indexOf(q) !== -1; };
+ const achados = entradas.filter(function (e) {
+ return casa(e.p.nf) || casa(e.p.nome) || casa(e.p.veiculo);
+ });
+ achados.forEach(function (e) { e.marker.addTo(resultadosBusca); });
+ resultadosBusca.addTo(mapa);
+
+ if (achados.length) {
+ const grupo = L.featureGroup(achados.map(function (e) { return e.marker; }));
+ mapa.fitBounds(grupo.getBounds(), { padding: [40, 40], maxZoom: 16 });
+ if (achados.length === 1) { achados[0].marker.openPopup(); }
+ if (infoBusca) infoBusca.textContent = achados.length + (achados.length === 1 ? ' resultado' : ' resultados');
+ } else {
+ if (infoBusca) infoBusca.textContent = 'Nenhum resultado';
+ }
+ }
+
+ if (inputBusca) {
+ let debounce = null;
+ inputBusca.addEventListener('input', function () {
+ clearTimeout(debounce);
+ const valor = inputBusca.value;
+ debounce = setTimeout(function () { aplicarBusca(valor); }, 200);
+ });
+ }
+
// Tela cheia (Fullscreen API sobre o container do mapa)
const btnFs = box.querySelector('.map-fullscreen');
if (btnFs) {