# Tasks: Corrección de Bugs de Rendimiento y Deuda Técnica Frontend

**Feature**: `010-correccion-bugs-rendimiento-frontend`
**Plan**: `plan.md`
**Total de tareas**: 26

> Formato: `- [ ] TXXX [P?] [USX] Descripción — archivo exacto`

---

## FASE 1 — Memory Leaks & Re-renders (US1, US3) 🟢 Riesgo Bajo

### US3 — Layout no acumula event listeners entre navegaciones

- [ ] T001 [P1] [US3] Añadir `[]` como segundo argumento del `useEffect` del overlay en `Sidebar.tsx` — `resources/js/Layouts/Sidebar.tsx`
- [ ] T002 [P1] [US3] Añadir handler tipado con `const handler` y retornar `removeEventListener` como cleanup — `resources/js/Layouts/Sidebar.tsx`
- [ ] T003 [P1] [US3] Añadir `return () => window.removeEventListener("resize", resizeSidebarMenu, true)` en el `useEffect` de resize — `resources/js/Layouts/VerticalLayouts/index.tsx`

### US1 — Formulario no congela la UI al escribir

- [ ] T004 [P1] [US1] Quitar `data` del array de dependencias del `useEffect` de sincronización de cliente — `resources/js/Pages/Eneon/Contratos/UniClienteUniPunto/hooks/useContratoUniClienteUniPunto.ts`
- [ ] T005 [P1] [US1] Eliminar la guarda condicional `if (data.documento_fiscal !== ...)` ya innecesaria — `resources/js/Pages/Eneon/Contratos/UniClienteUniPunto/hooks/useContratoUniClienteUniPunto.ts`
- [ ] T006 [P1] [US1] Simplificar el cuerpo del efecto para usar `setData(prev => ({...prev, ...}))` sin condición — `resources/js/Pages/Eneon/Contratos/UniClienteUniPunto/hooks/useContratoUniClienteUniPunto.ts`

---

## FASE 2 — Race Condition CUPS (US5) 🟢 Riesgo Bajo

- [ ] T007 [P2] [US5] Crear `AbortController` en el `useEffect` de carga de CUPS eléctricos y retornar `controller.abort()` como cleanup — `resources/js/Pages/Eneon/Contratos/UniClienteUniPunto/Contrato.tsx`
- [ ] T008 [P2] [US5] Crear `AbortController` en el `useEffect` de carga de CUPS gas y retornar `controller.abort()` como cleanup — `resources/js/Pages/Eneon/Contratos/UniClienteUniPunto/Contrato.tsx`
- [ ] T009 [P2] [US5] Pasar `signal` del `AbortController` a `axios` en `fetchCupsElectricosIfNeeded` — `resources/js/Pages/Eneon/Contratos/UniClienteUniPunto/Contrato.tsx`
- [ ] T010 [P2] [US5] Pasar `signal` del `AbortController` a `axios` en `fetchCupsGasIfNeeded` — `resources/js/Pages/Eneon/Contratos/UniClienteUniPunto/Contrato.tsx`
- [ ] T011 [P2] [US5] Silenciar errores `AbortError` en los catch de ambas funciones de fetch — `resources/js/Pages/Eneon/Contratos/UniClienteUniPunto/Contrato.tsx`

---

## FASE 3 — Console.log silenciados en producción (US6) 🟢 Riesgo Bajo

- [ ] T012 [P3] [US6] Envolver los 5 `console.log` de diagnóstico con `if (import.meta.env.DEV)` — `resources/js/services/dataService.ts` (líneas 54, 128, 249, 250, 251)
- [ ] T013 [P3] [US6] Envolver el `console.log` de la línea 244 con guard de entorno — `resources/js/Pages/Eneon/Contratos/UniClienteUniPunto/hooks/useCupsElectrico.ts`
- [ ] T014 [P3] [US6] Envolver el `console.log` de la línea 231 con guard de entorno — `resources/js/Pages/Eneon/Contratos/UniClienteUniPunto/hooks/useCupsGas.ts`
- [ ] T015 [P3] [US6] Envolver el `console.log` de la línea 18 con guard de entorno — `resources/js/Pages/Eneon/PuntosSuministro/Edit.tsx`
- [ ] T016 [P3] [US6] Envolver el `console.log` de la línea 25 con guard de entorno — `resources/js/Pages/Eneon/Dashboard/Components/ClientDetailPanel.tsx`
- [ ] T017 [P3] [US6] Envolver o eliminar los +10 `console.log` del componente legacy — `resources/js/Pages/Eneon/Contratos/ReferenciasCodigo/CupsGasSection.tsx`
- [ ] T018 [P3] [US6] Envolver o eliminar los +8 `console.log` del componente legacy — `resources/js/Pages/Eneon/Contratos/ReferenciasCodigo/CupsElectricSection.tsx`

---

## FASE 4 — Selectores Redux a nivel de módulo (US1, US3) 🟡 Riesgo Medio

- [ ] T019 [P1] [US1] Mover `selectLayoutState` y `selectLayoutProperties` fuera del cuerpo del componente al ámbito de módulo — `resources/js/Layouts/index.tsx`
- [ ] T020 [P1] [US1] Eliminar `PropTypes` redundante (`Layout.propTypes`) — `resources/js/Layouts/index.tsx`
- [ ] T021 [P1] [US3] Mover `selectDashboardData` fuera del cuerpo del componente `Header` al ámbito de módulo — `resources/js/Layouts/Header.tsx`
- [ ] T022 [P1] [US3] Mover `selecVerticaltLayoutProperties` fuera del componente `VerticalLayout` al ámbito de módulo — `resources/js/Layouts/VerticalLayouts/index.tsx`

---

## FASE 5 — RightSidebar lazy (US2) 🟡 Riesgo Medio

- [ ] T023 [P1] [US2] Convertir import síncrono de `RightSidebar` a `React.lazy` con `React.Suspense fallback={null}` — `resources/js/Layouts/index.tsx`

---

## FASE 6 — Caché centralizada de tarifas (US4) 🟡 Riesgo Medio

- [ ] T024 [P2] [US4] Eliminar la llamada a `buscarTarifas()` del `useEffect` de inicialización y hacer que el hook acepte `tarifasElectricas` como prop — `resources/js/Pages/Eneon/Contratos/UniClienteUniPunto/hooks/useCupsElectrico.ts`
- [ ] T025 [P2] [US4] Eliminar la llamada a `buscarTarifas()` del `useEffect` de inicialización y hacer que el hook acepte `tarifasGas` como prop — `resources/js/Pages/Eneon/Contratos/UniClienteUniPunto/hooks/useCupsGas.ts`
- [ ] T026 [P2] [US4] Añadir `useEffect` de carga centralizada de tarifas (eléctrica + gas) al mount en `Contrato.tsx` usando `dataService` con `simpleCache` y pasar las tarifas como props a los hooks — `resources/js/Pages/Eneon/Contratos/UniClienteUniPunto/Contrato.tsx`

---

## FASE 7 — Eliminar MUI de ContratoMultiPunto (US7) 🟠 Riesgo Moderado

- [ ] T027 [P3] [US7] Auditar el proyecto completo para verificar que `@mui/material` y `@mui/icons-material` solo se importan en `ContratoMultiPunto.tsx` — búsqueda global
- [ ] T028 [P3] [US7] Reemplazar `Dialog/DialogContent/DialogTitle/IconButton` de MUI con `Modal` de `react-bootstrap` en el modal de edición de CUPS eléctrico — `resources/js/Pages/Eneon/Contratos/UniClienteMultiPunto/ContratoMultiPunto.tsx`
- [ ] T029 [P3] [US7] Reemplazar `Dialog` de MUI con `Modal` de `react-bootstrap` en el modal de edición de CUPS gas (si existe) — `resources/js/Pages/Eneon/Contratos/UniClienteMultiPunto/ContratoMultiPunto.tsx`
- [ ] T030 [P3] [US7] Eliminar `@mui/material` y `@mui/icons-material` de `package.json` y ejecutar `npm install` — `package.json`

---

## Verificación por fase

- [ ] V01 [US3] Navegar 5 páginas — auditar event listeners en DevTools → conteo estable
- [ ] V02 [US1] React Profiler — teclear en campo de contrato → solo el campo editado se re-renderiza
- [ ] V03 [US5] Cambiar cliente A → B rápido → CUPS pertenecen a cliente B
- [ ] V04 [US6] `npm run build` + consola prod → 0 logs de diagnóstico
- [ ] V05 [US1] Navegar contratos → clientes → dashboard → contratos → layout sin parpadeo
- [ ] V06 [US2] `npm run build` — comparar tamaño chunk principal antes/después de lazy RightSidebar
- [ ] V07 [US4] Network DevTools filtro `/tarifa` → máx 2 requests al abrir, 0 al reabrir en misma sesión
- [ ] V08 [US7] Modal edición CUPS funciona con React-Bootstrap → `npm run build` sin traza de `@mui`
