# Ajuste de Dados — Filtros de Campos Vazios

**Data:** 2026-05-26  
**Escopo:** Frontend only — `designar_unificado.php` + `designar_unificado.js`  
**Tipo:** Extensão da feature de filtro client-side (adiciona 3 novos toggles ao existente)

---

## Problema

O toggle "Sem c. barras" já existe. O usuário precisa de filtros equivalentes para outros campos que podem estar vazios nos produtos: cubagem, peso e endereço.

## Solução

Agrupar os 4 toggles (incluindo o existente) em um container flex compartilhado, e adicionar os 3 novos seguindo exatamente o mesmo padrão de implementação já estabelecido.

---

## Campos e Condições

| Toggle | `id` do botão | Campo em `rawPrimaryData` | Condição "sem dados" | Flag JS |
|---|---|---|---|---|
| Sem barras | `toggle-sem-barras` | `codigo_barras` | `!p.codigo_barras` | `semCodigoBarras` (já existe) |
| Sem cubagem | `toggle-sem-cubagem` | `cubagem` | `!p.cubagem \|\| p.cubagem == 0` | `semCubagem` |
| Sem peso | `toggle-sem-peso` | `peso` | `!p.peso \|\| p.peso == 0` | `semPeso` |
| Sem endereço | `toggle-sem-end` | `localizacao` | `!p.localizacao` | `semEndereco` |

**Nota sobre o botão existente:** o texto do `toggle-sem-barras` muda de "Sem c. barras" para "Sem barras" para manter consistência visual com os demais pills.

**Nota:** `cubagem` é um número calculado no backend (`cub_altura * cub_largura * cub_profund`). Zero significa que as três dimensões são zero/ausentes. `localizacao` é o campo de endereço/localização (mapeado de `codigo_enderecamento` no laboratório).

---

## Arquitetura

Mudança puramente client-side. Padrão idêntico ao `semCodigoBarras` já implementado — sem novos conceitos.

---

## Componentes Alterados

### `designar_unificado.php`

**Substituir** o container isolado do toggle existente:

```html
<?php if ($tipo === 'ajuste'): ?>
<div style="margin: 0.5rem 0;">
    <button type="button"
            id="toggle-sem-barras"
            class="btn-action"
            title="Mostrar apenas produtos sem código de barras">
        <i class="bi bi-upc-scan"></i> Sem barras
    </button>
</div>
<?php endif; ?>
```

**Por este container compartilhado com os 4 pills:**

```html
<?php if ($tipo === 'ajuste'): ?>
<div style="display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.5rem 0;">
    <button type="button" id="toggle-sem-barras"  class="btn-action" title="Mostrar apenas produtos sem código de barras">
        <i class="bi bi-upc-scan"></i> Sem barras
    </button>
    <button type="button" id="toggle-sem-cubagem" class="btn-action" title="Mostrar apenas produtos sem cubagem">
        <i class="bi bi-box"></i> Sem cubagem
    </button>
    <button type="button" id="toggle-sem-peso"    class="btn-action" title="Mostrar apenas produtos sem peso">
        <i class="bi bi-speedometer2"></i> Sem peso
    </button>
    <button type="button" id="toggle-sem-end"     class="btn-action" title="Mostrar apenas produtos sem endereço">
        <i class="bi bi-geo-alt"></i> Sem endereço
    </button>
</div>
<?php endif; ?>
```

---

### `designar_unificado.js`

#### 1. `State.filters.primary` — 3 flags novos

```js
filters: {
    primary: {
        search: '',
        semCodigoBarras: false,
        semCubagem: false,
        semPeso: false,
        semEndereco: false
    },
    operadores: { search: '' }
},
```

#### 2. `State.init()` — 3 Sets novos (após `semBarrasIds` existente)

```js
// já existe:
this.semBarrasIds = new Set(
    this.rawPrimaryData.filter(p => !p.codigo_barras).map(p => String(p.id))
);

// novos:
this.semCubagemIds = new Set(
    this.rawPrimaryData.filter(p => !p.cubagem || p.cubagem == 0).map(p => String(p.id))
);
this.semPesoIds = new Set(
    this.rawPrimaryData.filter(p => !p.peso || p.peso == 0).map(p => String(p.id))
);
this.semEnderecoIds = new Set(
    this.rawPrimaryData.filter(p => !p.localizacao).map(p => String(p.id))
);
```

#### 3. `State.getFiltered()` — guard e bloco ajuste atualizados

Guard (já corrigido, precisa incluir novas flags):

```js
if (!filter || (
    !filter.search &&
    !filter.semCodigoBarras &&
    !filter.semCubagem &&
    !filter.semPeso &&
    !filter.semEndereco
)) return items;
```

Bloco ajuste (após o check de `semCodigoBarras` já existente):

```js
if (filter.semCodigoBarras && !State.semBarrasIds.has(String(item.id)))   return false;
if (filter.semCubagem      && !State.semCubagemIds.has(String(item.id)))   return false;
if (filter.semPeso         && !State.semPesoIds.has(String(item.id)))      return false;
if (filter.semEndereco     && !State.semEnderecoIds.has(String(item.id)))  return false;
return true;
```

#### 4. Event listeners — 3 novos (mesmo padrão do existente)

```js
document.getElementById('toggle-sem-cubagem')?.addEventListener('click', function () {
    State.filters.primary.semCubagem = !State.filters.primary.semCubagem;
    this.classList.toggle('active', State.filters.primary.semCubagem);
    State.pagination.primary.page = 1;
    View.renderPrimary();
});

document.getElementById('toggle-sem-peso')?.addEventListener('click', function () {
    State.filters.primary.semPeso = !State.filters.primary.semPeso;
    this.classList.toggle('active', State.filters.primary.semPeso);
    State.pagination.primary.page = 1;
    View.renderPrimary();
});

document.getElementById('toggle-sem-end')?.addEventListener('click', function () {
    State.filters.primary.semEndereco = !State.filters.primary.semEndereco;
    this.classList.toggle('active', State.filters.primary.semEndereco);
    State.pagination.primary.page = 1;
    View.renderPrimary();
});
```

---

## Comportamento

| Cenário | Resultado |
|---|---|
| Todos OFF | Lista completa (comportamento atual) |
| "Sem cubagem" ON | Somente produtos com `cubagem` falsy ou zero |
| "Sem peso" ON | Somente produtos com `peso` falsy ou zero |
| "Sem endereço" ON | Somente produtos com `localizacao` falsy |
| Múltiplos ON | Interseção — produto precisa satisfazer TODOS os filtros ativos |
| Toggle + busca textual | Cumulativo com texto |

---

## Fora do Escopo

- Campos `cub_altura`, `cub_largura`, `cub_profund` individuais — não chegam no flat data de ajuste.
- Campos `lote`, `validade`, `observacao` — são campos de coleta durante o ajuste, não pré-existentes no produto.
- Outros tipos de designação (separação, romaneio): container não renderiza.
