# Provider Upload Localization Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Mostrar instrucciones y errores claros en español o inglés para todas las cargas del portal de prestadores, alineando logo y portada con el límite API de 4 MB.

**Architecture:** Los contratos de archivo permanecen en `18-upload-contracts.js`; un nuevo módulo `18-upload-errors.js` convierte errores locales, HTTP y de validación en mensajes canónicos que pasan por `providerTranslate()`. El bridge conserva la validación autoritativa previa al proxy y Blade obtiene todas las ayudas desde `provider_portal.php`.

**Tech Stack:** Laravel 13, Blade, JavaScript ES2020, Laravel Mix, Node assertions, PHPUnit.

---

### Task 1: Contratos y traducciones de carga

**Files:**
- Modify: `tests/js/provider-i18n.test.js`
- Create: `tests/js/provider-upload-errors.test.js`
- Modify: `resources/js/provider/00-i18n-validation.js`
- Modify: `resources/js/provider/18-upload-contracts.js`
- Create: `resources/js/provider/18-upload-errors.js`
- Modify: `webpack.mix.js`
- Modify: `package.json`

- [ ] **Step 1: Escribir pruebas fallidas**

Comprobar ES/EN para límite de 4 MB, formato inválido, archivo vacío, `413`, `422`, dimensiones excesivas y fallo general. Cargar `00-i18n.js`, `00-i18n-validation.js`, `01-http.js`, `02-form-errors.js`, `18-upload-contracts.js` y `18-upload-errors.js` en un contexto VM.

- [ ] **Step 2: Confirmar RED**

Run: `node tests/js/provider-i18n.test.js && node tests/js/provider-upload-errors.test.js`

Expected: FAIL porque la portada aún acepta 8 MB y no existe el normalizador de errores de carga.

- [ ] **Step 3: Implementar contratos y normalización**

Definir mensajes canónicos españoles traducibles, cambiar portada a `4 * 1024 * 1024`, separar errores de archivo vacío, tamaño y tipo, e implementar:

```javascript
function providerUploadErrorMessage(error, kind) {
    const status = Number(error?.status || 0);
    const messages = providerUploadServerErrorMessages(error?.errors);
    const known = messages.map(providerCanonicalUploadServerMessage).find(Boolean);
    if (known) return providerTranslate(known);
    if (status === 413) return providerTranslate('El archivo es demasiado grande para procesarlo.');
    if (status === 422) return providerTranslate('El archivo no cumple los requisitos indicados.');
    return providerTranslate(error instanceof ProviderHttpError
        ? 'No fue posible cargar el archivo. Intenta nuevamente.'
        : error?.message || 'No fue posible cargar el archivo. Intenta nuevamente.');
}
```

Agregar el módulo al bundle inmediatamente después de `18-upload-contracts.js` y sumar su prueba a `test:provider`.

- [ ] **Step 4: Confirmar GREEN**

Run: `node tests/js/provider-i18n.test.js && node tests/js/provider-upload-errors.test.js`

Expected: PASS en español e inglés.

### Task 2: Presentación de errores en todos los formularios

**Files:**
- Modify: `tests/js/provider-form-errors.test.js`
- Modify: `resources/js/provider/02-form-errors.js`
- Modify: `resources/js/provider/18-media-viewmodel.js`
- Modify: `resources/js/provider/18-location-media-viewmodel.js`
- Modify: `resources/js/provider/19-verifications-viewmodel.js`

- [ ] **Step 1: Escribir pruebas fallidas**

Comprobar que `evidence.0` se mapea al control `evidence[]` y que el helper de carga entrega el mensaje localizado tanto al campo como al feedback general.

- [ ] **Step 2: Confirmar RED**

Run: `node tests/js/provider-form-errors.test.js && node tests/js/provider-upload-errors.test.js`

Expected: FAIL porque los índices de evidencia no se resuelven y los handlers muestran `error.message` literalmente.

- [ ] **Step 3: Implementar presentación localizada**

Mapear `evidence.N` a `evidence`, limpiar errores al iniciar cada submit y reemplazar cada captura por:

```javascript
providerPresentUploadError(form, error, 'logo', 'logo');
providerPresentUploadError(form, error, 'image', 'image');
providerPresentUploadError(form, error, 'evidence', 'document');
```

El helper debe llamar `providerRenderFieldErrors()` y `providerFeedback()` con el mismo texto localizado.

- [ ] **Step 4: Confirmar GREEN**

Run: `npm run test:provider`

Expected: todas las pruebas del portal pasan.

### Task 3: Bridge y ayudas Blade coherentes

**Files:**
- Modify: `tests/Feature/ProviderBridgeUploadValidationTest.php`
- Modify: `tests/Feature/ProviderPortalLocalizationTest.php`
- Modify: `app/Application/Bridge/ProviderUploadPayloadResolver.php`
- Modify: `resources/lang/es/provider_portal.php`
- Modify: `resources/lang/en/provider_portal.php`
- Modify: `resources/views/provider/partials/media.blade.php`

- [ ] **Step 1: Escribir pruebas fallidas**

Enviar una portada de 4097 KB y esperar `422`; comprobar ayudas de logo/portada en 4 MB, sucursal en 8 MB y evidencias en 10 MB para `/es/mi-prestador/perfil` y `/en/mi-prestador/perfil`.

- [ ] **Step 2: Confirmar RED**

Run: `php artisan test tests/Feature/ProviderBridgeUploadValidationTest.php tests/Feature/ProviderPortalLocalizationTest.php`

Expected: FAIL porque el bridge y las ayudas de portada todavía indican 8 MB.

- [ ] **Step 3: Alinear servidor y vistas**

Cambiar `cover` a `max:4096`, actualizar `hint_cover` y agregar `hint_location` en ambos idiomas debajo del selector de imagen de sucursal.

- [ ] **Step 4: Confirmar GREEN**

Run: `php artisan test tests/Feature/ProviderBridgeUploadValidationTest.php tests/Feature/ProviderPortalLocalizationTest.php`

Expected: PASS.

### Task 4: Bundle, versión y verificación integral

**Files:**
- Modify: `public/js/provider/app.js` (generado)
- Modify: `VERSION`

- [ ] **Step 1: Compilar y ejecutar auditorías**

Run: `npm run production && npm run test:provider && php artisan architecture:audit --strict && php artisan test`

Expected: build correcto, auditoría estricta y suites sin fallos.

- [ ] **Step 2: Evaluar versión**

El cambio altera mensajes y validación visible sin romper compatibilidad. Incrementar patch `1.7.7` a `1.7.8`, salvo que el hook de versión indique una regla distinta.

- [ ] **Step 3: Verificar artefactos**

Run: `git diff --check && rg -n "hasta 8 MB|maximum 8 MB" resources/js/provider/18-upload-contracts.js resources/lang/{es,en}/provider_portal.php`

Expected: sólo las imágenes de sucursal conservan 8 MB; portada queda en 4 MB.

- [ ] **Step 4: Commit e integración**

Commit de implementación, merge fast-forward a `master`, repetición de pruebas dirigidas sobre el resultado y push a `origin/master`.

