# Agenda de Eventos — Resumo Executivo

> **Versão analisada:** `v6` (o módulo existe, com pequenas diferenças, também na `v5`)
> **Slug do módulo:** `agenda-de-eventos` (tabela `modulos`, id `39`, nome "Agenda de Eventos")
> **Natureza:** Ambos (CMS para publicação + Portal público para consulta)
> **Estado:** migrado v5 -> v6 (módulo praticamente idêntico; ver `08-GAPS-E-DIVIDAS.md`)

---

## 1. Objetivo

A Agenda de Eventos é o módulo que publica a **programação de eventos da prefeitura**
(shows, conferências, Elections, narrações, atividades de-culture etc.) no portal público.
Cada evento pertence a **uma categoria** (ex.: "Cultura", "Educação"), possui período
(data/hora inicial e final), local, texto descritivo em HTML (Summernote), imagem de destaque
opcional e uma galeria de fotos opcional. O cidadão consulta a agenda, filtra por categoria
e abre o detalhe de cada evento; o operador do CMS cadastra, publica, edita e exclui
eventos e categorias.

## 2. Efeito / Impacto

| Faixa | Efeito |
|---|---|
| Cidadão | Vê a programação de eventos do município, filtrável por categoria, com imagem, datas, local, descrição e galeria de fotos. |
| Prefeitura (CMS) | Publica eventos com controle de "rascunho/publicado", upload de imagem de destaque e galeria de fotos, vínculo com secretaria/órgão e categoria. |
| Transparência e legalidade | A agenda deixa de existir apenas em folders de papel: passa a ter registro com autor, data de criação e log de auditoria (`activity()`), e publicação individual por evento. |
| Operação técnica | Depende de tabelas legadas (`archives` compartilhada), de uma **view SQL** (`agenda_de_eventos`) e de um par de rotas "órfãs" (`ajax-upload-files-calendar-event`, `/agenda`) que sobrevivem da v5. |

## 3. Comportamento

- Um evento é **publicado** quando `status = true`; o portal só lista eventos com
  `status = 1` (`v6/app/Http/Controllers/Portal/CalendarEventController.php:28`).
- O portal pagina **12 eventos por página** (`paginate(12)`), sem ordenação explícita.
- O filtro por categoria usa o **slug** da categoria: `/agenda-eventos/{category}`.
- O detalhe usa `{category}/{slug}`; o `slug` do evento é gerado a partir do título
  (máx. 50 caracteres) e desambiguado com sufixo `-N` quando há colisão
  (`v6/app/Repositories/Eloquent/Prefecture/CalendarEvent/CalendarEventRepositoryDefaultImpl.php:21-24`).
- Categoria e evento usam **soft delete** (`deleted_at`); registros excluídos somem de
  listagens e do portal, mas permanecem no banco.
- A **imagem de destaque** é gravada na tabela compartilhada `archives` com
  `calendar_events_id` preenchido e `highlight = 1`; a **galeria** usa
  `highlight = null`.
- Se a galeria for ativada no evento, o CMS redireciona para
  `editar-agenda` com âncora `#galeria` (`v6/app/Http/Controllers/Prefecture/CalendarEvent/CalendarEventController.php:112-116`).
- A exclusão em lote recebe o array `toDelete` e remove os eventos em uma transação
  (`v6/app/Http/Controllers/Prefecture/CalendarEvent/CalendarEventController.php:212-231`).
- Cada acesso ao CMS grava log de auditoria via `activity()` (listar, criar, editar,
  excluir, cadastrar arquivo).

## 4. Como o Usuário Interage

**Operador (CMS, `/cms/agenda-evento`)**:

1. Tela "Lista de Agenda de Eventos" — DataTable server-side alimentado pela view
   `agenda_de_eventos`; colunas ID, Título, Status, Data Inicial, Data Final, Categoria,
   Ações. Botões "Cadastrar Evento", "Categorias da Agenda de Eventos" e exclusão em lote.
2. Formulário de cadastro/edição — categoria (obrigatória), secretaria e órgão (opcionais),
   título, data/hora inicial, data/hora de encerramento, local, fonte, imagem principal,
   texto (Summernote), "Ativar Galeria" e "Publicar".
3. Aba "Galeria" — upload múltiplo de imagens via `POST /cms/galeria` (endpoint genérico
   de arquivos) com a coluna `calendar_events_id`; a tela recarrega a galeria por
   `GET /cms/galeria/calendar_events_id/{id}`.
4. Tela de categorias — formulário de nome + listagem com editar/excluir.

**Cidadão (Portal)**:

- `/agenda-eventos` — lista em grade (3 colunas) com imagem, data, título e nome da categoria;
  barra de botões "Todas Categorias" + uma aba por categoria; paginação.
- `/agenda-eventos/{categoria}` — mesma grade filtrada pela categoria.
- `/agenda-eventos/{categoria}/{slug}` — detalhe: título, período completo
  ("Data do evento: dd/mm/yyyy às hh:mm até dd/mm/yyyy às hh:mm"), local, compartilhamento,
  imagem de destaque ampliada, texto em HTML e galeria (lightgallery).

## 5. Detalhes e Particularidades Técnicas

- **Camadas**: `Route` -> `Middleware` (`check.logged` no CMS) -> `Controller`
  (`Prefecture\CalendarEvent\*` / `Portal\CalendarEventController`) -> `FormRequest`
  (`CalendarEventRequest`, `CategoryCalendarEventRequest`) -> `Repository`
  (`CalendarEventRepositoryDefaultImpl`) -> `Model` (`CalendarEvent`, `CategoryCalendarEvent`)
  -> tabelas `calendar_events`, `category_calendar_events`, `archives`.
- O CMS **não usa API Resource nem Presenter**: as views Blade recebem models Eloquent crus.
- O portal **acessa os models diretamente no controller** (sem repository), exceto a
  listagem do CMS, que usa `DB::table('agenda_de_eventos')` sobre uma **view SQL**.
- Dependências de terceiros: `cartalyst/sentinel` (auth/permissões), `yajra/laravel-datatables`
  (listagem), Summernote (texto), `jquery-upload-files` (upload da galeria), lightgallery
  (galeria do portal), Intervention Image via `FileTrait::compress` (miniaturas).
- **Acoplamento forte com `archives`**: a tabela é polimórfica manual (uma coluna FK por
  módulo: `contents_id`, `static_pages_id`, `biddings_id`, `calendar_events_id`, ...).

## 6. Estrutura de Dados

| Tabela | Papel | Chave |
|---|---|---|
| `calendar_events` | Eventos da agenda | `id` (PK), `category_calendar_events_id` (FK), `secretarias_id`/`orgaos_id` (FK `contents`), `slug` |
| `category_calendar_events` | Categorias da agenda | `id` (PK), `slug` |
| `archives` | Arquivos/imagens (destaque e galeria) | `id` (PK), `calendar_events_id` (FK) |
| `agenda_de_eventos` (**view SQL**) | Listagem do CMS já formatada | `value`, `titulo`, `status`, `data_inicial`, `data_final`, `categoria`, `categoria_slug`, `id`, `galeria`, `slug` |

Migrations: `v6/database/migrations/2022_01_06_105757_create_category_calendar_events_table.php`,
`v6/database/migrations/2022_01_07_101548_create_calendar_events_table.php`,
`v6/database/migrations/2022_01_07_111645_add_calendar_event_id_to_archives.php`,
`v6/database/migrations/2023_05_26_103328_add_secretarias_to_calendar_events.php`,
`v6/database/migrations/2023_05_26_110237_add_orgaos_to_calendar_events.php`.

## 7. Como Testar

1. **CMS — cadastro**: `/cms/agenda-evento/create` -> salvar com categoria, título, data
   inicial e texto -> conferir na listagem (CMS) que a linha aparece com status "Publicado".
2. **CMS — rascunho**: desmarcar "Publicar" -> o evento **não** aparece no portal.
3. **Portal — filtro**: `/agenda-eventos` -> clicar numa categoria -> a lista muda e o
   breadcrumb mostra a categoria.
4. **Portal — detalhe**: abrir um evento -> conferir período, local, imagem e galeria.
5. **CMS — exclusão em lote**: selecionar 2+ linhas -> "Excluir selecionados" -> os
   eventos somem da listagem e do portal.
6. **CMS — categorias**: criar categoria com nome repetido -> o slug deve ganhar sufixo `-N`.
7. **Validação**: salvar sem título ou sem categoria -> mensagem de erro em português.

## 8. Migração para Laravel Moderno

Reescrever com Eloquent enxuto (casts `datetime`/`boolean`), `FormRequest` com regras
explícitas (`final_date`nullable, categoria `exists`), `Policy` por permissão Sentinel
transladada para Gates, `enum` para o tipo de arquivo, `Storage` para o upload (hoje o
código grava direto em `storage/app/public/...`), API Resource JSON para o portal
(hoje inexistente) e testes Pest/PHPUnit de feature cobrindo os fluxos da seção 7.
Atenção: a **view SQL `agenda_de_eventos`** precisa ser reproduzida (query builder ou
`CalendarEvent::query()->with('category')`), e a **ordem** da listagem pública deve ser
definida explicitamente (hoje é indeterminada).

## 9. Resumo Geral

A Agenda de Eventos é um módulo CRUD simples e antigo (código praticamente idêntico na
v5 e na v6) que publica a programação de eventos da prefeitura. O CMS cadastra o evento
com categoria, secretaria/órgão, período, local, texto HTML, imagem de destaque e galeria
de fotos; o portal público lista 12 eventos por página, filtra por categoria e mostra o
detalhe com galeria de imagens. Os arquivos (destaque e galeria) moram na tabela
polimórfica `archives`, e a listagem do CMS lê uma view SQL (`agenda_de_eventos`) em vez
de Eloquent. Os principais riscos para a reconstrução são o acoplamento com `archives`,
a view SQL, a ausência de ordenação na listagem pública, a rota `show` do resource sem
método correspondente e a rota de upload `ajax-upload-files-calendar-event` que ficou
sem uso pelo fluxo atual de galeria.

---

## Índice do dossiê

| Arquivo | Conteúdo |
|---|---|
| `00-RESUMO.md` | Este documento |
| `01-ARQUITETURA.md` | Camadas, classes e o diagrama de fluxo |
| `02-MODELAGEM.md` | Estrutura de dados detalhada |
| `03-ROTAS-E-CONTROLADORES.md` | Rotas, controllers, requests, resources |
| `04-VIEWS-E-UX.md` | Telas, componentes, JS, assets |
| `05-REGRAS-E-PORTABILIDADE.md` | Particularidades e armadilhas |
| `06-MIGRACAO-MODERNA.md` | Plano de reconstrução em Laravel moderno |
| `07-TESTES.md` | Estratégia e casos de teste |
| `08-GAPS-E-DIVIDAS.md` | Pendências, riscos, comparativo v5 vs v6 |
