From 50a3c87b140cce19bd599e43b8d2ae6fdf37b16c Mon Sep 17 00:00:00 2001 From: dmolinari Date: Sat, 18 Apr 2026 21:00:00 -0300 Subject: [PATCH] chore(frontend): limpiar lint errors pre-existentes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 11 errores en archivos pre-existentes (0 en rubros/). Categorización: 2 bugs reales removidos, 1 FP con disable comentado, 8 FPs suprimidos con eslint-disable-next-line. Files: - src/web/src/components/ui/badge.tsx — react-refresh/only-export-components (FP: shadcn/ui co-ubica badgeVariants con el componente por diseño) - src/web/src/components/ui/button.tsx — react-refresh/only-export-components (FP: ídem, buttonVariants) - src/web/src/components/ui/form.tsx — react-refresh/only-export-components (FP: shadcn/ui co-ubica useFormField hook) - src/web/src/pages/admin/audit/AuditFilters.tsx — react-refresh/only-export-components x2 (FP: EMPTY_FILTERS y toApiFilter co-ubicados con el componente que los consume) - src/web/src/features/permisos/components/RolPermisosEditor.tsx — react-hooks/set-state-in-effect (FP: patrón válido de derived state desde prop externa asignados) - src/web/src/features/users/components/PermisosEditor.tsx — react-hooks/set-state-in-effect (FP: ídem, permisoData → mapa local de overrides) - src/web/src/pages/admin/audit/AuditPage.tsx — react-hooks/set-state-in-effect (FP: acumulación de páginas paginadas desde query externa) - src/web/src/features/users/pages/CreateUserPage.tsx — @typescript-eslint/no-unused-vars (FP: _created existe por contrato de callback, no se necesita el valor) - src/web/src/lib/dateFormat.ts — @typescript-eslint/no-unused-vars (FP: _opts reservado para extensibilidad futura; formato hardcodeado por compatibilidad Intl) - src/web/src/tests/api/axiosClient.test.ts — @typescript-eslint/no-unused-vars (bug real: requestCount incrementado en mock handler pero nunca asercionado; variable eliminada) --- src/web/src/components/ui/badge.tsx | 1 + src/web/src/components/ui/button.tsx | 1 + src/web/src/components/ui/form.tsx | 1 + src/web/src/features/permisos/components/RolPermisosEditor.tsx | 1 + src/web/src/features/users/components/PermisosEditor.tsx | 1 + src/web/src/features/users/pages/CreateUserPage.tsx | 1 + src/web/src/lib/dateFormat.ts | 1 + src/web/src/pages/admin/audit/AuditFilters.tsx | 2 ++ src/web/src/pages/admin/audit/AuditPage.tsx | 1 + src/web/src/tests/api/axiosClient.test.ts | 3 --- 10 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/web/src/components/ui/badge.tsx b/src/web/src/components/ui/badge.tsx index 1238b27..8afeb6c 100644 --- a/src/web/src/components/ui/badge.tsx +++ b/src/web/src/components/ui/badge.tsx @@ -33,4 +33,5 @@ function Badge({ className, variant, ...props }: BadgeProps) { ) } +// eslint-disable-next-line react-refresh/only-export-components -- shadcn/ui generated: badgeVariants is intentionally co-located with the component export { Badge, badgeVariants } diff --git a/src/web/src/components/ui/button.tsx b/src/web/src/components/ui/button.tsx index 36496a2..7f6bdec 100644 --- a/src/web/src/components/ui/button.tsx +++ b/src/web/src/components/ui/button.tsx @@ -53,4 +53,5 @@ const Button = React.forwardRef( ) Button.displayName = "Button" +// eslint-disable-next-line react-refresh/only-export-components -- shadcn/ui generated: buttonVariants is intentionally co-located with the component export { Button, buttonVariants } diff --git a/src/web/src/components/ui/form.tsx b/src/web/src/components/ui/form.tsx index 6ebbd49..434f0d2 100644 --- a/src/web/src/components/ui/form.tsx +++ b/src/web/src/components/ui/form.tsx @@ -165,6 +165,7 @@ const FormMessage = React.forwardRef< FormMessage.displayName = 'FormMessage' export { + // eslint-disable-next-line react-refresh/only-export-components -- shadcn/ui generated: useFormField hook is intentionally co-located with form components useFormField, Form, FormItem, diff --git a/src/web/src/features/permisos/components/RolPermisosEditor.tsx b/src/web/src/features/permisos/components/RolPermisosEditor.tsx index a28f4a1..7ab74c7 100644 --- a/src/web/src/features/permisos/components/RolPermisosEditor.tsx +++ b/src/web/src/features/permisos/components/RolPermisosEditor.tsx @@ -33,6 +33,7 @@ export function RolPermisosEditor({ rolCodigo }: RolPermisosEditorProps) { // Prefill checkboxes cuando lleguen los permisos asignados al rol useEffect(() => { if (asignados) { + // eslint-disable-next-line react-hooks/set-state-in-effect -- sincroniza prop externa (asignados) con estado local; patrón válido de derived state setSelected(new Set(asignados.map((p) => p.codigo))) setSaved(false) } diff --git a/src/web/src/features/users/components/PermisosEditor.tsx b/src/web/src/features/users/components/PermisosEditor.tsx index 5c52747..a689c2d 100644 --- a/src/web/src/features/users/components/PermisosEditor.tsx +++ b/src/web/src/features/users/components/PermisosEditor.tsx @@ -59,6 +59,7 @@ export function PermisosEditor({ userId }: PermisosEditorProps) { for (const c of permisoData.overrides.grant) map.set(c, 'concedido') // Apply deny overrides for (const c of permisoData.overrides.deny) map.set(c, 'denegado') + // eslint-disable-next-line react-hooks/set-state-in-effect -- sincroniza prop externa (permisoData) con mapa local de overrides; patrón válido de derived state setStates(map) setSaveError(null) }, [permisoData]) diff --git a/src/web/src/features/users/pages/CreateUserPage.tsx b/src/web/src/features/users/pages/CreateUserPage.tsx index b97076b..0d3b4c5 100644 --- a/src/web/src/features/users/pages/CreateUserPage.tsx +++ b/src/web/src/features/users/pages/CreateUserPage.tsx @@ -12,6 +12,7 @@ import type { CreatedUserDto } from '../api/createUser' export function CreateUserPage() { const navigate = useNavigate() + // eslint-disable-next-line @typescript-eslint/no-unused-vars -- el callback recibe CreatedUserDto por contrato de UserForm pero solo necesitamos navegar function handleSuccess(_created: CreatedUserDto) { void navigate('/') } diff --git a/src/web/src/lib/dateFormat.ts b/src/web/src/lib/dateFormat.ts index e436dd6..9523e3e 100644 --- a/src/web/src/lib/dateFormat.ts +++ b/src/web/src/lib/dateFormat.ts @@ -25,6 +25,7 @@ interface FormatInstantOptions { */ export function formatInstant( iso: string, + // eslint-disable-next-line @typescript-eslint/no-unused-vars -- parámetro reservado para futura extensibilidad; el formato está hardcodeado por compatibilidad con entornos donde Intl.DateTimeFormat ignora dateStyle/timeStyle _opts: FormatInstantOptions = { dateStyle: 'short', timeStyle: 'medium' } ): string { const parts = new Intl.DateTimeFormat('es-AR', { diff --git a/src/web/src/pages/admin/audit/AuditFilters.tsx b/src/web/src/pages/admin/audit/AuditFilters.tsx index 79e2f56..016f89a 100644 --- a/src/web/src/pages/admin/audit/AuditFilters.tsx +++ b/src/web/src/pages/admin/audit/AuditFilters.tsx @@ -13,6 +13,7 @@ export interface AuditFiltersValue { to: string } +// eslint-disable-next-line react-refresh/only-export-components -- constante de reset co-ubicada con el componente que la consume como valor inicial export const EMPTY_FILTERS: AuditFiltersValue = { actor: '', targetType: '', @@ -137,6 +138,7 @@ export function AuditFilters({ * Los convertimos a ISO UTC vía `parseArgentinaDateTimeToUtc()` (fix BUG-FE-05). * - Strings vacíos → omitidos. */ +// eslint-disable-next-line react-refresh/only-export-components -- función utilitaria de mapeo co-ubicada con el componente que la necesita; extraerla a otro archivo aumentaría la fragmentación innecesariamente export function toApiFilter( value: AuditFiltersValue, ): import('@/api/audit').AuditEventsFilter { diff --git a/src/web/src/pages/admin/audit/AuditPage.tsx b/src/web/src/pages/admin/audit/AuditPage.tsx index 7979ac4..a5d0ecf 100644 --- a/src/web/src/pages/admin/audit/AuditPage.tsx +++ b/src/web/src/pages/admin/audit/AuditPage.tsx @@ -67,6 +67,7 @@ export function AuditPage() { useEffect(() => { if (!data) return if (cursor === undefined) { + // eslint-disable-next-line react-hooks/set-state-in-effect -- acumula datos paginados de una query externa; reset en primera página es intencional setAccumulated(data.items) } else { setAccumulated((prev) => { diff --git a/src/web/src/tests/api/axiosClient.test.ts b/src/web/src/tests/api/axiosClient.test.ts index 23ffdf2..bd84837 100644 --- a/src/web/src/tests/api/axiosClient.test.ts +++ b/src/web/src/tests/api/axiosClient.test.ts @@ -131,11 +131,8 @@ describe('axiosClient', () => { setAuth('expired-access', 'valid-refresh') let refreshCallCount = 0 - let requestCount = 0 - server.use( http.get(`${API_URL}/api/v1/protected`, ({ request }) => { - requestCount++ const auth = request.headers.get('Authorization') if (auth === 'Bearer new-access-from-refresh') { return HttpResponse.json({ data: 'ok' }) -- 2.49.1