# Ajuste de Dados — Filtro Sem Código de Barras — Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Adicionar toggle pill "Sem c. barras" na tela de designação de Ajuste de Dados que filtra a lista para exibir somente produtos sem código de barras.

**Architecture:** Mudança puramente client-side. `designar_unificado.php` recebe CSS para estado ativo e o botão HTML condicional em `$tipo === 'ajuste'`. `designar_unificado.js` recebe: Set pré-computado no init, flag no filtro, correção do guard de early-return, lógica de exclusão em `getFiltered`, e event listener no controller.

**Tech Stack:** PHP (view template), vanilla JS (sem framework), Bootstrap Icons (`bi-upc-scan`), CSS custom properties `var(--dm-primary)`.

---

## Arquivos modificados

| Arquivo | O que muda |
|---|---|
| `componentes/Missoes/Logistica/sinais/Designacoes/html/designar_unificado.php` | CSS `.btn-action.active` + botão `#toggle-sem-barras` (condicional) |
| `componentes/Missoes/Logistica/sinais/Designacoes/html/designar_unificado.js` | Set pré-computado, flag `semCodigoBarras`, guard + filtro em `getFiltered`, listener no controller |

---

## Task 1: CSS para estado ativo do toggle

**Files:**
- Modify: `componentes/Missoes/Logistica/sinais/Designacoes/html/designar_unificado.php`

- [ ] **Localizar o bloco `.btn-action:hover`** (por volta da linha 248) no `<style>` do arquivo.

- [ ] **Adicionar regra `.btn-action.active` imediatamente após `.btn-action:hover`:**

```css
    .btn-action.active {
        background: var(--dm-primary);
        border-color: var(--dm-primary);
        color: white;
    }
```

O bloco resultante deve ficar assim:

```css
    .btn-action:hover {
        background: var(--dm-primary);
        border-color: var(--dm-primary);
        color: white;
    }

    .btn-action.active {
        background: var(--dm-primary);
        border-color: var(--dm-primary);
        color: white;
    }
```

- [ ] **Verificar no browser** que o botão "Todos" (já existente) não sofreu regressão visual.

---

## Task 2: Botão toggle no HTML da view

**Files:**
- Modify: `componentes/Missoes/Logistica/sinais/Designacoes/html/designar_unificado.php`

- [ ] **Localizar o bloco `<!-- Conteúdo Via Romaneio (default) -->`** (por volta da linha 888):

```html
            <!-- Conteúdo Via Romaneio (default) -->
            <div id="modo-romaneio-container">
                <input type="text" class="search-input" id="search-primary" placeholder="Buscar <?= strtolower($primaryLabel) ?>...">
                <div class="item-list" id="lista-primary">
```

- [ ] **Inserir o toggle pill entre o `<input>` de busca e o `<div id="lista-primary">`**, condicionado a `$tipo === 'ajuste'`:

```html
            <!-- Conteúdo Via Romaneio (default) -->
            <div id="modo-romaneio-container">
                <input type="text" class="search-input" id="search-primary" placeholder="Buscar <?= strtolower($primaryLabel) ?>...">
                <?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 c. barras
                    </button>
                </div>
                <?php endif; ?>
                <div class="item-list" id="lista-primary">
```

- [ ] **Verificar que em tipos diferentes de `ajuste`** (ex: separação, romaneio) o botão não aparece — abrir a tela de designação de outro tipo.

- [ ] **Verificar que em `ajuste`** o botão aparece abaixo da busca, antes da lista.

---

## Task 3: Pré-computação do Set e flag no State

**Files:**
- Modify: `componentes/Missoes/Logistica/sinais/Designacoes/html/designar_unificado.js`

- [ ] **Adicionar `semCodigoBarras: false` em `State.filters.primary`** (linha ~43):

Antes:
```js
        filters: {
            primary: { search: '' },
            operadores: { search: '' }
        },
```

Depois:
```js
        filters: {
            primary: { search: '', semCodigoBarras: false },
            operadores: { search: '' }
        },
```

- [ ] **Localizar o final do bloco de carregamento de `rawPrimaryData` em `State.init()`** — por volta da linha 104:

```js
                if (!this.hasHierarchy) {
                    this.rawPrimaryData.forEach(item => {
                        const id = item.id;
                        this.data.primary[id] = { ...item, selected: false };
                    });
                }
                this.pagination.primary.total = this.rawPrimaryData.length;
```

- [ ] **Adicionar a pré-computação do Set logo após `this.pagination.primary.total = ...`:**

```js
                if (!this.hasHierarchy) {
                    this.rawPrimaryData.forEach(item => {
                        const id = item.id;
                        this.data.primary[id] = { ...item, selected: false };
                    });
                }
                this.pagination.primary.total = this.rawPrimaryData.length;

                // Pré-computa IDs de produtos sem código de barras (O(n) uma vez)
                this.semBarrasIds = new Set(
                    this.rawPrimaryData
                        .filter(p => !p.codigo_barras)
                        .map(p => String(p.id))
                );
```

---

## Task 4: Corrigir guard e adicionar filtro em `getFiltered`

**Files:**
- Modify: `componentes/Missoes/Logistica/sinais/Designacoes/html/designar_unificado.js`

- [ ] **Localizar `getFiltered` (linha ~153):**

```js
        getFiltered: function (type) {
            const items = Object.values(this.data[type]);
            const filter = this.filters[type];
            if (!filter || !filter.search) return items;
```

- [ ] **Corrigir o guard e a definição de `searchLower`** — sem essa correção, o toggle não funciona quando a busca está vazia:

```js
        getFiltered: function (type) {
            const items = Object.values(this.data[type]);
            const filter = this.filters[type];
            if (!filter || (!filter.search && !filter.semCodigoBarras)) return items;

            const searchLower = filter.search ? filter.search.toLowerCase() : '';
```

A linha `const searchLower = filter.search.toLowerCase();` original continua logo abaixo do guard — substituir ela também.

- [ ] **Localizar o bloco de filtro para `ajuste` (linha ~162-166):**

```js
                    if (this.tipo === 'ajuste') {
                        const marcaText = item.marcaData ? ' ' + item.marcaData.descricao : '';
                        const text = (item.descricao || '') + ' ' + (item.codigo_produto || '') + ' ' + (item.codigo_barras || '') + marcaText;
                        return text.toLowerCase().includes(searchLower);
                    }
```

- [ ] **Expandir o bloco para aplicar o filtro de sem barras após o filtro de texto:**

```js
                    if (this.tipo === 'ajuste') {
                        // Filtro de texto
                        if (filter.search) {
                            const marcaText = item.marcaData ? ' ' + item.marcaData.descricao : '';
                            const text = (item.descricao || '') + ' ' + (item.codigo_produto || '') + ' ' + (item.codigo_barras || '') + marcaText;
                            if (!text.toLowerCase().includes(searchLower)) return false;
                        }
                        // Filtro sem código de barras: exclui quem TEM barras
                        if (filter.semCodigoBarras && !State.semBarrasIds.has(String(item.id))) return false;
                        return true;
                    }
```

---

## Task 5: Event listener do toggle no Controller

**Files:**
- Modify: `componentes/Missoes/Logistica/sinais/Designacoes/html/designar_unificado.js`

- [ ] **Localizar o bloco de listener do `search-primary` no `bindEvents` (linha ~577):**

```js
            document.getElementById('search-primary')?.addEventListener('input', e => {
                this.debounceFilter('primary', e.target.value);
            });
            document.getElementById('search-operadores')?.addEventListener('input', e => {
                this.debounceFilter('operadores', e.target.value);
            });
```

- [ ] **Adicionar o listener do toggle imediatamente após o listener de `search-operadores`:**

```js
            document.getElementById('search-primary')?.addEventListener('input', e => {
                this.debounceFilter('primary', e.target.value);
            });
            document.getElementById('search-operadores')?.addEventListener('input', e => {
                this.debounceFilter('operadores', e.target.value);
            });

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

---

## Task 6: Verificação manual e commit

- [ ] **Abrir a tela de designação de Ajuste de Dados** no browser.

- [ ] **Verificar cenário 1 — toggle ativa filtro:**
  - Clicar "Sem c. barras"
  - Botão deve ficar com fundo azul (classe `active`)
  - Lista deve exibir somente produtos sem código de barras
  - Counter `#count-primary` permanece mostrando selecionados (zero se nada selecionado)

- [ ] **Verificar cenário 2 — filtros cumulativos:**
  - Com toggle ativo, digitar texto na busca
  - Lista deve reduzir para produtos sem barras que contenham o texto

- [ ] **Verificar cenário 3 — toggle desativa:**
  - Clicar "Sem c. barras" novamente
  - Botão volta ao estado normal
  - Lista exibe todos os produtos novamente (respeitando busca textual se houver)

- [ ] **Verificar cenário 4 — seleção preservada:**
  - Selecionar alguns produtos com toggle ativo
  - Desativar toggle
  - Os produtos selecionados devem permanecer marcados na lista completa

- [ ] **Verificar cenário 5 — sem regressão em outros tipos:**
  - Abrir designação de Separação ou Romaneio
  - Botão "Sem c. barras" não deve aparecer

- [ ] **Commit:**

```bash
git add componentes/Missoes/Logistica/sinais/Designacoes/html/designar_unificado.php \
        componentes/Missoes/Logistica/sinais/Designacoes/html/designar_unificado.js
git commit -m "feat(ajustedados): toggle filtro sem código de barras na designação"
```
