# Temas e Cores — Arquitetura

> **Slug do módulo:** `temas-e-cores` (tabela `modulos`, id 2)
> **Natureza:** CMS (painel administrativo) + Portal (público)

## 1. Visão geral

O módulo **não possui controller, model, migration ou tabela própria**. Ele é uma *fatia
funcional* de um módulo genérico de configurações. A "identidade" do módulo vem de três
eixos:

1. **Categoria de configuração** — `category_configurations.slug = 'temas'` (id 3).
2. **Recursos do CMS** — `resources.slug = 'tema-do-portal'` e `resources.slug = 'template-do-portal'`,
   ambos com `modulo_id = 2`.
3. **Rota** — `edit.configuracoes.by.category` com o parâmetro `slug = 'temas'`.

A única parte com estrutura própria é o **Modelo 5 (Personalizável)**: tabela `layouts` +
`v6/app/Http/Controllers/Prefecture/LayoutController.php`.

```
CMS (operador)                          Portal (cidadão)
───────────                             ───────────────
GET /cms/configuracoes/editar/temas
  → ConfigurationController@editByCategory
      → getConfiguration('temas')  ──┐
  → view prefecture.configurations.temas.edit
      → form.blade.php
          → select_layout.blade.php   GET /
          → modal.blade.php             → PortalController@index
POST /cms/update/configuration           → getTemplateActived()
  → ConfigurationController@updateByCategory   → Configuration::where('key','layout')
      → ConfigurationRequest::rules()      → view portal.layouts.{modelo}.home.index
      → Configuration::save()                   → head.blade.php (--cor-1..4)
GET /cms/editar/modelo-personalizavel    → layout.blade.php (background-image)
  → LayoutController@edit
      → Layout (tabela `layouts`)
```

## 2. Camadas e classes envolvidas

| Classe / arquivo | Namespace | Papel no módulo |
|---|---|---|
| `v6/app/Http/Controllers/Prefecture/ConfigurationController.php` | `App\Http\Controllers\Prefecture` | Controller único dos 4 módulos de configuração. `editByCategory()` monta as telas; `updateByCategory()` grava **todas** as categorias. |
| `v6/app/Http/Controllers/Prefecture/LayoutController.php` | `App\Http\Controllers\Prefecture` | Controller do modelo 5: edita HTML de preview/tags, estilos, ordem e CSS customizado. |
| `v6/app/Http/Model/Prefecture/Configuration.php` | `App\Prefecture` | Model da tabela `configurations` (soft delete). |
| `v6/app/Http/Model/Prefecture/CategoryConfiguration.php` | `App\Http\Model\Prefecture` | Model da tabela `category_configurations`. |
| `v6/app/Http/Model/Prefecture/Layout.php` | `App\Http\Model\Prefecture` | Model da tabela `layouts` (modelo 5). Usa `LayoutPresenter`. |
| `v6/app/Http/Presenters/LayoutPresenter.php` | `App\Http\Presenters` | Apresentador do model `Layout`. |
| `v6/app/Http/Requests/ConfigurationRequest.php` | `App\Http\Requests` | Validação dinâmica por chave de configuração. |
| `v6/app/Http/Traits/GetInformationsPrefectureTrait.php` | `App\Http\Traits` | `getConfiguration($reference)` — filtra `configurations` pela categoria. |
| `v6/app/Http/Traits/FileTrait.php` | `App\Http\Traits` | `getFileName()` — nome único do upload de plano de fundo. |
| `v6/app/Http/Controllers/Portal/HelperController.php` | `App\Http\Controllers\Portal` | `getColors()` — endpoint público JSON com as 4 cores. |
| `v6/app/Http/Controllers/Portal/PortalController.php` | `App\Http\Controllers\Portal` | Resolve o template ativo e renderiza a home. |
| `v6/app/Http/Controllers/Admin/Controller.php` | `App\Http\Controllers\Admin` | `getTemplateActived()` — valida que a view do template existe. |
| `v6/app/Helpers/functions.php` | global | `getActualLayout()` (linha 1130) e `getNewsQuantity($layout)`. |
| `v6/app/Http/Presenters/ContentPresenter.php` | `App\Http\Presenters` | Troca classes CSS dos cards de notícia conforme o modelo. |
| `v6/app/Http/Traits/ExportsContentTrait.php` | `App\Http\Traits` | Usa `cor_1` na cor dos PDFs exportados. |
| `v6/app/Repositories/Eloquent/Prefecture/Ratings/Envios/EnviosRepository.php` | — | Usa `cor_1` no e-mail de avaliação. |
| `v6/app/Http/Controllers/Swagger/SwaggerController.php` | — | Usa `cor_2` na UI do Swagger. |
| `v6/app/Providers/ConfigHeaderServiceProvider.php` | `App\Providers` | Injeta `$configHeader` (contém `background`, `cor_1`..`cor_4`) nas views do portal. |

## 3. Fluxo de leitura da tela de temas

```
GET /cms/configuracoes/editar/temas
  middleware: check.logged
    → ConfigurationController@editByCategory('temas')
        reference = 'temas'; acess = 'tema-do-portal'
        → getConfiguration('temas')            [trait GetInformationsPrefectureTrait]
        → CategoryConfiguration::where('slug','temas')->first()
        → DB::table('states')->get()           [não usado por 'temas']
        → has_access(['tema-do-portal.edit'])  [false → flash + redirect dashboard.index]
        → case 'temas': monta $temas_lte e $templatesPortal
        → view prefecture.configurations.temas.edit
            → form.blade.php
                → select_layout.blade.php  (grade de 6 modelos)
                → modal.blade.php          (pré-visualização)
            → campos de cor / upload / checkbox
```

## 4. Fluxo de gravação

```
POST /cms/update/configuration   (rota update.configurations.by.category)
  → ConfigurationRequest::rules()
        → 1 query em `configurations` por CADA campo enviado (N+1)
        → regras: required|max:50|min:3 para cor_1..cor_4
  → ConfigurationController@updateByCategory()
        → $category = CategoryConfiguration::find(category_configurations_id)
        → $dataForm = $request->except('_token','category_configurations_id','display')
        → se a 1ª chave enviada for 'layout': valida contra
          ['modelo1'..'modelo6'] → senão flash de erro + redirect back
        → foreach ($dataForm as $key => $value):
              Configuration::where('key',$key)->first()
              se hasFile($key): Intervention resize + salva em
                storage/app/public/configuracoes/<nome>
                (background NÃO é redimensionado)
              senão: $config->value = $value
              → activity()->log('Edição de configuração')
        → flash('Configurações salvas com sucesso')
        → redirect()->route('edit.configuracoes.by.category', 'temas')
```

## 5. Consumo no portal

| Ponto de consumo | Arquivo | Uso |
|---|---|---|
| Variáveis CSS | `v6/resources/views/portal/layouts/barra-privacidade/head.blade.php` | `:root { --cor-1..--cor-4 }` + classes `.bg-color-1..4`. |
| Estilos do portal | `v6/resources/views/portal/layouts/default/master.blade.php` | `background:`/`color:` por classe e contraste com `tinycolor`. |
| Plano de fundo | `v6/resources/views/portal/layouts/modelo{1..6}/layout/layout.blade.php` | `background-image: url('/storage/{{ $configHeader['background'] }}')`, `background-repeat`, `background-attachment`. |
| Skin do CMS | `v6/resources/views/vendor/adminlte/page.blade.php:5-7,58,66` | `assets/vendor/adminlte/dist/css/skins/skin-{$cor_cms}.min.css`; logo troca entre `logo-cms.png` e `logo-cms-branco.png` quando o valor é `black`. |
| Quantidade de notícias | `v6/app/Helpers/functions.php` (switch por `$layout`) | modelo1=6, modelo2=7, modelo3=10−diferença, modelo4=3, modelo5=8−diferença, modelo6=4. |
| Slides da home | `v6/app/Http/Controllers/Portal/PortalController.php:90-92` | limite 6 (7 no modelo2); modelos 1, 2 e 6 compartilham o bloco de slides. |
| Classes dos cards | `v6/app/Http/Presenters/ContentPresenter.php:162-215` | `preview($modelo)` troca o CSS por modelo. |
| Endpoint público | `v6/app/Http/Controllers/Portal/HelperController.php:10-13` | `GET /getColors` → JSON `[{key,value}]` de `cor_1..cor_4`. |

## 6. Dependências externas

| Pacote / asset | Uso |
|---|---|
| `intervention/image` | Redimensionamento do upload de `background` e de demais arquivos de configuração (exceto `background`). |
| `bootstrap-colorpicker` (`v6/public/assets/plugins/colorpicker-2.5.2/`) | Seletor de cor no formulário do CMS. |
| `tinycolor` (`v6/public/assets/plugins/tinycolor/tinycolor.js`) | Ajuste de contraste no JS do portal. |
| `laracasts/presenter` (`PresentableTrait`) | `LayoutPresenter` no model `Layout`. |
| `cartalyst/sentinel` | `has_access()` / `Sentinel::getUser()` nas permissões e no log de atividade. |
| `spatie/laravel-activitylog` (via `activity()`) | Log de "Edição de configuração" e "Acessou edição de configuração de temas". |
| AdminLTE 1.22 | Skins em `v6/public/assets/vendor/adminlte/dist/css/skins/`. |
