# Implementação frontend — Central2 Frontend Core (F-1 + F-2 + F-3)

## Views criadas / modificadas

- `componentes/Missoes/Logistica/sinais/Central2/html/central2.php` — view index do sinal Central2; container do mapa (`#c2-map`), textareas de config JSON, bloco `C2_MAP_CONFIG`, alerta offline `#c2-socket-offline-alert`, todas as strings via `show()`
- `componentes/Missoes/Logistica/sinais/Central2/html/central2.js` — asset JS próprio do Central2 (865 linhas); IIFE única com `window.C2_STATE`, todos os módulos abaixo

## Forms

Nenhum form criado nesta fase (escrita de rotas é B3 — Labs).

## Módulos implementados em central2.js

### F-1: Núcleo de mapa e markers
- `C2_STATE` — store global (rotas, markersConfig, markerMap, rotaColorMap, pedidoToRotaMap, mapInstance, rotaPolygons)
- `iconBeltMap` — 14 entradas portadas de maps.js ln 490–586
- `naturalSort` — portado de maps.js ln 658–681
- `getOffsetCoordinates` — portado de maps.js ln 718–769 (sem o stackCircle, pois google.maps.Circle requer mapa inicializado)
- `initC2Map` — async, usa `google.maps.importLibrary('maps')`, popula `C2_STATE.mapInstance`
- `getC2MapInstance` — acesso ao singleton do mapa
- `addMarkersToC2Map(markersConfig)` — cria `AdvancedMarkerElement` com `createIconBelt`, armazena em `C2_STATE.markerMap`
- `createIconBelt(markerData)` — portado de maps.js ln 780–926; retorna HTMLElement (div.icon-belt)
- `StyleResolver` — portado de maps.js ln 13510–13541
- `createValueBadge`, `createCubageBadge`, `createDeadlineBadge` — portados de maps.js ln 13546–13669
- `MarkerVisualStrategies` — portado de maps.js ln 13447–13505 (cubage, value, deadline, default)
- `aplicarVisualizacaoNoMarcador` — portado de maps.js ln 13387–13411
- `updateAllMarkerVisuals` — adaptado de maps.js ln 2520–2552 para C2_STATE
- `generateDefaultMarkerIcon(color)` / `generateRouteMarkerIcon(color)` — SVG pin colorido (maps.js ln 2392–2400)
- `crossProduct`, `convexHull` — portados de maps.js ln 2411–2441
- `drawRoutePolygons` — usa C2_STATE.rotas + convexHull + google.maps.Polygon
- `clearRoutePolygons` — limpa C2_STATE.rotaPolygons

### F-2: Store + undo/redo
- `pushC2History()` — snapshot de `C2_STATE.rotas` em memória (max 20)
- `undoC2()` / `redoC2()` — restaura estado + redesenha polígonos e visuais
- Sem textarea, sem localStorage

### F-3: Socket desacoplado
- `C2Socket` — IIFE aninhado com `init`, `on`, `off`, `dispatch`, `subscribeRoom`, `showOfflineAlert`, `hideOfflineAlert`
- Rooms: `observable-galaxia_logistica_central_v2` e `observable-galaxia_logistica_board_v2`
- Handlers registrados: `route_update`, `route_delete`, `markers_update`
- `registrarHandlersSocket()` — chamado no DOMContentLoaded

## i18n

Strings visíveis no PHP via `show()`:

- `'Central'` — título da página
- `'Logística'` — breadcrumb
- `'Central V2 (em desenvolvimento)'` — breadcrumb
- `'Módulo em desenvolvimento — NÃO é produção'` — título do alerta dev
- `'Reescrita V2 desacoplada do Central, acessível apenas a desenvolvedores e rodando em paralelo à V1 (produção), que permanece intacta.'` — corpo do alerta dev
- `'Sincronização offline'` — título do alerta socket
- `'Atualize a página para reconectar.'` — subtítulo do alerta socket

Strings em JS (`title` de ícones do iconBeltMap, texto de badges): são construídas dinamicamente em JS. `show()` não existe como função JS global no projeto — padrão adotado conforme codebase existente (maps.js também não usa show() no JS).

## Endpoints consumidos

Nenhum endpoint consumido diretamente nesta fase. O `addMarkersToC2Map` consome dados já carregados em `C2_STATE.markersConfig` (populado por Lab B3 futuro). O socket (C2Socket) consome payloads `{action, data, timestamp}` publicados nas rooms `_v2` pelo backend.

## Verificações de sintaxe

```
node --check central2.js   → sem erros
php -l central2.php        → No syntax errors detected
```

## Checklist anti-padrão

- `maps.js` não foi editado (diff pré-existente da branch, não desta sessão)
- Nenhuma referência a `.rotasGeradas` ou textarea de estado em central2.js
- Rooms terminam em `_v2` (ROOM_CENTRAL, ROOM_BOARD)
- Handlers registrados via `C2Socket.on()` — sem dispatch implícito por nome de função global
- Sem chamadas de form Galaxia / Laboratório de escrita (B3 futuro)
- Sem referências a rooms sem `_v2`

## Smoke test sugerido

1. Abrir `/missao/Logistica/Central2` como usuário na allowlist `Config::DEV_USER_IDS`
2. Verificar no console: `window.C2_STATE` existe com campos `rotas`, `markerMap`, `rotaColorMap`, `pedidoToRotaMap`, `mapInstance`, `rotaPolygons`
3. Verificar: `window.C2.getMap()` retorna instância do Google Maps após carregamento
4. Mapa deve renderizar com centro em São Paulo (lat -23.5505, lng -46.6333), zoom 11
5. No console, testar markers:
   ```javascript
   window.C2.addMarkers([{pedido_id:1, lat:-23.55, lng:-46.63, arcoIcones:['sequencia']}]);
   // Marcador deve aparecer no mapa
   ```
6. Testar polígonos:
   ```javascript
   window.C2_STATE.rotas = { 1: { pedidos: [1] } };
   window.C2_STATE.rotaColorMap.set(1, '#e53935');
   window.C2.drawRoutePolygons();
   // Ponto/polígono vermelho deve aparecer no mapa
   ```
7. Testar undo/redo:
   ```javascript
   window.C2.pushHistory();
   window.C2_STATE.rotas = { 1: { pedidos: [] } };
   window.C2.undo();
   console.log(window.C2_STATE.rotas[1].pedidos.length); // deve ser 1
   ```
8. Testar socket offline: DevTools > Network > Offline → aguardar ~5s → alerta `#c2-socket-offline-alert` deve aparecer no canto inferior direito
9. Reconectar (Network > Online) — se Scaledrone reconectar, alerta deve sumir
10. Verificar no console: nenhum erro JS ao carregar a página
