# Publicações — Views e UX

## 1. CMS — telas

Pasta: `v6/resources/views/prefecture/contents/publicacoes/`

| Arquivo | Linhas | Função |
|---|---|---|
| `index.blade.php` | 68 | Listagem (datatable `tabela_publicacoes`) |
| `create.blade.php` | 35 | Wrapper do formulário de criação |
| `edit.blade.php` | 71 | Wrapper do formulário de edição (galeria + link permanente) |
| `form.blade.php` | 147 | Formulário completo |

Estrutura da listagem (`index.blade.php`):

```blade
<h3 class="box-title align-middle">Lista de Publicações</h3>
@if (has_access(['publicacoes.create']))
    <a href="cadastrar/publicacoes" class="btn btn-success font-weight-bold btn-sm" role="button">
        <i class="fa fa-plus"></i> Cadastrar Publicação
    </a>
@endif
@if (has_access(['publicacoes.create']))
    <a href="{{ route('cadastrar-categorias', 'publicacoes') }}"
        class="btn btn-primary font-weight-bold btn-sm" role="button">Categorias de
        Publicação</a>
@endif
<table id="tabela_publicacoes" class="table table-striped w-100">
    <thead>
        <tr>
            <th width="5%">ID</th>
            <th>Título</th>
            <th>Categoria</th>
            <th class="text-center">Data de publicação</th>
            <th class="column-actions text-center">Ações</th>
        </tr>
    </thead>
```

Scripts (`index.blade.php`):

```blade
<script src="{{ url('assets/js/custom/utilities/deleteAll.js') }}"></script>
<script src="{{ asset('assets/js/custom/contents/publicacoes/datatable.js') }}"></script>
```

Layout do CMS: `admin.layouts.app` (AdminLTE 1.22 / Bootstrap 3).

## 2. CMS — formulário

`v6/resources/views/prefecture/contents/publicacoes/form.blade.php`

| Campo | Componente | Observações |
|---|---|---|
| Categoria | `Form::select('category_contents_id', $categoryContentSelect->plucK('name','id'))` | Lista as subcategorias; prefixo "Pai > Filho" quando aplicável |
| Link Permanente | `components.inputs.input` `id = 'slug'` | Exibido **somente** na edição; prefixo `url("publicacoes/$category->slug")` |
| Título | `components.inputs.input` `id = 'title'` | obrigatório, `maxlen` default |
| Data de publicação | `components.inputs.date` `id = 'publication_date'` | máscara `br-data-tempo`, formato `d/m/Y H:i` |
| Layout de exibição | `components.inputs.radio` `name = 'layout'` | `1` = Com Barra Lateral, `2` = Sem Barra Lateral (padrão na criação) |
| Texto | `components.inputs.textarea` `id = 'text'` | Summernote |
| Arquivos | `components.inputs.archive` | Bloco de anexos com "Adicionar Arquivo" |

Trecho do layout de exibição:

```blade
<span class="text-bold d-block text-left">Layout de exibição</span>
@include('components.inputs.radio', [
'data' => 1,
'id' => 'layout-1',
'name' => 'layout',
'titulo' => 'Com Barra Lateral',
'image' => '/assets/images/page-sidebar.png',
'value' => isset($content) && $content->layout == 1,
])
@include('components.inputs.radio', [
'data' => 2,
'id' => 'layout-2',
'name' => 'layout',
'titulo' => 'Sem Barra Lateral',
'image' => '/assets/images/page-wide.png',
'value' => (isset($content) && $content->layout == 2) || !isset($content),
])
```

Scripts do formulário: `add_archive.js`, Summernote (`summernote.min.js`,
`summernote-pt-BR.js`, `summernote-image-atr.js`, `richtext/summernote.js`) e a
máscara de data `00/00/0000 00:00`.

## 3. CMS — JavaScript da datatable

`v6/public/assets/js/custom/contents/publicacoes/datatable.js`

| Coluna | Campo | Render |
|---|---|---|
| Título | `titulo` | `div.p-10-0` |
| Categoria | `categoria` | nome em negrito |
| Data | `data_publicacao` | `converterData()` gera `<span class="d-none">YYYY-MM-DD HH:MM:SS</span>` para ordenação |
| Ações | `data: null` | botão "Acessar publicação" (`/publicacoes/{categoria_slug}/{slug}`, em nova aba) e botão de editar |

```js
runDatatables('publicacoes', collums, true, 'ASC', null, true);
```

O `runDatatables` chama `GET /cms/datatable/publicacoes`.

## 4. Portal — arquivos Blade por layout

| Layout | Pasta | Arquivos |
|---|---|---|
| `modelo1` | `v6/resources/views/portal/layouts/modelo1/publicacoes/` | `list.blade.php` (115), `show.blade.php` (139), `view.blade.php` (48) |
| `modelo2` | `.../modelo2/publicacoes/` | `list.blade.php`, `pub-nav.blade.php`, `show.blade.php`, `view.blade.php` |
| `modelo3` | `.../modelo3/publicacoes/` | idem modelo2 |
| `modelo4` | `.../modelo4/publicacoes/` | idem modelo2 |
| `modelo5` | `.../modelo5/publicacoes/` | idem modelo2 |
| `modelo6` | `.../modelo6/publicacoes/` | idem modelo2 |
| `newsbit` | `.../newsbit/publicacoes/` | `index.blade.php`, `list.blade.php`, `show.blade.php`, `view.blade.php` |

Componente de navegação de categorias:
`v6/resources/views/portal/components/categories-contents/publicacoes/nav.blade.php`.

Componente de listagem de arquivos do PDF inline:
`v6/resources/views/portal/components/view_pdf/files-list.blade.php`.

## 5. Portal — listagem (show + list)

`show.blade.php` (modelo1) monta a moldura e carrega a partial `list`:

```blade
@section('content')
    <div class="col-md-12 mx-auto row">
        @include('portal.components.categories-contents.publicacoes.nav')
        <div id="pub-content" class="col-md-8 text-center text-secondary">
            <div class="sk-spinner sk-spinner-wave"> ... </div>
            <div id="include-list">
                @include('portal.layouts.modelo1.publicacoes.list')
            </div>
        </div>
    </div>
@endsection
```

O JavaScript de paginação recarrega o bloco via Ajax:

```js
function getPosts(page) {
    $('#pub-content').toggleClass('sk-loading');
    var ano = $('select[name="ano"]').val();
    var mes = $('select[name="mes"]').val();
    var text = $('input[id="search"]').val();

    $.ajax({
        url: '?page=' + page + '&ano=' + ano + '&mes=' + mes + '&texto=' + text,
        dataType: 'json',
    }).done(function(data) {
        $('#pub-content').toggleClass('sk-loading');
        $('#include-list').html(data);
        location.hash = page;
    }).fail(function() {
        $('#pub-content').toggleClass('sk-loading');
        alert('As publicações não puderam ser carregadas.');
    });
}
```

A resposta é o HTML da partial `list` (o controller responde
`Response::json(view(...)->render())`).

### Filtros na partial `list`

| Filtro | Elemento | Comportamento |
|---|---|---|
| Ano | `<select name="ano" onchange="getPostsByAno();">` | opções vindas de `$anos` (SQL com `extract(year ...)`); anos futuros são ocultados (`@if ($ano->ano <= date('Y'))`) |
| Mês | `<select name="mes" onchange="getPostsByMes();">` | opções vindas de `$meses`; rótulo via `translateMonth($mes->mes)` |
| Texto | `<input id="search">` | busca acento-insensível em título e texto |
| Categoria | `<input type="hidden" name="sub_category" value="{{ $category->slug }}">` | usado pela rota de exportação |

## 6. Portal — documento (`view.blade.php`)

`v6/resources/views/portal/layouts/modelo1/publicacoes/view.blade.php`:

```blade
<h4 class="text-uppercase txt-color-2 font-or">{{ $content->categoryContents->name }}</h4>
<i class="border-title d-block bg-color-1 mb-4"></i>

<h3 class="f1-l-3 cl2 p-b-16 p-t-33 respon2">{{ $content->title }}</h3>

<span>Publicado em</span>
<span>{{ date('d/m/Y', strtotime($content->publication_date)) }}
    às {{ date('H:i', strtotime($content->publication_date)) }}</span>

<div class="text-secondary text-content p-b-50">{!! $content->text !!}</div>

@if (count($archives) > 0 || $view_pdf != null)
    @include('portal.components.view_pdf.files-list')
@endif
@if(!isset($content->layout) || $content->layout == 1)
    <div class="col-xl-3 col-lg-3 col-md-4 col-sm-12 ml-auto pl-0">
        @include('portal.layouts.modelo1.layout.sidebar.layout')
    </div>
@endif
```

| Elemento | Condição |
|---|---|
| Nome da categoria | sempre |
| Data/hora de publicação | sempre |
| Corpo HTML | sempre |
| Anexos + PDF inline | `count($archives) > 0 || $view_pdf != null` |
| Barra lateral | `layout` vazio ou `== 1` |

## 7. Portal — exportação

Botões na partial `list` (presentes em `modelo1`, `modelo5` e `newsbit`):

```blade
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="exportarPublicacoes('xls')" title="Exportar Excel">xls</button>
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="exportarPublicacoes('pdf')" title="Exportar PDF">pdf</button>
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="exportarPublicacoes('csv')" title="Exportar CSV">csv</button>
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="exportarPublicacoes('txt')" title="Exportar TXT">txt</button>
```

E o JavaScript que dispara o download:

```js
function exportarPublicacoes(type) {
    var params = {
        type: type,
        sub_category: '{{ $category->slug }}',
        ano: $('#ano').val(),
        mes: $('#mes').val(),
        texto: $('#search').val()
    };
    window.location.href = '{{ route('publicacoes.export') }}?' + $.param(params);
}
```

Os parâmetros enviados são os mesmos da listagem (`sub_category`, `ano`,
`mes`, `texto`) mais `type`.

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

| Tela | O que aparece |
|---|---|
| `/publicacoes` | Redirecionamento automático para a primeira subcategoria |
| `/publicacoes/editais` | Menu de categorias, selos de Ano/Mês, campo de busca, lista paginada (12/página) e botões de exportação |
| `/publicacoes/editais/{slug}` | Categoria, título, data/hora, corpo, anexos, PDF inline e (opcionalmente) barra lateral |

## 9. O que o operador vê

| Elemento | Origem |
|---|---|
| Coluna "Categoria" | nome da subcategoria |
| Coluna "Data de publicação" | `publication_date` formatada `d/m/Y H:i:s` |
| Botão "Acessar publicação" | `/publicacoes/{categoria_slug}/{slug}` |
| "Link Permanente" | exibido só na edição |
| Auditoria | `activity()` em create/edit/delete |

## 10. Exportações — detalhes

| Formato | Tecnologia | Nome do arquivo |
|---|---|---|
| `xls` | `Maatwebsite\Excel` (`ContentsExport`) | `publicacoes_<cat>_<Ymd_His>.xlsx` |
| `csv` | `Maatwebsite\Excel` | `publicacoes_<cat>_<Ymd_His>.csv` |
| `txt` | `Maatwebsite\Excel` com `Excel::TSV` | `publicacoes_<cat>_<Ymd_His>.txt` |
| `pdf` | DomPDF, view `exports.contents`, papel A4 paisagem | `publicacoes_<cat>_<Ymd_His>.pdf` |

A cor do PDF vem de `configurations.key = 'cor_1'`, com fallback `#1075ad`.

As colunas exportadas (`v6/app/Exports/ContentsExport.php`) são:

| Cabeçalho | Origem |
|---|---|
| Título | `title` |
| Data de Publicação | `publication_date` (formatada `d/m/Y`) |
| Descrição | `strip_tags(stripslashes(text))` |
| Atualizado em | `updated_at ?? created_at` (formatada `d/m/Y H:i`) |
