<%# app/views/operacoes_dashboard/index.html.erb %> <%# Dashboard de análise de entregas por operação (KPIs, insucessos, STS, mapa). %> <% content_for :head do %> <%# Flatpickr (date range) — CSS no %> <%# Leaflet (mapa de calor) %> <% end %> <% hoje = Date.current %> <% atalhos = { 'Hoje' => [hoje, hoje], '7 dias' => [hoje - 6, hoje], 'Este mês' => [hoje.beginning_of_month, hoje], '30 dias' => [hoje - 29, hoje] } %> <% ini_iso = @periodo_inicio.strftime('%Y-%m-%d') %> <% fim_iso = @periodo_fim.strftime('%Y-%m-%d') %> <%# Parâmetros de operação a preservar ao trocar de modo/período %> <% ctx_ops = { operacao: @operacao, op_a: @op_a, op_b: @op_b }.compact %> <%# Atualiza os dados sozinho a cada 5 min (data-auto-refresh-interval-value em ms), sem o operador apertar F5. Ver auto_refresh_controller.js. %>
<%# ── Cabeçalho ─────────────────────────────────────────── %>

Dashboard de Operações

<% if @modo == 'global' %> <%= icone :global %> Global · <%= @periodo_inicio.strftime('%d/%m/%Y') %> – <%= @periodo_fim.strftime('%d/%m/%Y') %> <% elsif @modo == 'comparar' %> <%= icone :comparar %> Comparação entre operações (cada uma no seu próprio período) <% elsif @metricas&.data_inicio %> <%= @metricas.operacoes_label %> · <%= @metricas.data_inicio.strftime('%d/%m/%Y') %> – <%= @metricas.data_fim.strftime('%d/%m/%Y') %> <%= @periodo_explicito ? '(período filtrado)' : '(operação inteira)' %> <% elsif @operacao %> <%= Operacao.label(@operacao) %> <% end %> · Atualizado <%= ultima_atualizacao_label %>

<%# Filtro de período — Global e Operação. No modo Operação ele só entra em vigor quando o operador ESCOLHE uma faixa (params inicio/fim): sem isso o recorte é a operação inteira, senão abrir uma operação de meses atrás cairia no mês corrente e mostraria zero. %> <% if %w[global operacao].include?(@modo) %>
<%= icone :calendario, espaco: false %>
<% atalhos.each do |label, (ini, fim)| %> <%# No Global a faixa SEMPRE vale (é o que define a visão); no modo Operação só quando escolhida — senão o atalho apareceria aceso sem estar sendo aplicado. %> <% ativo = (@periodo_explicito || @modo == 'global') && @periodo_inicio == ini && @periodo_fim == fim %> <%= link_to label, operacoes_dashboard_path(ctx_ops.merge(modo: @modo, inicio: ini.strftime('%Y-%m-%d'), fim: fim.strftime('%Y-%m-%d'))), data: { turbo: false }, class: "px-3 py-2.5 rounded-xl text-sm whitespace-nowrap border #{ativo ? 'bg-orange-500 text-black border-orange-500 font-bold' : 'bg-[#1a1a1a] text-gray-300 border-white/10 hover:border-orange-500'}" %> <% end %> <%# Volta ao recorte natural da operação (sem faixa de datas na URL). %> <% if @modo == 'operacao' %> <%= link_to 'Operação inteira', operacoes_dashboard_path(ctx_ops.merge(modo: 'operacao')), data: { turbo: false }, class: "px-3 py-2.5 rounded-xl text-sm whitespace-nowrap border #{@periodo_explicito ? 'bg-[#1a1a1a] text-gray-300 border-white/10 hover:border-orange-500' : 'bg-orange-500 text-black border-orange-500 font-bold'}" %> <% end %>
<% end %>
<%# ── Abas de modo + atalho para a planilha ─────────────── %> <% modos = { 'operacao' => [:operacao, 'Operação'], 'global' => [:global, 'Global'], 'comparar' => [:comparar, 'Comparar'] } %> <%# A faixa de datas só viaja entre as abas se o operador tiver ESCOLHIDO uma. Carregar o default (mês corrente) ao entrar em "Operação" faria uma operação de meses atrás abrir zerada. %> <% ctx_periodo = @periodo_explicito ? { inicio: ini_iso, fim: fim_iso } : {} %>
<% modos.each do |m, (ic, label)| %> <% ativo = @modo == m %> <%= link_to rotulo(ic, label, cor: (ativo ? nil : 'text-brand-laranja')), operacoes_dashboard_path(ctx_ops.merge(ctx_periodo).merge(modo: m)), data: { turbo: false }, class: "px-4 py-2 rounded-xl text-sm font-semibold whitespace-nowrap #{ativo ? 'bg-orange-500 text-black' : 'bg-[#1a1a1a] text-gray-300 border border-white/10 hover:border-orange-500'}" %> <% end %>
<%# Planilha da operação (tabela espelho) — leva o contexto atual junto %> <% planilha_ctx = request.query_parameters .slice('f_driver', 'f_sts', 'f_status', 'f_obs', 'f_resultado', 'f_data') .merge(modo: (@modo == 'global' ? 'global' : 'operacao'), inicio: ini_iso, fim: fim_iso) %> <% planilha_ctx[:operacao] = @operacao if @operacao %> <%= link_to rotulo(:planilha, 'Planilha da operação', cor: nil), operacoes_planilha_path(planilha_ctx), data: { turbo: false }, class: 'px-4 py-2 rounded-xl text-sm font-semibold whitespace-nowrap bg-[#1a1a1a] text-orange-400 border border-orange-500/40 hover:bg-orange-500 hover:text-black' %>
<% if @tabelas_validas.blank? %>
Nenhuma operação encontrada no banco (tabelas gade_entregas_*).
<% else %> <%# ── Filtros ativos (cross-filter por clique nas tabelas) ── %> <% if @chips.any? && %w[operacao global].include?(@modo) %>
Filtros ativos: <% @chips.each do |chip| %> <%= chip[:rotulo] %>: <%= chip[:display] || chip[:valor] %> <%= link_to icone(:fechar, cor: nil, tamanho: 'w-3.5 h-3.5'), operacoes_dashboard_path(request.query_parameters.except(chip[:param])), data: { turbo: false }, class: 'hover:text-white font-bold', title: 'Remover filtro' %> <% end %> <%= link_to 'Limpar tudo', operacoes_dashboard_path(request.query_parameters.except(*@chips.map { |c| c[:param] })), data: { turbo: false }, class: 'text-xs text-gray-400 hover:text-orange-400 underline' %>
<% end %> <%# ── Seletor de operação por modo ───────────────────── %> <% if @modo == 'operacao' %>
<% if @metricas %> <%= render 'painel', metricas: @metricas, filtravel: true %> <%= render 'mapa', metricas: @metricas %> <% end %> <% if @fora_operacao %> <%= render 'fora_operacao', fora: @fora_operacao, inicio: @periodo_inicio, fim: @periodo_fim %> <% end %> <% elsif @modo == 'global' %>
<%= icone :global %> Visão Global — todas as <%= @tabelas_validas.size %> operações agregadas no período.
<% if @metricas %> <%= render 'painel', metricas: @metricas, filtravel: true %> <%= render 'mapa', metricas: @metricas %> <% end %> <% if @fora_operacao %> <%= render 'fora_operacao', fora: @fora_operacao, inicio: @periodo_inicio, fim: @periodo_fim %> <% end %> <% else # comparar %>
<%# Comparativo direto A x B (tabela + barras agrupadas) %> <% if @metricas_a && @metricas_b %> <%= render 'comparativo', a: @metricas_a, b: @metricas_b, label_a: @metricas_a.operacoes_label, label_b: @metricas_b.operacoes_label %> <% end %> <%# Detalhe completo de cada operação (recolhível) %>
<%= icone :buscar %> Ver detalhe completo de cada operação
<% if @metricas_a %> <%= render 'painel', metricas: @metricas_a, titulo: "A · #{@metricas_a.operacoes_label}" %> <% else %>

Selecione a operação A.

<% end %>
<% if @metricas_b %> <%= render 'painel', metricas: @metricas_b, titulo: "B · #{@metricas_b.operacoes_label}" %> <% else %>

Selecione a operação B.

<% end %>
<% end %> <% end %>
<%# ── Scripts: flatpickr, Chart.js, Leaflet ───────────────── %>