# Novidades — Views e UX

> Telas no CMS (AdminLTE). O changelog **não** é publicado no portal.

---

## 1. Layouts e assets

| Item | Caminho | Papel |
|---|---|---|
| Layout do CMS | `v6/resources/views/admin/layouts/app.blade.php` | Container AdminLTE |
| Menu do AdminLTE | `v6/resources/views/vendor/adminlte/page.blade.php:310-317` | Item "Novidades" |
| Rodapé do AdminLTE | `v6/resources/views/vendor/adminlte/page.blade.php:427-432` | Versão do sistema + link para o changelog |
| CSS Insignia (timeline) | `v6/public/layouts/modulos/inspinia/style.css`, `animate.css` | Estilo da timeline vertical |
| CSS ICheck | `v6/public/layouts/modulos/ICheck/custom.css` | Checkboxes |
| Summernote | `v6/public/assets/plugins/summernote/summernote.min.js` | Editor da descrição |
| FontAwesome iconpicker | `v6/public/assets/plugins/fontawesome-iconpicker/dist/js/fontawesome-iconpicker.js` | Seleção do ícone |
| JS do modal | `v6/public/assets/js/custom/config/novidades/changelog-modal.js` | Abre o modal de detalhe |

---

## 2. Tela de listagem (timeline)

`v6/resources/views/prefecture/configurations/changelog/index.blade.php`.

Estrutura:

```blade
<div id="vertical-timeline" class="vertical-container dark-timeline center-orientation">
    @foreach ($changelogs as $log)
        <div class="vertical-timeline-block" id="{{ $log->id }}">
            <div class="vertical-timeline-icon navy-bg">
                <i class="{{ $log->icon }} icon"></i>
            </div>
            <div class="vertical-timeline-content">
                <h2 class="title">{{ str_limit($log->title, 50) }}</h2>
                <p>
                    <input type="hidden" class="description" value="{{ $log->descricao }}">
                    {{ str_limit(strip_tags($log->descricao), 250) }}
                </p>
                <div class="actions">
                    ... botões ...
                </div>
                <span class="vertical-date">
                    <span class=" numero_versao">Versão {{ $log->numero_versao }}</span> <br />
                    <small class="data_versao">{{ date('d/m/Y', strtotime($log->data_versao)) }}</small>
                </span>
            </div>
        </div>
    @endforeach
</div>
```

Características:

- Um bloco por versão, em ordem **decrescente** por `id`.
- O **título** é truncado em 50 caracteres (`str_limit`, função do Laravel
  5.5, removida no Laravel 6+).
- O **resumo** da descrição é o HTML sem tags, truncado em 250
  caracteres.
- A descrição **completa** é escondida em um `<input type="hidden">` para
  ser lida pelo JavaScript.
- Se não houver registros, exibe "Nenhum registro encontrado" e remove o
  traço vertical da timeline via CSS inline.
- A descrição é impressa com `{{ }}` (escapada) no resumo — **seguro**;
  no modal, é injetada com `innerHTML` (ver 04/05).

### 2.1 Botões de ação

| Botão | Condição | Destino |
|---|---|---|
| Olho / "Saber mais" | `changelog.edit` -> ícone; senão -> botão "Saber mais" | abre o modal |
| Lápis | `changelog.edit` | `route('changelog.editar', $log->id)` |
| Lixeira | `changelog.delete` | `Form::open(['route' => ['changelog.delete', $log->id], 'method' => 'DELETE'])` |

> O botão "Saber mais" **sempre** existe (fora do `@if` de edição), o
> que garante que a descrição completa é acessível a qualquer operador
> autenticado — mesmo sem permissão de edição.

---

## 3. Modal de detalhe

`v6/resources/views/prefecture/configurations/changelog/modal.blade.php`.

Estrutura: `<div class="modal fade" id="modal">` com `#modalTitle`,
`#content-modal` e `#version-modal`.

O JavaScript (`v6/public/assets/js/custom/config/novidades/changelog-modal.js`)
preenche os três campos:

```js
let data = document.getElementById(e.attributes.id.value);
let desc = data.querySelector('.description').value;
let title = data.querySelector('.title').innerHTML;
let icon = data.querySelector('.icon').classList;
let data_version = data.querySelector('.data_versao').innerHTML;
let numero_versao = data.querySelector('.numero_versao').innerHTML.split(' ')[1];

document.querySelector('#modalTitle').innerHTML = `${title} <br> <small><i class="fa fa-calendar"></i> ${data_version}</small>`;
document.querySelector('#content-modal').innerHTML = desc;
document.querySelector('#version-modal').innerHTML = `<i class="${icon}"></i> Versão ${numero_versao}`;
$('#modal').modal('show');
```

Pontos:

- `desc` (o HTML do Summernote) é injetado com **`innerHTML`** — o
  conteúdo é sanitizado apenas pelo Summernote no cliente, sem
  sanitização no servidor. Como o `title` também vai para `innerHTML`,
  um título com `<script>` seria executado.
- O `numero_versao` é extraído com `split(' ')[1]` do texto
  "Versão 6.0" — frágil se o texto mudar.
- Não há sanitização de `data_version` (vem de `innerHTML` do servidor).

---

## 4. Formulário

`v6/resources/views/prefecture/configurations/changelog/create.blade.php`,
`edit.blade.php` e `form.blade.php`.

| Campo | Componente | Validação no cliente | Regra no servidor |
|---|---|---|---|
| `title` | `Form::text` | `maxlength="150"` | `required|max:120|min:3` |
| `numero_versao` | `Form::text` | `maxlength=20`, `pattern="^[0-9]+(\.[0-9]+)*$"` | `required` |
| `data_versao` | `input` + `datetimepicker` (`format: 'd/m/Y H:i:s'`) | — | `required` |
| `icon` | `Form::text` com `iconpicker` | `maxlength=120` | `required` |
| `descricao` | `textarea.summernote` | — | `required|min:3` |

> A divergência `maxlength="150"` (cliente) x `max:120` (servidor) faz
> o servidor rejeitar títulos de 121 a 150 caracteres com uma mensagem
> que o usuário não antecipa.

Scripts: Summernote (pt-BR) + `fontawesome-iconpicker` +
`datetimepicker` com locale `pt-BR`.

---

## 5. JavaScript / Ajax

- **Sem AJAX**: a listagem é renderizada no servidor.
- **Sem polling**.
- Único JS do módulo: `changelog-modal.js` (descrito em 3).

---

## 6. Exportações

**Nenhuma.**

---

## 7. O que o operador vê

1. Engrenagem do CMS -> **Novidades** (ou o link "Versão" no rodapé).
2. Timeline vertical, da versão mais recente para a mais antiga, com
   ícone, título truncado, resumo, número da versão e data.
3. "Saber mais" -> modal com a descrição completa (com imagens).
4. Lápis -> formulário de edição; lixeira -> exclusão.
5. "Cadastrar Novidades" -> formulário (visível apenas com
   `changelog.index`).

## 8. O que o cidadão vê

**Nada.** O changelog é interno. O portal público mostra apenas a
**versão numérica** no rodapé (`update_logs.version`), sem link.

---

## 9. Itens de UX a preservar na v7

- A timeline vertical com ícone colorido por versão.
- O resumo com HTML removido e o detalhe completo em modal.
- O seletor de ícones (FontAwesome) com pré-visualização.
- O datepicker em pt-BR.
- A numeração de versão exibida junto da data.
