# Temas e Cores — Views e UX

> **Slug do módulo:** `temas-e-cores` (tabela `modulos`, id 2)

## 1. Telas do CMS

| Arquivo | Função |
|---|---|
| `v6/resources/views/prefecture/configurations/temas/edit.blade.php` | Tela principal (estende `admin.layouts.app`). Cabeçalho "Configuração de Tema", inclui `form.blade.php`, botão de salvar e "Voltar". Carrega o CSS do colorpicker. |
| `v6/resources/views/prefecture/configurations/temas/form.blade.php` | Formulário: inclui `select_layout.blade.php` e renderiza os demais campos da categoria `temas` por tipo (`file`, `checkbox`, `text`) + bloco especial de `cor_cms`. |
| `v6/resources/views/prefecture/configurations/temas/select_layout.blade.php` | Grade com as 6 miniaturas de template, radio `name="layout"` e botão de edição do modelo 5. |
| `v6/resources/views/prefecture/configurations/temas/modal.blade.php` | Modal de pré-visualização do template selecionado. |
| `v6/resources/views/prefecture/configurations/modelo5/edit.blade.php` | Editor do modelo 5 (129 linhas): upload/download de CSS, formulário `save.layout` com o HTML de preview/tags e os campos `input-*`. |

## 2. Renderização por tipo de campo (`form.blade.php`)

O formulário itera `$configurations` (a coleção da categoria `temas`) e **ignora** `layout`
(tratado em `select_layout.blade.php`) e `cor_cms` (tratado separadamente):

```blade
@foreach ($configurations as $configuration)
    @if ($configuration->key != 'layout')
        @if ($configuration->key != 'cor_cms')
            @if ($configuration->key == 'background')
                {{-- upload com pré-visualização via FileReader e botão "Remover imagem" --}}
            @elseif ($configuration->key != 'background_fixed' && $configuration->key != 'background_repeat')
                {{-- file / checkbox / text conforme $configuration->type --}}
            @endif
        @else
            {{-- <select> com $temas_lte --}}
        @endif
    @endif
@endforeach
```

| Tipo | HTML gerado |
|---|---|
| `text` (cores) | `<div class="input-group colorpicker-component">` + `<span class="input-group-addon"><i></i></span>` — o `bootstrap-colorpicker` é inicializado em `edit.blade.php` com `$('.colorpicker-component').colorpicker();`. |
| `file` (`background`) | `<input type="file" accept="image/*">` + pré-visualização com `FileReader` e botão `deleteArchive(id)`. |
| `checkbox` (`background_fixed`, `background_repeat`) | `<input type="checkbox" value="1">` com `old(key, value) == '1' ? 'checked'`. **Só aparecem dentro do bloco de `background`** (estão aninhados no `if ($configuration->key == 'background')`). |
| `text` (`cor_cms`) | `<select name="cor_cms">` preenchido por `$temas_lte`. |

> **Bug de layout:** `background_fixed` e `background_repeat` são renderizados dentro do
> `@if ($configuration->key == 'background')`, e o `@elseif` seguinte exclui explicitamente
> essas duas chaves — portanto, se `background` não existir na coleção, os dois checkboxes
> **não aparecem**. Além disso, o checkbox de `background` não tem `name` no `value="0"`
> oculto (o input oculto do `background_fixed` está dentro do bloco de `background`).

## 3. Grade de templates (`select_layout.blade.php`)

```blade
@php
    $layout =  $configurations->where('key', 'layout')->first();
@endphp

<form action="{{ route('update.configurations.by.category') }}" class="form-list" method="post"
    enctype="multipart/form-data">
    {!! csrf_field() !!}
        {{-- trecho omitido no arquivo original --}}
    <input type="hidden" name="category_configurations_id" value="{{ $category->id }}">
    @if (has_access(['layouts']))
        {{-- trecho omitido no arquivo original --}}
        @foreach ($templatesPortal as $template)
            @php $check = isset($layout->value) && $layout->value == $template['key'] @endphp

            <div class="text-center template-select p-0 m-3 template-{{ $template['key'] }} @if ($check) is-checked @else not-checked @endif"
                style='cursor: pointer;width: 300px;height:310px' id="{{ $template['key'] }}">
                <img src='{{ $template['img'] }}' class="thumb-template img-size" />
                <input id="modalImage" type="hidden" name="modalImage" value="{{ $template['modal'] }}" disabled>
                <h4 class="title-template">{{ $template['value'] }}</h4>

                <input type="radio" name="{{ $layout->key }}" id="{{ $template['key'] }}"
                    class="hidden radio-templates" value="{{ $template['key'] }}"
                    @if ($check) checked @endif>
                <div class="box-actions">
                    @if ($template['key'] == 'modelo5')
                        @if (has_access('modelo-personalizavel.*'))
                            <a href="{{ route('edit.layout') }}" class="btn btn-primary" data-toggle="tooltip"
                               data-title="Editar">
                                <i class="glyphicon glyphicon-edit icon-spacer" style="color: #ffffff"></i>
                            </a>
                        @endif
                    @endif
        {{-- trecho omitido no arquivo original --}}
                </div>
            </div>
        @endforeach
    @endif
    @include('prefecture.configurations.temas.modal')
```

Imagens referenciadas (todas existentes em `v6/public/assets/images/`):

| Modelo | Miniatura | Modal |
|---|---|---|
| `modelo1` | `modelo1-min.jpg` | `modelo01-modal.jpg` |
| `modelo2` | `modelo2-min.jpg` | `modelo02-modal.jpg` |
| `modelo3` | `modelo3-min.jpg` | `modelo03-modal.jpg` |
| `modelo4` | `modelo4-min.jpg` | `modelo04-modal.jpg` |
| `modelo5` | `modelo05-min.jpg` | `modelo05-modal.jpg` |
| `modelo6` | `modelo6-min.png` | `modelo6.jpg` |

> O `name="modalImage"` é um campo **disabled**, portanto não é enviado ao servidor.

## 4. JS/Ajax

| Arquivo | Comportamento |
|---|---|
| `v6/public/assets/js/custom/utilities/helpers/select-modelo.js` | Clique na miniatura preenche `#key` e abre o modal; clique no ícone de check chama `refreshSelectedTemplate()`, que alterna as classes `is-checked`/`not-checked`, marca o radio e troca `bg-green`/`bg-red`. |
| `v6/resources/views/prefecture/configurations/temas/edit.blade.php` | Inicializa o colorpicker; `change` em `input[name='background']` lê o arquivo com `FileReader` e mostra a miniatura em `#image-holder-background`. |
| `v6/resources/views/prefecture/configurations/temas/form.blade.php` | `deleteArchive(archive_id)` — `POST` em `route('remove.arquivo.configuracao')` com `_token` e `archive_id`; em sucesso mostra "Arquivo apagado com sucesso!" e remove o botão após 1,5 s. |
| `v6/resources/views/portal/layouts/default/master.blade.php` | `tinycolor` calcula contraste entre `cor_1`, `cor_3` e `cor_4` e ajusta cores de texto/bordas. |
| `v6/resources/views/prefecture/configurations/modelo5/edit.blade.php` | Formulário de upload (`route('upload.css')`) e download (`route('download.css')`); POST `route('save.layout')` com `html`, `htmlTags` e campos `input-*`. |

## 5. Como as cores chegam ao portal

`v6/resources/views/portal/layouts/barra-privacidade/head.blade.php`:

```blade
@inject('config', 'App\Prefecture\Configuration')
@php
    $cor_1 = $config->where('key', 'cor_1')->first()->value;
    $cor_2 = $config->where('key', 'cor_2')->first()->value;
    $cor_3 = $config->where('key', 'cor_3')->first()->value;
    $cor_4 = $config->where('key', 'cor_4')->first()->value;
@endphp

<style>
    :root{
        --cor-1: {{$cor_1}};
        --cor-2: {{$cor_2}};
        --cor-3: {{$cor_3}};
        --cor-4: {{$cor_4}};
    }
```

`v6/resources/views/portal/layouts/default/master.blade.php` (linhas 7-10, 68-119, 152, 172-198)
aplica as mesmas quatro variáveis em regras `background:`/`color:` por classe e usa
`tinycolor` para contraste.

> Ambos os arquivos fazem `->first()->value` **sem** `?:` — se a chave não existir, o
> resultado é um erro fatal (`Attempt to read property on null`).

## 6. Plano de fundo no `<body>`

Idêntico nos 6 templates:
`v6/resources/views/portal/layouts/modelo1/layout/layout.blade.php` (e `modelo2`..`modelo6`):

```blade
@if (!empty($configHeader['background']))
    <style>
        body {
            background-image: url('/storage/{{ $configHeader['background'] }}');
            background-position: center top;
            background-size: 100%;
            background-repeat: {{ $configHeader['background_repeat'] === '1' ? 'repeat' : 'no-repeat' }};
            background-attachment: {{ $configHeader['background_fixed'] === '1' ? 'fixed' : 'scroll' }};"
        }
    </style>
@endif
```

`$configHeader` é injetado por `v6/app/Providers/ConfigHeaderServiceProvider.php`, que carrega
`cor_1`..`cor_4`, `background`, `background_fixed`, `background_repeat` entre outras chaves.

## 7. Skin do CMS

`v6/resources/views/vendor/adminlte/page.blade.php` (linhas 1-8):

```blade
@extends('adminlte::master')
@inject('config', 'App\Prefecture\Configuration')

@section('adminlte_css')
    <link rel="stylesheet"
          href="{{ asset('assets/vendor/adminlte/dist/css/skins/skin-' . $config->where('key', 'cor_cms')->first()->value . '.min.css') }} ">
```

- Skins disponíveis: `v6/public/assets/vendor/adminlte/dist/css/skins/`.
- O logo troca de imagem conforme o valor (`logo-cms.png` quando `black`, `logo-cms-branco.png`
  caso contrário) — linhas 58 e 66 do mesmo arquivo.
- A consulta é feita **3 vezes por render** do AdminLTE (CSS + 2 logos), sem cache.

## 8. Templates do portal (consequência da chave `layout`)

| Template | Home | Efeito do modelo |
|---|---|---|
| `modelo1` | `v6/resources/views/portal/layouts/modelo1/home/index.blade.php` | 6 notícias; bloco de slides. |
| `modelo2` | `v6/resources/views/portal/layouts/modelo2/home/index.blade.php` | 7 notícias; bloco de slides. |
| `modelo3` | `v6/resources/views/portal/layouts/modelo3/home/index.blade.php` | 10 − diferença notícias. |
| `modelo4` | `v6/resources/views/portal/layouts/modelo4/home/index.blade.php` | 3 notícias. |
| `modelo5` | `v6/resources/views/portal/layouts/modelo5/home/index.blade.php` | 8 − diferença; blocos definidos na tabela `layouts`. |
| `modelo6` | `v6/resources/views/portal/layouts/modelo6/home/index.blade.php` | 4 notícias; bloco de slides. |

`v6/app/Http/Presenters/ContentPresenter.php` (linhas ~162-215) troca as classes CSS dos
cards de notícia conforme o modelo (`preview($modelo)`).

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

- Home, listagens e páginas internas renderizadas com o template escolhido: cores aplicadas
  em botões, títulos, links e fundos de datas; plano de fundo opcional fixo/repetido.
- Se o template gravado não tiver a view `portal.layouts.{modelo}.home.index`,
  `getTemplateActived()` grava `pagina_em_manutencao = 1` e responde **404** — o portal
  inteiro fica fora do ar até a configuração ser corrigida.

## 10. Exportações afetadas

| Consumer | Cor usada | Arquivo |
|---|---|---|
| PDFs exportados | `cor_1` (fallback `#1075ad`) | `v6/app/Http/Traits/ExportsContentTrait.php:13` |
| UI do Swagger | `cor_2` | `v6/app/Http/Controllers/Swagger/SwaggerController.php:14` |
| E-mail de avaliação (ouvidoria) | `cor_1` | `v6/app/Repositories/Eloquent/Prefecture/Ratings/Envios/EnviosRepository.php:42` |

Não há exportação própria do módulo de temas.
