Ruta: GET /us/su/lau/ads/createVista: su/anuncioMétodo: SUController::ads()
$banners = Banner::with('viewedByUsers')->latest()->get();
$activeCount = $banners->where('is_active', true)->count();
La vista muestra cada banner con:
viewedByUsers)Ruta: POST /us/su/lau/ads/createMétodo: SUController::create()
Validación:
| Campo | Reglas | Descripción |
|—|—|—|
| title | required, string, max 255 | Título del banner |
| content | nullable, string | Contenido/descripción |
| type | required, in: feature, update, info, warning | Tipo de anuncio |
| image_url | nullable, string, max 255 | URL externa de imagen |
| file | nullable, image, mimes:jpg,jpeg,png,svg, max 20MB | Archivo de imagen |
| action_text | nullable, string, max 255 | Texto del botón |
| action_url | nullable, string, max 255 | URL del botón |
| is_active | required, boolean | Estado activo |
| start_date | required, date | Fecha de inicio |
| end_date | required, date, after_or_equal:start_date | Fecha de fin |
Flujo de imagen:
Si se sube archivo (file):
1. Genera nombre con Str::uuid() + extensión original
2. Guarda en storage/public/banners/{uuid}.{ext}
3. image_url = /storage/banners/{uuid}.{ext}
Si no → usa image_url del formulario
Ruta: PUT /us/su/lau/ads/update/{id}Método: SUController::update()
Misma validación (usa Banner::getAvailableTypes() para validar el tipo). Encuentra por ID y actualiza.
Ruta: DELETE /us/su/lau/ads/{id}Método: SUController::delete()
Busca por ID y elimina. Las relaciones pivote (banner_user_views) se eliminan automáticamente por cascada.
Ruta: POST /us/su/lau/ads/{id}/reset-viewsMétodo: SUController::resetViews()
$banner = Banner::findOrFail($id);
$banner->viewedByUsers()->detach();