# Onda 1 — UX Foundation — Spec

## Contexto e problema

A primeira leva do `dashboard-operacional` foi mergeada em `dev_team` com **8 dúvidas em aberto** registradas em `PRD/dashboard-operacional/01-spec.md` e com débito visual perceptível em relação ao protótipo React documentado em `componentes/Missoes/Logistica/sinais/Dashboard/frontend-documentacao.md`. Sem fechar essa fundação, as ondas 2-5 reabrem decisões transversais (chart lib, datepicker, persistência de estado, cache, definição de "erro") e empilham abstrações sobre variáveis indefinidas. Esta onda **decide e registra** cada um desses pontos e entrega paridade visual e de loading-states com o protótipo.

## Escopo

- ✅ Faz parte:
  - Decisão registrada (com justificativa) para cada uma das 8 dúvidas em aberto do PRD anterior.
  - Implementação do mecanismo escolhido para persistência de período + aba selecionada.
  - Adoção de **uma única** chart lib em todos os 6 KPIs (sparklines) e séries do dashboard.
  - Adoção de **um único** componente de seleção de intervalo de datas (date range picker).
  - Cache server-side de séries diárias com chave `(customer, range, tipo)` e TTL definido entre 5 e 15 min.
  - Auditoria documental dos 12 handlers `/api/v1/dashboard/*` (mantém / migra / remove) — pode ser executada nesta onda ou diferida para a onda 2; a **decisão sobre quando executar** é entregável desta onda.
  - Validação documental do mapeamento Sondas ↔ tabelas reais em `dev_gx_goldie` para `RotaSeparacao`, `ParticipacaoSeparacao`, `Carregamento`, `ErrosMotorista`, `Pessoa`.
  - Decisão sobre destino do arquivo `frontend-documentacao.md` (commitar in-place / mover para PRD / remover ao final da onda 5).
  - Definição operacional de "carga com erro" para o KPI de assertividade do conferente, validada com coordenador de expedição.
  - Aplicação consistente das cores semafóricas em todos os pontos definidos no PRD anterior (assertividade ≥95/≥88; score ≥70/≥45; eficiência de fluxo ≥95/≥85; overnight 0 / 1-3 / ≥4).
  - Skeleton/loading visível em **todos** os blocos (KPIs, séries, rankings) durante re-fetch ao trocar período/aba.
  - Badges de score e assertividade nos rankings.
- ❌ Fora de escopo:
  - Drilldown em pessoa, filtros adicionais (filial/CD, turno, tipo de rota), exportação, comparativo, metas, alertas, histórico — pertencem às ondas 3-5.
  - Modularização do `dashboard.js` (44KB) — pertence à onda 2.
  - Qualquer alteração de schema do banco.
  - Abrir `/api/v1` publicamente; alterar autenticação ou autorização.
  - Introdução de React/Vite/Tailwind/shadcn/Recharts no repo.
  - Mudança da rota `/missao/logistica/dashboard` ou criação de sinal novo.
  - Pixel-perfect com o protótipo React (a meta é paridade de hierarquia, cor semafórica e regra de agregação).

## User stories

### US1 — Persistência do período e aba via link compartilhável
**Como** gestor logístico **eu quero** que a aba ativa e o período selecionado fiquem preservados no link **para** poder compartilhar uma visão exata com colegas e voltar à mesma view depois de um reload.

**Critérios de aceite:**
- AC1.1: Decisão entre querystring e `sessionStorage` (ou combinação) está registrada no `02-techplan.md` com justificativa.
- AC1.2: Ao trocar de aba (Visão Geral / Separação / Carregamento), o estado da aba é refletido na URL (ou no mecanismo escolhido) sem reload da página.
- AC1.3: Ao trocar o período, o estado do período é refletido no mecanismo escolhido sem reload.
- AC1.4: Abrir a URL gerada em outra sessão/aba reproduz exatamente a mesma aba e período (quando o mecanismo for compartilhável por link).
- AC1.5: Reload (F5) na página preserva aba e período.
- AC1.6: Estado inválido (ex.: range fora dos limites permitidos) cai em default documentado, sem quebrar a tela.

### US2 — Chart lib unificada para sparklines e séries
**Como** time de devs Genesis **eu quero** uma única biblioteca de gráficos adotada no dashboard **para** evitar bundles duplicados e divergências visuais entre KPIs.

**Critérios de aceite:**
- AC2.1: Auditoria das libs de gráfico já presentes no Genesis está registrada no `02-techplan.md`.
- AC2.2: Decisão final (lib escolhida + versão) está registrada com justificativa.
- AC2.3: Os 6 KPIs renderizam sparklines com a lib escolhida.
- AC2.4: Nenhuma outra lib de gráfico é introduzida nem permanece importada por código deste sinal.
- AC2.5: A lib é carregada uma única vez por página (sem duplicação).

### US3 — Date range picker unificado
**Como** gestor logístico **eu quero** um seletor de intervalo de datas consistente **para** filtrar o dashboard sem fricção.

**Critérios de aceite:**
- AC3.1: Auditoria dos pickers já presentes no Genesis está registrada no `02-techplan.md`.
- AC3.2: Decisão final (componente + versão) está registrada com justificativa.
- AC3.3: O seletor permite escolher início e fim do intervalo em uma única interação coesa.
- AC3.4: O seletor respeita o locale do usuário (pt-br / en / es) sem string hardcoded.
- AC3.5: Não há outro componente de date range picker convivendo nesta tela.

### US4 — Cache curto de séries diárias
**Como** time de devs Genesis **eu quero** cache server-side de séries diárias **para** reduzir latência percebida em re-fetches frequentes.

**Critérios de aceite:**
- AC4.1: Decisão sobre backend de cache (apcu / memcached / redis / outro) está registrada no `02-techplan.md` com justificativa baseada no que o Genesis já usa.
- AC4.2: TTL final escolhido entre 5 e 15 minutos está registrado.
- AC4.3: Chave de cache é `(customer, range, tipo)` (ou superconjunto justificado).
- AC4.4: p95 dos handlers de série diária com cache quente é < 200ms para período de 30 dias em `dev_gx_goldie`.
- AC4.5: Re-fetch após expiração do TTL retorna dados atualizados (cache invalidation observável em teste de integração).
- AC4.6: Cache é tenant-safe — nenhum cliente vê dado cacheado de outro `customer`.

### US5 — Auditoria dos handlers `/api/v1/dashboard/*`
**Como** time de devs Genesis **eu quero** saber quais dos 12 handlers permanecem, migram ou são removidos **para** não carregar dívida nas ondas seguintes.

**Critérios de aceite:**
- AC5.1: Lista dos 12 handlers com classificação `mantém | migra | remove` está registrada no `02-techplan.md`.
- AC5.2: Para cada handler classificado como `migra` ou `remove`, há justificativa textual.
- AC5.3: A decisão sobre **executar** a poda nesta onda ou diferir para a onda 2 está registrada explicitamente.
- AC5.4: Se a poda for executada nesta onda, nenhum consumidor (view/JS) fica apontando para handler removido.

### US6 — Mapeamento Sondas ↔ tabelas reais validado
**Como** time de devs Genesis **eu quero** confirmação de que as Sondas atuais batem com as colunas/relacionamentos reais em `dev_gx_goldie` **para** confiar nos números mostrados.

**Critérios de aceite:**
- AC6.1: Mapeamento de `RotaSeparacao`, `ParticipacaoSeparacao`, `Carregamento`, `ErrosMotorista` e `Pessoa` está documentado no `02-techplan.md` com nome de colunas e FKs reais.
- AC6.2: Qualquer divergência encontrada entre Sonda e tabela real está listada com proposta de correção (mesmo que a correção fique pra outra onda).
- AC6.3: A validação foi executada efetivamente em `dev_gx_goldie` (não só inferida do código).

### US7 — Destino do `frontend-documentacao.md` decidido
**Como** PO/TL **eu quero** uma decisão registrada sobre o destino desse arquivo untracked **para** não conviver indefinidamente com referência fora do controle de versão.

**Critérios de aceite:**
- AC7.1: Uma das três opções está registrada no `02-techplan.md`: (a) commitar in-place, (b) mover para `PRD/dashboard-operacional-refinamento/`, (c) remover ao final da onda 5.
- AC7.2: Se a decisão for (a) ou (b), a movimentação/commit é executada nesta onda.
- AC7.3: Se a decisão for (c), uma anotação explícita registra que a remoção será feita ao final da onda 5.

### US8 — Definição de "carga com erro" para assertividade do conferente
**Como** coordenador de expedição **eu quero** que o KPI de assertividade do conferente reflita uma definição validada de "carga com erro" **para** confiar nos rankings e decisões de treinamento.

**Critérios de aceite:**
- AC8.1: Decisão registrada no `02-techplan.md`: "qualquer entrada em `errosMotorista[]` conta" **ou** "apenas tipos específicos contam" (com a lista dos tipos e a lista do que é excluído, ex.: `avaria_transporte`).
- AC8.2: A decisão foi validada com coordenador de expedição (registrar quem validou ou marcar como pendência se ainda não foi possível).
- AC8.3: O cálculo do KPI no código reflete a definição decidida.
- AC8.4: A mudança de definição (vs versão anterior, se houver mudança nos números) é comunicada antes do release — registrar canal/forma da comunicação no techplan.

### US9 — Paridade visual com o protótipo React
**Como** gestor logístico **eu quero** ver as mesmas cores semafóricas, badges e sparklines do protótipo **para** ter leitura rápida e consistente do estado operacional.

**Critérios de aceite:**
- AC9.1: Cores semafóricas para assertividade aplicadas conforme limites: verde ≥95, amarelo ≥88 e <95, vermelho <88.
- AC9.2: Cores semafóricas para score: verde ≥70, amarelo ≥45 e <70, vermelho <45.
- AC9.3: Cores semafóricas para eficiência de fluxo: verde ≥95, amarelo ≥85 e <95, vermelho <85.
- AC9.4: Cores semafóricas para overnight: verde 0, amarelo 1-3, vermelho ≥4.
- AC9.5: Sparkline presente em cada um dos 6 KPIs.
- AC9.6: Badges de score e de assertividade presentes nas linhas de ranking.
- AC9.7: Comparação lado-a-lado com o protótipo (screenshots no review) mostra mesma hierarquia de informação e mesmas cores semafóricas.

### US10 — Skeleton/loading consistente em re-fetch
**Como** gestor logístico **eu quero** ver indicadores de carregamento em todos os blocos quando trocar período ou aba **para** entender que os números estão sendo atualizados e não confiar em valor obsoleto.

**Critérios de aceite:**
- AC10.1: Ao trocar de período, todos os blocos afetados (KPIs, séries, rankings) exibem skeleton/loading.
- AC10.2: Ao trocar de aba, os blocos da aba destino exibem skeleton/loading até o primeiro render com dados.
- AC10.3: O skeleton aparece em < 100ms após a interação (mantém AC8.3 do PRD anterior).
- AC10.4: Após chegar a resposta, o skeleton é substituído pelo conteúdo sem flicker visível.
- AC10.5: Em caso de erro de fetch, o skeleton é substituído por estado de erro, não mantido indefinidamente.

### US11 — Zero regressão funcional
**Como** time de devs Genesis **eu quero** garantir que tudo que já funciona em `dev_team` continua funcionando **para** que essa onda só some, nunca regrida.

**Critérios de aceite:**
- AC11.1: A integration suite existente do `dashboard-operacional` continua passando em `dev_gx_goldie`.
- AC11.2: A rota `/missao/logistica/dashboard` continua acessível com o mesmo contrato externo (parâmetros aceitos, comportamento básico).
- AC11.3: Nenhum handler que permanece tem seu contrato (request/response) alterado de forma quebradora sem atualização simultânea dos consumidores.

## Personas envolvidas

| Persona | Papel | Ponto de contato com a feature |
|---|---|---|
| Gestor logístico / supervisor | Decisor operacional | Abre o dashboard, troca aba/período, lê KPIs e rankings |
| Coordenador de separação | Gestor de equipe de separação | Aba Separação, ranking ponderado, badges de score |
| Coordenador de expedição | Gestor de equipe de carregamento | Aba Carregamento, KPI de assertividade do conferente — valida US8 |
| Time de devs Genesis | Mantenedor | Implementa decisões US1-US7, mantém regressão zero |

## Dados / entidades-chave (alto nível)

- `RotaSeparacao` — rota de separação (origem do KPI de fluxo, score, overnight).
- `ParticipacaoSeparacao` — vínculo separador ↔ rota (base do ranking de separação).
- `Carregamento` — carga conferida (origem do KPI de assertividade do conferente).
- `ErrosMotorista` — entradas que classificam uma carga como "com erro" (sujeito da definição em US8).
- `Pessoa` — separador / conferente (sujeito do ranking).
- Estado de UI (período selecionado + aba ativa) — não é entidade de banco, mas é dado persistido conforme US1.
- Cache de séries diárias — chave `(customer, range, tipo)`, conforme US4.

## Regras de negócio

1. Cores semafóricas de assertividade: verde ≥95, amarelo ≥88 e <95, vermelho <88.
2. Cores semafóricas de score: verde ≥70, amarelo ≥45 e <70, vermelho <45.
3. Cores semafóricas de eficiência de fluxo: verde ≥95, amarelo ≥85 e <95, vermelho <85.
4. Cores semafóricas de overnight: verde 0, amarelo 1-3 inclusive, vermelho ≥4.
5. Sparkline é obrigatório nos 6 KPIs.
6. Estado de período + aba é persistido conforme decisão da US1 (link compartilhável quando aplicável).
7. Cache de séries diárias respeita isolamento por `customer` (multi-tenant safe).
8. TTL do cache fica entre 5 e 15 min (valor exato decidido na US4).
9. Definição de "carga com erro" (US8) é a fonte única de verdade para o cálculo do KPI de assertividade do conferente neste sinal.
10. Skeleton/loading é obrigatório em todos os blocos durante re-fetch (KPIs, séries, rankings).
11. Toda decisão das 8 dúvidas em aberto deve estar registrada no `02-techplan.md` com justificativa textual.
12. Apenas uma chart lib e um date range picker convivem no dashboard.
13. Multi-tenant obrigatório (`customerControl` / `companyControl`) em toda Sonda/handler tocado.
14. Todas as strings novas em PHP/JS passam por i18n (pt-br / en / es).

## Métricas de sucesso

- 8/8 dúvidas em aberto fechadas e registradas no `02-techplan.md`.
- Auditoria documental dos 12 handlers `/api/v1/dashboard/*` entregue (mantidos / migrados / removidos).
- Validação visual no review: screenshots lado-a-lado vs protótipo React mostram mesmas cores semafóricas e mesma hierarquia.
- Skeleton/loading aparece em <100ms após troca de período/aba.
- p95 dos handlers de série diária com cache < 200ms para período de 30 dias em `dev_gx_goldie`.
- Zero regressão funcional vs `dev_team` (integration suite verde).
- Coordenador de expedição confirma a definição de "carga com erro" antes do release.

## Dúvidas em aberto

- [ ] US7 — destino final do `frontend-documentacao.md`: PO/TL precisam alinhar entre as três opções (commitar / mover / remover ao final da onda 5).
- [ ] US8 — disponibilidade do coordenador de expedição para validar a definição de "carga com erro" dentro da janela desta onda; se não houver, a definição entra como provisória e a comunicação pré-release vira gate.
- [ ] US5 — definir, junto ao TL no techplan, se a poda dos handlers acontece nesta onda ou é diferida para a onda 2 (o impacto em escopo/tempo da onda 1 depende disso).
