# Avisos — Views e UX

> CMS (AdminLTE) e portal (Bootstrap 4). O modal do aviso aparece na home de todos os
> layouts, com HTML copiado em 7 arquivos.

---

## 1. CMS — `v6/resources/views/prefecture/contents/anuncios/`

| Arquivo | Função | Observações |
|---|---|---|
| `index.blade.php` | Listagem com DataTable `#tabela_anuncios` | Colunas: checkbox de lote, ID, Título, Status, Ações; botão "Cadastrar Aviso" (`cadastrar/anuncios`) |
| `create.blade.php` | Formulário de cadastro | inclui `anuncios/form.blade.php` |
| `edit.blade.php` | Formulário de edição | `Form::model($content, ['route' => ['conteudo.update', $content->id], 'files' => true, 'method' => 'PUT'])` |
| `form.blade.php` | Campos | Status, Título, Link, Imagem (upload + preview + editor), "Abrir em nova guia" |

### Formulário (real)

```blade
{{-- v6/resources/views/prefecture/contents/anuncios/form.blade.php --}}
<input type="hidden" name="category_contents_id" value="{{$categoryContent->id}}">

@include('components.inputs.checkbox', [
    'size' => 12,
    'id' => 'status',
    'titulo' => 'Ativar/Desativar',
    'data' => isset($content)&& $content->status == false  ? false : true
])

@include('components.inputs.input', [
    'size' => 5, 'id' => 'title', 'titulo' => 'Título', 'mandatory' => true,
    'maxlen' => '120', 'placeholder' => 'Título',
    'data' => isset($content) ? $content->title : old('title')
])

@include('components.inputs.input', [
    'size' => 7, 'id' => 'link', 'titulo' => 'Link', 'mandatory' => true,
    'maxlen' => '200', 'placeholder' => 'URL',
    'data' => isset($content) ? $content->linksUnique['link'] : old('link')
])

<input type="file" class="form-control-file" name="archive_highlight" accept="image/*" id="file" style="display: none !important;">
<small id="fileHelp" class="form-text text-muted"></small>
<div>
    <small class="form-text text-muted">Tamanho padrão: 700x405</small>
</div>

@include('components.inputs.checkbox', [
    'size' => 5, 'id' => 'isBlank', 'titulo' => 'Abrir em nova guia',
    'data' => isset($content) && $content->linksUnique['isBlank'] == 1 ? true : false
])
```

Características do formulário:

| Campo | Comportamento |
|---|---|
| Status | Checkbox "Ativar/Desativar"; marcado por padrão na criação (`$content->status == false ? false : true`) |
| Título | Input de 5 colunas, `maxlen` 120 |
| Link | Input de 7 colunas, `maxlen` **200** no markup (o servidor aceita até 2999) |
| Imagem | Upload escondido (`display:none`), acionado pelo botão "Selecionar imagem"; preview em `storage/content/anuncios/{id}/destaque/{nome}`; botão "Editar" (recorte); dica "Tamanho padrão: 700x405" |
| Abrir em nova guia | Checkbox `isBlank` (persistido em `links.isBlank`) |

## 2. CMS — JavaScript do DataTable

Arquivo: `v6/public/assets/js/custom/contents/avisos/datatable.js`

```js
let collums = [
    {
        data: 'titulo',
        render: function (data) {
            return `<div class='vertical-middle' style='padding:8px'>${data}</div>`;
        }
    },
    {
        data: 'status_name',
        render: function (data) {
            return `<div class='font-weight-bold text-center'>${data}</div>`;
        }
    },
    {
        data: null,
        orderable: false,
        render: function (data) {
            return `<div class='flex justify-center'>`
                + createActiveButton(data.status, data.id, 'item', data.active, data.inactivate)
                + createBTN(data.id, `editar/anuncios/${data.id}`, data.edit, data.delete)
                + `</div>`;
        }
    }
];

runDatatables('anuncios', collums, true, 'ASC', null, true);
```

- `runDatatables` consome `/cms/datatable/anuncios`
  (`v6/public/assets/js/custom/utilities/table.js:181-184`).
- `createActiveButton(data.status, data.id, 'item', data.active, data.inactivate)` gera o
  botão de liga/desliga que faz `POST /cms/set-status`
  (`v6/public/assets/js/custom/utilities/table.js:373-393`).
- A exclusão em lote usa `assets/js/custom/utilities/deleteAll.js`
  (`index.blade.php:57`).

## 3. Portal — onde o aviso aparece

| Layout | Arquivo | Forma |
|---|---|---|
| modelo1 | `v6/resources/views/portal/layouts/modelo1/home/aviso.blade.php` | Include próprio `home/aviso` |
| modelo2 | `v6/resources/views/portal/layouts/modelo2/home/index.blade.php:16` | `@include('portal.layouts.modelo1.home.aviso')` |
| modelo3 | `v6/resources/views/portal/layouts/modelo3/home/aviso.blade.php` | Include próprio |
| modelo4 | `v6/resources/views/portal/layouts/modelo4/home/aviso.blade.php` | Include próprio (id do modal `modalAviso`) |
| modelo5 | `v6/resources/views/portal/layouts/modelo5/home/index.blade.php:56-70` | HTML inline (Bootstrap 5) |
| modelo6 | `v6/resources/views/portal/layouts/modelo6/home/index.blade.php:18-30` | HTML inline |
| default | `v6/resources/views/portal/layouts/default/pages/index.blade.php:12-30` | HTML inline (layout sem `home/index`, portanto inativo) |

Conteúdo do modal (modelo1, real):

```blade
@if (isset($modulos['avisos']) && $modulos['avisos'] && !empty($anuncio))
    <button type="button" class="d-none" id="btn-anuncio" data-toggle="modal" data-target="#anuncio"></button>
    <div class="modal fade" id="anuncio" tabindex="-1" role="dialog" aria-hidden="true">
        <div class="modal-dialog modal-dialog-centered" style="max-width: 700px" role="document">
            <div class="modal-content">
                <div class="modal-body">
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close" style="position: absolute; right: 20px; font-size: 40px">
                        <span aria-hidden="true">&times;</span>
                    </button>
                    <a href="{{ $anuncio->linksUnique->link }}"
                       @if ($anuncio->linksUnique->isBlank == true) target="_blank" @endif>
                        <img style="width: 100%" src="{{ url($anuncio->archives->where('highlight', 1)->first()->path) }}" alt="{{ $anuncio->title }}">
                    </a>
                </div>
            </div>
        </div>
    </div>
@endif
```

Observações:

- O `modelo1` exige `isset($modulos['avisos'])` — ou seja, o aviso só é exibido se o
  módulo **"Avisos"** estiver habilitado na configuração de módulos do portal.
- A variável `$modulos` vem de um view composer:
  `v6/app/Providers/ModulosServiceProvider.php:22-50` — `Modulos::all()->pluck('status','slug')`,
  com `Cache::rememberForever('modulos', fn () => Modulos::all()->pluck('status','slug'))`. O composer é aplicado às homes de
  `modelo1`..`modelo6`; **não** é aplicado a `portal.layouts.default.pages.index`,
  então no layout `default` o `isset($modulos['avisos'])` é falso e o modal não é
  renderizado (o que evita o erro, mas deixa o layout `default` sem aviso).
- O `default` e o `modelo6` **não** verificam `$modulos['avisos']`: exibem o modal
  sempre que houver `$anuncio` (divergência entre layouts).
- A imagem vem de `$anuncio->archives->where('highlight', 1)->first()->path`: se o aviso
  ativo não tiver imagem de destaque, o acesso a `->path` em `null` gera erro.

## 4. Abertura automática do modal

Em cada layout há um script que dispara o clique no botão oculto:

```blade
{{-- v6/resources/views/portal/layouts/modelo1/layout/scripts.blade.php:17-20 --}}
@if (!empty($anuncio))
    $(document).ready(function() {
        $('#btn-anuncio').click();
    });
@endif
```

No `modelo6` a abertura usa a API nativa do Bootstrap 5:

```js
// v6/resources/views/portal/layouts/modelo6/layout/scripts.blade.php:17-21
var modalEl = document.getElementById('anuncio');
```

## 5. O que o usuário final vê

1. Abre a home do portal: o modal com o comunicado surge automaticamente (sem clique).
2. O modal mostra a **imagem** do aviso (700x405) clicável.
3. O clique navega para o link informado pelo operador; se "Abrir em nova guia" estiver
   marcado, abre em nova aba (`target="_blank"`).
4. O botão "X" fecha o modal.
5. Não há como consultar o aviso depois que ele é fechado, nem uma página que os liste.

## 6. Exportações

O CMS exporta a listagem de avisos (Excel/PDF) pelos botões client-side do DataTable
(`v6/public/assets/js/custom/utilities/table.js:29-33`). O portal não exporta.
