Skip to content

OM-508: Íconos de las categorías: integración, todavía no terminado.#203

Merged
elianasmz merged 14 commits into
devfrom
OM-508
May 20, 2026
Merged

OM-508: Íconos de las categorías: integración, todavía no terminado.#203
elianasmz merged 14 commits into
devfrom
OM-508

Conversation

@J-Kanami-PS

@J-Kanami-PS J-Kanami-PS commented May 18, 2026

Copy link
Copy Markdown
Collaborator

El administrador puede crear una categoría y agregarle ícono, también lo puede editar. El ícono de cada categoría se visualiza en el listado y en la visualización detallada de cada categoría.

Summary by CodeRabbit

  • New Features

    • Selector de íconos para categorías con vista previa en formularios de crear/editar.
    • Modal de edición reutilizable para categorías.
  • Improvements

    • Modales (crear/editar/borrar/aprobar/rechazar) muestran errores, manejan estados de envío y evitan acciones conflictivas.
    • Tabla y detalle de categorías muestran íconos, badges de visibilidad/estado y mejor manejo de paginación/filtrado.
    • Validaciones de entrada y propTypes añadidos para mayor robustez.
  • Bug Fixes

    • Ajustes en flujos de aprobación/rechazo/borrado para mantener conteos y páginas correctas.

Review Change Stack

@vercel

vercel Bot commented May 18, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
frontend-marketplace Ready Ready Preview, Comment May 20, 2026 1:18am

@coderabbitai

coderabbitai Bot commented May 18, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@J-Kanami-PS has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 22 minutes and 16 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8df04d68-33ab-481b-91d9-ac5f095e8d23

📥 Commits

Reviewing files that changed from the base of the PR and between 3968fa2 and 425ef3d.

📒 Files selected for processing (2)
  • src/features/admin/components/CategoryEditModal.jsx
  • src/features/admin/pages/AdminCategoriesPage.jsx
📝 Walkthrough

Walkthrough

Se añade selección y renderizado de íconos para categorías: nuevo IconPicker/CategoryIcon, integración en crear/editar modales, tablas y detalle, y actualización de API para aceptar y devolver icon. También se añaden propTypes, manejo de Escape y ajustes de carga/paginación.

Changes

Category Icon Management System

Layer / File(s) Summary
API Contracts for Icon Support
src/features/admin/services/adminCategoriesApi.js
createAdminCategory acepta icon; fetchAdminCategoryById y updateAdminCategory documentan/retornan icon.
Dev dependency update
package.json
Se agrega @types/prop-types en devDependencies.
Icon Picker Component
src/features/admin/components/CategoryIconPicker.jsx
ICON_OPTIONS, CategoryIcon (resuelve por nombre con fallback) e IconPicker (grilla de opciones, propTypes).
CategoryEditModal (new)
src/features/admin/components/CategoryEditModal.jsx
Modal de edición con zod validation, estado `name
Create/Delete/Approve/Reject Modals
src/features/admin/pages/AdminCategoriesPage.jsx
Crear ahora pasa (name, icon); modales incluyen cierre por Escape condicionado, render de errores y propTypes.
CategoryRow & RequestRow
src/features/admin/pages/AdminCategoriesPage.jsx
CategoryRow usa CategoryIcon (cat.icon), añade badges, botones con title y propTypes; RequestRow añade propTypes y callbacks.
Page State and Handlers
src/features/admin/pages/AdminCategoriesPage.jsx
Estados para modales/selecciones/errores; loadRequests con status: false; handlers para crear/editar/aprobar/rechazar ajustados con paginación y manejo de errores.
Tabs, Filters & Categories Panel
src/features/admin/pages/AdminCategoriesPage.jsx
Reestructura de pestañas, header de categorías, filtros (search/visible), estadísticas y contador de categorías ocultas.
Tables, Requests List & Modals Render
src/features/admin/pages/AdminCategoriesPage.jsx
Tabla de categorías/solicitudes con estados de carga/vacío, mapeo a filas y paginación; sección de modales reorganizada.
Category Detail Page
src/features/admin/pages/AdminCategoryDetailPage.jsx
Detalle usa CategoryIcon, delega edición a CategoryEditModal, corrige useEffect deps para loadProducts, reestructura header y tabla, añade render centralizado de productos.

Sequence Diagram

sequenceDiagram
  participant Admin as Admin User
  participant UI as Client UI (Create/Edit)
  participant IconPicker as IconPicker/CategoryIcon
  participant API as adminCategoriesApi
  participant DB as Backend

  Admin->>UI: abre modal, ingresa nombre y selecciona ícono
  UI->>IconPicker: renderiza opciones, user selecciona icon
  IconPicker-->>UI: onChange(name)
  UI->>API: POST createAdminCategory(name, icon)
  API->>DB: persiste categoría con icon
  DB-->>API: retorna categoría con icon
  API-->>UI: confirma creación
  Admin->>UI: abre detalle/editar
  UI->>IconPicker: inicializa con category.icon
  Admin->>UI: cambia icon y guarda
  UI->>API: PUT updateAdminCategory(id, { name?, icon?, visible? })
  API->>DB: actualiza campos cambiados
  DB-->>API: retorna categoría actualizada
  API-->>UI: confirma actualización
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • Benjakr04

Poem

🐰 Con orejas listas, el conejo eligió un icono,
Brilla la categoría en la lista y en el rincón,
Saltó entre grids y modales con alegría,
Guardó el cambio, cerró el modal y celebró,
¡Un pequeño ícono, una gran sonrisa!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning El título describe la característica principal (iconos de categorías) pero incluye la frase 'todavía no terminado', lo que indica que el cambio no está completo para merguear. Actualizar el título para reflejar solo cambios completados, removiendo 'todavía no terminado' o marcar como borrador si aún hay trabajo pendiente.
Docstring Coverage ⚠️ Warning Docstring coverage is 63.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch OM-508

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
src/features/admin/pages/AdminCategoriesPage.jsx (1)

771-782: ⚖️ Poor tradeoff

Las estadísticas de Visible/Oculta solo reflejan la página actual.

El "Total de Categorías" muestra el conteo global (pagination.categoryTotal), pero "Categorías Visibles" y "Categorías Ocultas" calculan sobre el array categories de la página actual. Esto puede ser confuso cuando hay múltiples páginas.

Además, si se aplica un filtro de visibilidad, los conteos serán aún menos representativos.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/admin/pages/AdminCategoriesPage.jsx` around lines 771 - 782, Las
métricas "Categorías Visibles" y "Categorías Ocultas" se están calculando sobre
el array de la página actual (`categories`) y no representan el total global ni
respetan filtros; cambia la fuente de verdad para esos contadores: usa los
totales globales proporcionados por el paginador/response (por ejemplo
`pagination.visibleCategoryTotal` / `pagination.hiddenCategoryTotal` o nombres
análogos) en lugar de `categories.filter(c => c.visible).length` y
`hiddenCategoriesCount`, o si el backend no expone esos campos, solicita al
backend que devuelva totales por visibilidad y usa esos valores;
alternativamente, si quieres mantener conteos por página deja claro en las
etiquetas (ej. "Visibles en esta página") y actualiza la UI para respetar
filtros usando los totales de `pagination`.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/features/admin/components/CategoryIconPicker.jsx`:
- Around line 90-98: El componente IconPicker aún usa IconPicker.defaultProps;
React 19 requiere usar parámetros por defecto en la firma de la función: remove
the IconPicker.defaultProps block and update the IconPicker function signature
to provide a default for disabled (e.g. function IconPicker({ value, onChange,
disabled = false }) ), leaving the PropTypes declaration intact; ensure no other
references rely on defaultProps.

In `@src/features/admin/pages/AdminCategoriesPage.jsx`:
- Around line 6-8: El import inutilizado Tag en la lista de imports desde
"lucide-react" debe eliminarse; abre la declaración que importa Search, Trash2,
Eye, AlertTriangle, Tag, Package, Pencil, X, Plus, CheckCircle, XCircle, Clock y
quita solo el identificador Tag para que ya no sea importado por la componente
AdminCategoriesPage.jsx (o la declaración donde aparece) y guarda el archivo.
- Around line 160-164: En EditModal, el manejador handleOverlayKeyDown y el
onClick del overlay deben respetar el estado isSubmitting igual que CreateModal:
antes de invocar onCancel() comprueba que !isSubmitting para evitar cerrar el
modal durante el envío; modifica handleOverlayKeyDown (y la función o handler
anónimo usado en el onClick del overlay) para condicionar la llamada a onCancel
con !isSubmitting, usando las mismas variables/props isSubmitting y onCancel ya
presentes en el componente.

In `@src/features/admin/pages/AdminCategoryDetailPage.jsx`:
- Around line 57-71: While isSubmitting is true, prevent all close paths: update
handleOverlayKeyDown to return early if isSubmitting (so Escape does nothing),
replace inline onClick={onCancel} with a wrapper that returns early when
isSubmitting and only calls onCancel when e.target === e.currentTarget (to avoid
clicks inside the dialog), and ensure the dialog close/X control checks
isSubmitting and either disables the button or no-ops its click handler; also
guard any other places that call onCancel to no-op while isSubmitting. Use the
existing symbols handleOverlayKeyDown, onCancel and isSubmitting (and the
close/X button handler) to locate and change the logic.

---

Nitpick comments:
In `@src/features/admin/pages/AdminCategoriesPage.jsx`:
- Around line 771-782: Las métricas "Categorías Visibles" y "Categorías Ocultas"
se están calculando sobre el array de la página actual (`categories`) y no
representan el total global ni respetan filtros; cambia la fuente de verdad para
esos contadores: usa los totales globales proporcionados por el
paginador/response (por ejemplo `pagination.visibleCategoryTotal` /
`pagination.hiddenCategoryTotal` o nombres análogos) en lugar de
`categories.filter(c => c.visible).length` y `hiddenCategoriesCount`, o si el
backend no expone esos campos, solicita al backend que devuelva totales por
visibilidad y usa esos valores; alternativamente, si quieres mantener conteos
por página deja claro en las etiquetas (ej. "Visibles en esta página") y
actualiza la UI para respetar filtros usando los totales de `pagination`.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7fec95c1-c39a-432e-93f7-f8338c1d1e2e

📥 Commits

Reviewing files that changed from the base of the PR and between 902556d and 5c1b784.

📒 Files selected for processing (4)
  • src/features/admin/components/CategoryIconPicker.jsx
  • src/features/admin/pages/AdminCategoriesPage.jsx
  • src/features/admin/pages/AdminCategoryDetailPage.jsx
  • src/features/admin/services/adminCategoriesApi.js

Comment thread src/features/admin/components/CategoryIconPicker.jsx
Comment thread src/features/admin/pages/AdminCategoriesPage.jsx Outdated
Comment thread src/features/admin/pages/AdminCategoriesPage.jsx Outdated
Comment thread src/features/admin/pages/AdminCategoryDetailPage.jsx Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (1)
src/features/admin/components/CategoryEditModal.jsx (1)

48-53: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Evitar cierre del modal mientras isSubmitting está activo.

Ahora se puede cerrar por overlay, Escape o botón X durante "Guardando...", dejando la operación en curso sin feedback en pantalla. Condicioná esos cierres con !isSubmitting igual que el botón Cancelar.

🔧 Ajuste propuesto
-        <div
+        <div
             role="button"
             tabIndex={0}
-            onClick={onCancel}
-            onKeyDown={e => e.key === "Escape" && onCancel()}
+            onClick={isSubmitting ? undefined : onCancel}
+            onKeyDown={e => !isSubmitting && e.key === "Escape" && onCancel()}
             style={{
@@
                     <button
                         type="button"
-                        onClick={onCancel}
+                        onClick={isSubmitting ? undefined : onCancel}
+                        disabled={isSubmitting}
                         style={{ background: "none", border: "none", cursor: "pointer", color: "`#6b7280`" }}
                     >

Also applies to: 71-77

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/admin/components/CategoryEditModal.jsx` around lines 48 - 53,
Evita que el modal se cierre mientras isSubmitting es true: updatea las llamadas
a onCancel en el overlay div (role="button" con onClick/onKeyDown) y en el botón
de cierre (los handlers alrededor de la sección equivalente a 71-77) para que
sólo invoquen onCancel cuando !isSubmitting; es decir, envuelve las invocaciones
actuales (onClick, onKeyDown where e.key === "Escape", y el handler del botón X)
con una comprobación if (!isSubmitting) onCancel() o condicionales inline, igual
que el botón Cancelar ya hace, para bloquear cierres durante la operación de
guardado.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/features/admin/components/CategoryEditModal.jsx`:
- Around line 48-67: El overlay actualmente tiene role="button" — quita ese role
del div externo y deja el overlay como solo contenedor visual; keep
onClick/onKeyDown handlers but remove role="button". Mueve role="dialog" y
aria-modal="true" al panel interno (el div que llama e.stopPropagation()), y
añade aria-labelledby or aria-label on ese panel si hay un título visible (usar
el id del título si existe) para cumplir con la semántica accesible; conserva
onCancel en onClick del overlay para cerrar al hacer clic fuera y mantiene
e.stopPropagation() en el panel para evitar el cierre accidental.

In `@src/features/admin/pages/AdminCategoriesPage.jsx`:
- Around line 46-57: Replace the overlay div that currently uses role="button"
with an accessible modal container: change role="button" to role="dialog", add
aria-modal="true" and a proper accessible label (aria-labelledby or aria-label),
keep the escape handler wired to call onCancel but attach it to the dialog
container (the same element in the diff that currently has onClick/onKeyDown)
and ensure tabIndex is set to allow focus (e.g., tabIndex={-1} or 0 as
appropriate) so keyboard focus can be managed; remove the incorrect
role="button" from the other three modal overlays that use the same pattern
(they also use isSubmitting and onCancel in their handlers) and ensure
consistent dialog semantics across all modals.
- Line 765: La variable hiddenCategories está filtrando categories con c.visible
(mostrando las visibles) pero se usa como "ocultas"; cambia la expresión en la
asignación hiddenCategories (actualmente categories.filter(c => c.visible)) a
categories.filter(c => !c.visible) para invertir la lógica, y corrige las otras
ocurrencias relacionadas que usan hiddenCategories / la cuenta de categorías
ocultas (las referencias alrededor del texto que muestra el conteo de ocultas)
para que reflejen el nuevo filtro.

In `@src/features/admin/pages/AdminCategoryDetailPage.jsx`:
- Around line 277-281: The code renders "Gs. NaN" when p.isOffer is true but
p.originalPrice is undefined; update the render condition in
AdminCategoryDetailPage.jsx so the struck price paragraph only renders when
originalPrice is present and a valid number (e.g., change the check from
p.isOffer to p.isOffer && Number.isFinite(Number(p.originalPrice))) and only
call toLocaleString when originalPrice is validated; optionally show a safe
fallback (like nothing or "—") when originalPrice is missing.

---

Duplicate comments:
In `@src/features/admin/components/CategoryEditModal.jsx`:
- Around line 48-53: Evita que el modal se cierre mientras isSubmitting es true:
updatea las llamadas a onCancel en el overlay div (role="button" con
onClick/onKeyDown) y en el botón de cierre (los handlers alrededor de la sección
equivalente a 71-77) para que sólo invoquen onCancel cuando !isSubmitting; es
decir, envuelve las invocaciones actuales (onClick, onKeyDown where e.key ===
"Escape", y el handler del botón X) con una comprobación if (!isSubmitting)
onCancel() o condicionales inline, igual que el botón Cancelar ya hace, para
bloquear cierres durante la operación de guardado.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e09ad3c2-dcc1-4d98-9b9e-9b3a4bfd47d0

📥 Commits

Reviewing files that changed from the base of the PR and between 5c1b784 and 4590e3c.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (5)
  • package.json
  • src/features/admin/components/CategoryEditModal.jsx
  • src/features/admin/components/CategoryIconPicker.jsx
  • src/features/admin/pages/AdminCategoriesPage.jsx
  • src/features/admin/pages/AdminCategoryDetailPage.jsx

Comment thread src/features/admin/components/CategoryEditModal.jsx Outdated
Comment thread src/features/admin/pages/AdminCategoriesPage.jsx Outdated
Comment thread src/features/admin/pages/AdminCategoriesPage.jsx Outdated
Comment thread src/features/admin/pages/AdminCategoryDetailPage.jsx Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (3)
src/features/admin/pages/AdminCategoryDetailPage.jsx (1)

188-196: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Evitá renderizar Gs. NaN cuando falta originalPrice.

En Line 188-196, con p.isOffer === true y p.originalPrice inválido/ausente, la UI muestra NaN.

💵 Condición segura sugerida
-                            {p.isOffer && (
+                            {p.isOffer && Number.isFinite(Number(p.originalPrice)) && (
                                 <p style={{
                                     margin: 0,
                                     fontSize: "11px",
                                     color: "`#9ca3af`",
                                     textDecoration: "line-through"
                                 }}>
                                     Gs. {Number(p.originalPrice).toLocaleString("es-PY")}
                                 </p>
                             )}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/admin/pages/AdminCategoryDetailPage.jsx` around lines 188 - 196,
When rendering the crossed original price in AdminCategoryDetailPage.jsx (inside
the product render where p.isOffer is checked), avoid displaying "Gs. NaN" by
only rendering the price when p.originalPrice is a valid number: check
Number.isFinite(Number(p.originalPrice)) (or
!isNaN(parseFloat(p.originalPrice))) before formatting with toLocaleString; if
invalid/absent, skip the whole <p> block. Update the conditional that currently
uses p.isOffer to require both p.isOffer and a numeric originalPrice (reference
the p.isOffer check and p.originalPrice field in the product render).
src/features/admin/components/CategoryEditModal.jsx (1)

70-75: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Bloqueá todos los cierres del modal mientras se está guardando.

En Line 74, Line 75, Line 108 y Line 210 todavía se puede cerrar el modal durante isSubmitting (Escape/overlay/X). Eso permite “perder” el estado visible de guardado en vuelo.

🔧 Ajuste mínimo sugerido
-    const handleOverlayClick = (event) => {
-        if (event.target === event.currentTarget) {
+    const handleOverlayClick = (event) => {
+        if (!isSubmitting && event.target === event.currentTarget) {
             onCancel();
         }
     };
@@
-        <dialog
+        <dialog
             open
             aria-modal="true"
             aria-labelledby="edit-modal-title"
-            onClose={onCancel}
+            onClose={() => {
+                if (!isSubmitting) onCancel();
+            }}
             onClick={handleOverlayClick}
@@
-                    <button
+                    <button
                         type="button"
-                        onClick={onCancel}
+                        onClick={onCancel}
+                        disabled={isSubmitting}
                         style={{ background: "none", border: "none", cursor: "pointer", color: "`#6b7280`" }}
                     >
@@
-                    <button
+                    <button
                         type="button"
-                        onClick={onCancel}
+                        onClick={onCancel}
                         disabled={isSubmitting}

Also applies to: 91-92, 106-109, 210-211

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/admin/components/CategoryEditModal.jsx` around lines 70 - 75,
The modal currently allows closing during in-flight saves; update the close
handlers to block closes when isSubmitting is true: add an early-return guard so
onCancel ignores attempts to close while isSubmitting, update handleOverlayClick
to not call onCancel (or to return) when isSubmitting, and apply the same guard
to the close-button click/handler and any Escape/onClose invocation paths used
in CategoryEditModal.jsx; reference the isSubmitting flag in each handler
(onCancel, handleOverlayClick and the close-button onClick/Escape handler) so
attempts to close are no-ops until isSubmitting is false.
src/features/admin/pages/AdminCategoriesPage.jsx (1)

33-36: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Agregá semántica modal explícita en el dialog.

En Line 33-36 falta aria-modal="true", y eso degrada la accesibilidad del overlay como diálogo modal real.

♿ Fix mínimo
         <dialog
             open
+            aria-modal="true"
             aria-labelledby={labelId}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/admin/pages/AdminCategoriesPage.jsx` around lines 33 - 36, Add
the explicit modal semantics to the dialog element by adding aria-modal="true"
to the <dialog> tag that currently has open and aria-labelledby={labelId};
update the JSX for the dialog component (the element using aria-labelledby and
labelId in AdminCategoriesPage) to include aria-modal="true" so assistive tech
treats this overlay as a true modal dialog.
🧹 Nitpick comments (1)
src/features/admin/components/CategoryEditModal.jsx (1)

65-67: ⚡ Quick win

stopPropagation acá es redundante y se puede eliminar.

En Line 60 ya filtrás cierre por event.target === event.currentTarget, así que el onClick del contenedor interno (Line 91) no aporta comportamiento.

🧹 Simplificación sugerida
-    const stopPropagation = (event) => {
-        event.stopPropagation();
-    };
@@
-            <div
-                onClick={stopPropagation}
-                style={{
+            <div
+                style={{

Also applies to: 90-92

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/admin/components/CategoryEditModal.jsx` around lines 65 - 67,
Remove the redundant stopPropagation helper and any onClick={stopPropagation}
usages inside the modal: the outer click handler already checks event.target ===
event.currentTarget to detect backdrop clicks, so the inner container's onClick
(and the stopPropagation function declaration) can be deleted; search for the
stopPropagation function and any inner container onClick attributes in
CategoryEditModal.jsx and remove them to simplify the modal click handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@src/features/admin/components/CategoryEditModal.jsx`:
- Around line 70-75: The modal currently allows closing during in-flight saves;
update the close handlers to block closes when isSubmitting is true: add an
early-return guard so onCancel ignores attempts to close while isSubmitting,
update handleOverlayClick to not call onCancel (or to return) when isSubmitting,
and apply the same guard to the close-button click/handler and any
Escape/onClose invocation paths used in CategoryEditModal.jsx; reference the
isSubmitting flag in each handler (onCancel, handleOverlayClick and the
close-button onClick/Escape handler) so attempts to close are no-ops until
isSubmitting is false.

In `@src/features/admin/pages/AdminCategoriesPage.jsx`:
- Around line 33-36: Add the explicit modal semantics to the dialog element by
adding aria-modal="true" to the <dialog> tag that currently has open and
aria-labelledby={labelId}; update the JSX for the dialog component (the element
using aria-labelledby and labelId in AdminCategoriesPage) to include
aria-modal="true" so assistive tech treats this overlay as a true modal dialog.

In `@src/features/admin/pages/AdminCategoryDetailPage.jsx`:
- Around line 188-196: When rendering the crossed original price in
AdminCategoryDetailPage.jsx (inside the product render where p.isOffer is
checked), avoid displaying "Gs. NaN" by only rendering the price when
p.originalPrice is a valid number: check
Number.isFinite(Number(p.originalPrice)) (or
!isNaN(parseFloat(p.originalPrice))) before formatting with toLocaleString; if
invalid/absent, skip the whole <p> block. Update the conditional that currently
uses p.isOffer to require both p.isOffer and a numeric originalPrice (reference
the p.isOffer check and p.originalPrice field in the product render).

---

Nitpick comments:
In `@src/features/admin/components/CategoryEditModal.jsx`:
- Around line 65-67: Remove the redundant stopPropagation helper and any
onClick={stopPropagation} usages inside the modal: the outer click handler
already checks event.target === event.currentTarget to detect backdrop clicks,
so the inner container's onClick (and the stopPropagation function declaration)
can be deleted; search for the stopPropagation function and any inner container
onClick attributes in CategoryEditModal.jsx and remove them to simplify the
modal click handling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9d0840ce-425d-4589-abf8-b8efb3330b50

📥 Commits

Reviewing files that changed from the base of the PR and between 4590e3c and 3968fa2.

📒 Files selected for processing (4)
  • src/features/admin/components/CategoryEditModal.jsx
  • src/features/admin/components/CategoryIconPicker.jsx
  • src/features/admin/pages/AdminCategoriesPage.jsx
  • src/features/admin/pages/AdminCategoryDetailPage.jsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/features/admin/components/CategoryIconPicker.jsx

@sonarqubecloud

Copy link
Copy Markdown

@elianasmz
elianasmz merged commit 281bd4f into dev May 20, 2026
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants