# Agenda de Eventos — Rotas e Controllers

> Fontes: `v6/routes/basepro.php` (CMS), `v6/routes/web.php` (Portal),
> `v6/routes/breadcrumbs.php` (breadcrumbs), `v6/app/Http/Kernel.php` (middleware).

---

## 1. CMS — `/cms/agenda-evento` (Prefecture)

Prefixo aplicado pelo grupo `Route::group(['prefix' => 'cms', 'before' => 'csrf'], ...)`
em `v6/routes/basepro.php:34`. Todo o grupo é servido com o middleware `web`
(sessão + `VerifyCsrfToken`).

| Método | URI | Nome (`->name()`) | Controller@action | Middleware |
|---|---|---|---|---|
| GET | `/cms/agenda-evento` | `agenda-evento.index` | `Prefecture\CalendarEvent\CalendarEventController@index` | `check.logged` |
| GET | `/cms/agenda-evento/create` | `agenda-evento.create` | `...CalendarEventController@create` | `check.logged` |
| POST | `/cms/agenda-evento` | `agenda-evento.store` | `...CalendarEventController@store` | `check.logged` |
| GET | `/cms/agenda-evento/{agenda_evento}` | `agenda-evento.show` | `...CalendarEventController@show` | `check.logged` |
| GET | `/cms/agenda-evento/{agenda_evento}/edit` | `agenda-evento.edit` | `...CalendarEventController@edit` | `check.logged` |
| PUT/PATCH | `/cms/agenda-evento/{agenda_evento}` | `agenda-evento.update` | `...CalendarEventController@update` | `check.logged` |
| DELETE | `/cms/agenda-evento/{agenda_evento}` | `agenda-evento.destroy` | `...CalendarEventController@destroy` | `check.logged` |

Fonte: `v6/routes/basepro.php:202`
(`Route::resource('agenda-evento', 'Prefecture\CalendarEvent\CalendarEventController')->middleware('check.logged')`).

| Método | URI | Nome | Controller@action | Middleware |
|---|---|---|---|---|
| GET | `/cms/agenda-evento/editar/{id}` | `editar-agenda` | `...CalendarEventController@edit` | (resource do grupo) |

Fonte: `v6/routes/basepro.php:228`. É a rota usada no redirecionamento após salvar
com galeria ativada (`route("editar-agenda", [$calendarEvent->id . '#galeria'])`).

> A rota `agenda-evento.show` **não tem método correspondente**: `CalendarEventController`
> não implementa `show()`. O acesso a `/cms/agenda-evento/{id}` resulta em erro 500
> ("method does not exist"). Ver `08-GAPS-E-DIVIDAS.md`.

### 1.1 Rotas auxiliares do CMS

| Método | URI | Nome | Controller@action | Middleware |
|---|---|---|---|---|
| POST | `/cms/ajax-upload-files-calendar-event` | `ajax.upload.files.calendar.event` | `...CalendarEventController@ajaxUploadFiles` | `csrf` (grupo `cms`) |
| POST | `/cms/agenda-evento/delete-por-lote` | `ajax.calendar-event.deleteByLote` | `...CalendarEventController@deleteByLote` | `csrf` |
| GET | `/cms/datatable/agenda_evento` | `agenda_evento` | `Prefecture\DatatableController@get_agenda_eventos` | `csrf` |

Fontes: `v6/routes/basepro.php:124`, `:156`, `:418`.

### 1.2 Rotas de galeria (genéricas, usadas pela aba Galeria do evento)

Grupo `Route::group(['prefix' => 'galeria', 'as' => 'galeria.'], ...)` em
`v6/routes/basepro.php:384-390`:

| Método | URI | Controller@action | Uso pela agenda |
|---|---|---|---|
| POST | `/cms/galeria` | `Prefecture\ArchiveController@saveArchivesFromGalleryOrDriver` | Upload múltiplo (com `table=calendar_event` e `id=<evento>`) |
| GET | `/cms/galeria/{column?}/{id?}` | `...@getArchivesFromGalleryOrDriver` | Lista as imagens (`column=calendar_events_id`) |
| POST | `/cms/galeria/delete/{id}` | `...@deleteArchives` | Exclusão de imagem da galeria |
| PUT | `/cms/galeria/update-title/{id}` | `...@updateArchiveTitle` | Renomear |
| POST | `/cms/galeria/update-order` | `...@updateArchivesOrder` | Reordenar |

### 1.3 Categorias (CMS)

`v6/routes/basepro.php:203`:
`Route::resource('categoria-agenda-evento', 'Prefecture\CalendarEvent\CategoryCalendarEventController')->middleware('check.logged')`

| Método | URI | Nome | Controller@action | Middleware |
|---|---|---|---|---|
| GET | `/cms/categoria-agenda-evento` | `categoria-agenda-evento.index` | `...CategoryCalendarEventController@index` | `check.logged` |
| GET | `/cms/categoria-agenda-evento/create` | `categoria-agenda-evento.create` | `...@create` | `check.logged` |
| POST | `/cms/categoria-agenda-evento` | `categoria-agenda-evento.store` | `...@store` | `check.logged` |
| GET | `/cms/categoria-agenda-evento/{categoria_calendar_event}` | `categoria-agenda-evento.show` | `...@show` | `check.logged` |
| GET | `/cms/categoria-agenda-evento/{categoria_calendar_event}/edit` | `categoria-agenda-evento.edit` | `...@edit` | `check.logged` |
| PUT/PATCH | `/cms/categoria-agenda-evento/{categoria_calendar_event}` | `categoria-agenda-evento.update` | `...@update` | `check.logged` |
| DELETE | `/cms/categoria-agenda-evento/{categoria_calendar_event}` | `categoria-agenda-evento.destroy` | `...@destroy` | `check.logged` |

> `CategoryCalendarEventController` **não implementa `create()` nem `show()`**: a tela de
> listagem+cadastro é servida por `index()` (view `prefecture.category-calendar-events.create`),
> e a rota `create` resultará em erro. Ver `08-GAPS-E-DIVIDAS.md`.

---

## 2. Portal — público

`v6/routes/web.php:26-29`, dentro do grupo
`Route::middleware(['check.site.manutention'])->group(...)` (`v6/routes/web.php:6`).

| Método | URI | Nome | Controller@action | Middleware |
|---|---|---|---|---|
| GET | `/agenda` | `agenda` | `Portal\CalendarEventController@index` | `check.site.manutention` (+ `web`) |
| GET | `/agenda-eventos` | `agenda-eventos` | `Portal\CalendarEventController@index` | idem |
| GET | `/agenda-eventos/{category}` | `agenda-eventos-category` | `Portal\CalendarEventController@categoryIndex` | idem |
| GET | `/agenda-eventos/{category}/{slug}` | `agenda-eventos.show` | `Portal\CalendarEventController@show` | idem |

- `/agenda` é **alias** de `/agenda-eventos` (rota nova na v6; ver `08-GAPS-E-DIVIDAS.md`).
- `/agenda-eventos/{category}` recebe o **slug** da categoria (não o id).
- `/agenda-eventos/{category}/{slug}` recebe o slug do **evento**; o parâmetro `{category}`
  é ignorado pelo controller (o slug do evento já é único na prática).

---

## 3. Breadcrumbs

`v6/routes/breadcrumbs.php:273-284`:

| Nome | Hierarquia | Url |
|---|---|---|
| `calendar-events` | Home > Agenda de Eventos | `route('agenda-eventos')` |
| `category-calendar-events` | `calendar-events` > Categoria | `route('agenda-eventos-category', [$category->slug])` |
| `calendar-event` | `category-calendar-events` > Evento | — (sem link) |

As views do portal renderizam o breadcrumb com
`Breadcrumbs::view("portal.layouts.$modelo.layout.breadcrumb", ...)`, dinâmico conforme o
template ativo.

---

## 4. Form Requests / validações

### 4.1 `CalendarEventRequest` (`v6/app/Http/Requests/CalendarEventRequest.php`)

| Campo | Regra | Efeito |
|---|---|---|
| `category_calendar_events_id` | `SelectRule('Categoria')` | Reprova `'0'` (placeholder do select) |
| `title` | `required|max:120` | Título obrigatório |
| `initial_date` | `required` | Data/hora inicial obrigatória |
| `final_date` | `nullable` | Data/hora de encerramento opcional (na v5 era `required`) |
| `source` | `max:120` | Fonte opcional |
| `local` | `max:120` | Local opcional |
| `text` | `required` | Descrição HTML obrigatória |
| `archive_highlight` | `max:20000|mimes:jpg,jpeg,png,gif,webp` | Imagem de destaque (até ~5 MB, só imagens) |

Mensagens em português no método `messages()`. `authorize()` retorna `true`
(sem verificação de permissão no request — a autorização é feita na view por
`has_access`).

> Observação: a regra `mimes:` combinada com `max:20000` (KB) limita a 5 MB, mas a
> mensagem diz "menor que 5MB" enquanto a regra `max` está em KB — coerente, porém
> implícito.

### 4.2 `CategoryCalendarEventRequest` (`v6/app/Http/Requests/CategoryCalendarEventRequest.php`)

| Campo | Regra | Observação |
|---|---|---|
| `name` | `nullable|max:190` | Na v5 era `required|max:190`; na v6 o nome passou a ser opcional |

### 4.3 Validações fora do Form Request

- O controller de eventos **não** valida `secretarias_id`/`orgaos_id`: valores `'0'` são
  convertidos em `null` pelo repository
  (`v6/app/Repositories/Eloquent/Prefecture/CalendarEvent/CalendarEventRepositoryDefaultImpl.php:40-41`).
- A rota `deleteByLote` usa `Request` cru: o array `toDelete` **não é validado**; o
  repository faz `whereIn('id', $array)->delete()`.

---

## 5. API Resources / Presenters

**Não existem** API Resources ou Presenters para este módulo. Todos os controllers
devolvem models Eloquent ou arrays associativos montados à mão:

| Endpoint | Formato da resposta |
|---|---|
| `GET /cms/datatable/agenda_evento` | JSON do Yajra DataTables (colunas da view + `edit`, `delete`, `active`, `inactivate` injetados por `struct_views`) |
| `DELETE /cms/agenda-evento/{id}` | `{"success": "Evento deletado com sucesso."}` (200) ou `{"erro": "..."}` (500) |
| `POST /cms/agenda-evento/delete-por-lote` | `{"success": "Eventos deletados com sucesso."}` (200) ou `{"erro": "..."}` (500) |
| `POST /cms/ajax-upload-files-calendar-event` | **Sem retorno** (o método não retorna nada em nenhum caminho) |

---

## 6. Autorização e permissões

| Recurso | Verificação |
|---|---|
| Acesso às telas do CMS | `check.logged` (`v6/app/Http/Middleware/CheckLogged.php`): exige `Sentinel::check()`, senão redireciona para `dashboard.index` |
| Botões na listagem de eventos | `has_access(['agenda-evento.create'])`, `has_access(['agenda-evento.delete'])` (`v6/app/Library/Helper/appHelpers.php:22-42`) |
| Botões na tela de categorias | `has_access(['agenda-evento.edit'])`, `has_access(['agenda-evento.delete'])` (reaproveita as permissões do módulo de eventos) |
| Colunas de ação da DataTable | `struct_views($data, 'agenda-evento')` → `agenda-evento.edit`, `agenda-evento.delete`, `agenda-evento.restore`, `agenda-evento.inactivate` |
| Permissões do papel | `v6/database/seeds/RolesTableSeeder.php:28` define `agenda-evento.index/.create/.edit/.delete/.inactivate/.restore/.show` para o papel "Administrador"; `super-admin` passa por atalho em `has_access` |

O portal **não exige autenticação** para a agenda.

> `check.route.permission` (`v6/app/Http/Middleware/CheckRoutePermission.php`) existe no
> Kernel, mas **não** é aplicado às rotas de recurso da agenda: a proteção efetiva é
> apenas `check.logged` + os `has_access` das views.

---

## 7. Consumidores externos das rotas

| Consumidor | Uso |
|---|---|
| `v6/resources/views/prefecture/calendar-events/index.blade.php` | `route('agenda-evento.create')`, `route('categoria-agenda-evento.index')`, `route('ajax.calendar-event.deleteByLote')` |
| `v6/resources/views/prefecture/calendar-events/form.blade.php` | `route('categoria-agenda-evento.index')` |
| `v6/public/assets/js/custom/contents/agenda-eventos/datatable.js` | `runDatatables('agenda_evento', ...)` -> `GET /cms/datatable/agenda_evento`; link público `/agenda-eventos/{categoria_slug}/{slug}` |
| `v6/resources/views/portal/layouts/calendar-events/index.blade.php` | `route('agenda-eventos')`, `route('agenda-eventos-category', [$categorie->slug])`, `route('agenda-eventos.show', [categoria, evento])` |
