Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Rate limit exceeded
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 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 configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughSe añade selección y renderizado de íconos para categorías: nuevo ChangesCategory Icon Management System
Sequence DiagramsequenceDiagram
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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
…evitar duplicación de código.
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
src/features/admin/pages/AdminCategoriesPage.jsx (1)
771-782: ⚖️ Poor tradeoffLas 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 arraycategoriesde 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
📒 Files selected for processing (4)
src/features/admin/components/CategoryIconPicker.jsxsrc/features/admin/pages/AdminCategoriesPage.jsxsrc/features/admin/pages/AdminCategoryDetailPage.jsxsrc/features/admin/services/adminCategoriesApi.js
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (1)
src/features/admin/components/CategoryEditModal.jsx (1)
48-53:⚠️ Potential issue | 🟠 Major | ⚡ Quick winEvitar cierre del modal mientras
isSubmittingestá 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!isSubmittingigual 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
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (5)
package.jsonsrc/features/admin/components/CategoryEditModal.jsxsrc/features/admin/components/CategoryIconPicker.jsxsrc/features/admin/pages/AdminCategoriesPage.jsxsrc/features/admin/pages/AdminCategoryDetailPage.jsx
There was a problem hiding this comment.
♻️ Duplicate comments (3)
src/features/admin/pages/AdminCategoryDetailPage.jsx (1)
188-196:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winEvitá renderizar
Gs. NaNcuando faltaoriginalPrice.En Line 188-196, con
p.isOffer === trueyp.originalPriceinválido/ausente, la UI muestraNaN.💵 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 winBloqueá 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 winAgregá 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
stopPropagationacá es redundante y se puede eliminar.En Line 60 ya filtrás cierre por
event.target === event.currentTarget, así que elonClickdel 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
📒 Files selected for processing (4)
src/features/admin/components/CategoryEditModal.jsxsrc/features/admin/components/CategoryIconPicker.jsxsrc/features/admin/pages/AdminCategoriesPage.jsxsrc/features/admin/pages/AdminCategoryDetailPage.jsx
🚧 Files skipped from review as they are similar to previous changes (1)
- src/features/admin/components/CategoryIconPicker.jsx
|



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
Improvements
Bug Fixes