Skip to content

better error treatment#161

Merged
henri318 merged 2 commits into
mainfrom
fix/better_error_treatment
Jul 17, 2026
Merged

better error treatment#161
henri318 merged 2 commits into
mainfrom
fix/better_error_treatment

Conversation

@henri318

@henri318 henri318 commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • Nuevas funcionalidades

    • Añadida una pantalla de error para productos con opción de reintento y mensajes traducidos.
    • Renovada la página de perfil, con edición y eliminación de cuenta, validación de sesión y campos adaptados al tipo de usuario.
    • Mejorada la navegación interna mediante enlaces más rápidos en distintas secciones.
  • Correcciones

    • Los errores de inicio de sesión muestran mensajes seguros y consistentes.
    • Se detectan fallos al subir diseños y se restauran artículos del carrito si su eliminación falla.
    • Los errores reales al cargar productos ya no se muestran incorrectamente como “no encontrado”.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@henri318, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 38 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5f8f48c8-01a4-4c33-b806-d6a5f7bbe186

📥 Commits

Reviewing files that changed from the base of the PR and between e5c77ab and 2c47e39.

📒 Files selected for processing (15)
  • app/[locale]/profile/page.tsx
  • app/[locale]/profile/profile-form.tsx
  • app/api/users/me/route.ts
  • composition-root/container.ts
  • modules/auth/presentation/schemas/auth-schemas.ts
  • modules/users/application/dto/update-user.dto.ts
  • modules/users/application/use-cases/get-user-profile-use-case.ts
  • modules/users/application/use-cases/update-user-use-case.ts
  • modules/users/domain/user-profile-port.ts
  • modules/users/infrastructure/prisma-user-repository.ts
  • modules/users/infrastructure/user-profile-adapter.ts
  • tests/unit/app/[locale]/profile/profile-form.test.tsx
  • tests/unit/app/[locale]/profile/profile-page.test.tsx
  • tests/unit/modules/users/application/get-user-profile-use-case.test.ts
  • tests/unit/modules/users/application/update-user.test.ts
📝 Walkthrough

Walkthrough

El PR reemplaza enlaces internos por next/link, incorpora manejo explícito de errores en autenticación y productos, migra el perfil a un componente servidor con formulario cliente, valida fallos de subida y eliminación, y añade pruebas y traducciones asociadas.

Changes

Flujos de navegación interna

Layer / File(s) Summary
Navegación interna con Link
app/[locale]/admin/sellers/page.tsx, app/[locale]/auth/*, app/[locale]/layout.tsx, app/[locale]/orders/page.tsx, app/[locale]/seller/*, modules/cart/..., shared/layout/*, shared/ui/pagination.tsx
Los enlaces internos de administración, autenticación, pedidos, vendedores, carrito, cabecera y paginación pasan de <a> a Link conservando destinos, estilos y textos.

Errores de autenticación

Layer / File(s) Summary
Errores de autenticación
app/[locale]/auth/signin/page.tsx, shared/layout/login-modal.tsx, tests/unit/app/[locale]/auth/signin/signin-page.test.tsx, tests/unit/modules/presentation/components/login-modal.test.tsx
SignInPage y LoginModal muestran errores genéricos, restablecen la carga y cubren respuestas fallidas y excepciones mediante pruebas.

Errores y reintento de producto

Layer / File(s) Summary
Errores tipados y pantalla de recuperación
modules/products/application/get-product-by-id-use-case.ts, app/[locale]/products/[id]/page.tsx, app/[locale]/products/[id]/error.tsx, app/[locale]/products/[id]/error.module.css, shared/i18n/locales/*
Los productos inexistentes usan NotFoundError, los errores no relacionados se relanzan y la ruta añade una pantalla localizada con botón de reintento.
Validación de subida
app/[locale]/products/[id]/customization-experience.tsx, tests/unit/app/[locale]/products/[id]/customization-experience.test.tsx
La subida comprueba response.ok y lanza File storage failed cuando el almacenamiento rechaza el archivo.

Perfil y carrito

Layer / File(s) Summary
Perfil servidor-cliente
app/[locale]/profile/page.tsx, app/[locale]/profile/profile-form.tsx, tests/unit/app/[locale]/profile/*
ProfilePage obtiene sesión y usuario en servidor, redirige usuarios no válidos y delega la edición y eliminación en ProfileForm, con pruebas actualizadas.
Recuperación del carrito
modules/cart/presentation/components/cart-view.tsx, tests/unit/app/cart/cart-view.test.tsx
La eliminación valida la respuesta DELETE y restaura los artículos locales cuando falla; la prueba cubre la recuperación.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ProfilePage
  participant getServerSession
  participant UserRepository
  participant ProfileForm
  participant UsersAPI
  ProfilePage->>getServerSession: Obtener sesión
  ProfilePage->>UserRepository: Buscar usuario
  UserRepository-->>ProfilePage: Devolver perfil
  ProfilePage->>ProfileForm: Pasar datos del perfil
  ProfileForm->>UsersAPI: PATCH /api/users/me
  ProfileForm->>UsersAPI: DELETE /api/users/me
Loading

Possibly related PRs

Suggested labels: enhancement

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive El título es demasiado genérico y no describe con suficiente precisión el cambio principal del PR. Usa un título más específico, por ejemplo: "Improve error handling across auth, profile, and product flows".
✅ 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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/better_error_treatment

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.

@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 (2)
app/[locale]/products/[id]/error.module.css (1)

6-16: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Actualizar la notación de colores a sintaxis moderna.

Las herramientas de análisis estático (Stylelint) sugieren actualizar la notación de rgba() a la sintaxis moderna de rgb() con porcentajes para el canal alfa. Esto mejora la consistencia y cumple con los estándares actuales de CSS.

♻️ Propuesta de refactorización

Reemplazar el uso de rgba en el degradado de fondo:

-  background:
-    radial-gradient(
-      circle at 12% 18%,
-      rgba(213, 92, 92, 0.12),
-      transparent 24rem
-    ),
-    linear-gradient(
-      135deg,
-      rgba(247, 241, 232, 0.72),
-      rgba(255, 255, 255, 0.94)
-    );
+  background:
+    radial-gradient(
+      circle at 12% 18%,
+      rgb(213 92 92 / 12%),
+      transparent 24rem
+    ),
+    linear-gradient(
+      135deg,
+      rgb(247 241 232 / 72%),
+      rgb(255 255 255 / 94%)
+    );

Reemplazar los colores en el contenedor de la tarjeta (.card):

-  border: 1px solid rgba(13, 92, 70, 0.16);
+  border: 1px solid rgb(13 92 70 / 16%);
   border-top: 5px solid var(--color-coral);
   border-radius: var(--radius-md);
   padding: clamp(2rem, 7vw, 4.5rem);
   background: var(--color-white);
-  box-shadow: 0 1.5rem 4rem rgba(8, 20, 18, 0.1);
+  box-shadow: 0 1.5rem 4rem rgb(8 20 18 / 10%);

Y finalmente el estado focus-visible del botón:

 .retry:focus-visible {
-  outline: 3px solid rgba(213, 92, 92, 0.48);
+  outline: 3px solid rgb(213 92 92 / 48%);
   outline-offset: 3px;
 }

Also applies to: 21-26, 68-71

🤖 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 `@app/`[locale]/products/[id]/error.module.css around lines 6 - 16, Actualiza
las declaraciones de color en el fondo del módulo, el contenedor .card y el
estado focus-visible del botón, reemplazando todas las formas rgba() por la
sintaxis moderna rgb() con el canal alfa expresado como porcentaje. Conserva
exactamente los mismos valores visuales y gradientes.

Source: Linters/SAST tools

modules/cart/presentation/components/cart-view.tsx (1)

311-327: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Evita llamadas duplicadas a buildCustomizationHref.

Se está llamando a la función buildCustomizationHref dos veces consecutivas con los mismos argumentos en este render. Puedes utilizar una función anónima autoejecutable (IIFE) para calcular el resultado una sola vez.

♻️ Refactor sugerido
-                {labels.customizationEditFromCart &&
-                  buildCustomizationHref(
-                    locale,
-                    item.productId,
-                    item.customization,
-                    item.id,
-                  ) && (
-                    <Link
-                      href={
-                        buildCustomizationHref(
-                          locale,
-                          item.productId,
-                          item.customization,
-                          item.id,
-                        ) ?? '#'
-                      }
-                      className={styles.editLink}
-                    >
-                      {labels.customizationEditFromCart}
-                    </Link>
-                  )}
+                {(() => {
+                  const editHref = buildCustomizationHref(
+                    locale,
+                    item.productId,
+                    item.customization,
+                    item.id,
+                  );
+                  return labels.customizationEditFromCart && editHref ? (
+                    <Link href={editHref} className={styles.editLink}>
+                      {labels.customizationEditFromCart}
+                    </Link>
+                  ) : null;
+                })()}
🤖 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 `@modules/cart/presentation/components/cart-view.tsx` around lines 311 - 327,
Actualiza el render alrededor de buildCustomizationHref para calcular el enlace
una sola vez por elemento, reutilizando ese resultado tanto en la condición como
en la prop href del componente Link. Puedes encapsular la evaluación en una
IIFE, manteniendo el comportamiento actual y el fallback a '#' cuando no haya
URL.
🤖 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 `@app/`[locale]/profile/page.tsx:
- Around line 3-4: Modifica ProfilePage para que no consulte directamente el
repositorio: introduce un caso de uso de aplicación como GetUserProfileUseCase,
define la interfaz de puerto necesaria en la capa de dominio/aplicación y mueve
la implementación concreta al adaptador de infraestructura. Registra y resuelve
el caso de uso mediante container en el composition root, haciendo que la página
dependa únicamente de ese caso de uso y conserve el comportamiento actual del
perfil.

In `@app/`[locale]/profile/profile-form.tsx:
- Around line 45-58: Update the address handling in the profile form so clearing
every address field sends an explicit deletion value instead of omitting address
from the PATCH. Preserve omission when the user made no address change, and
update the corresponding request schema/API handling to distinguish “unchanged”
from “delete” while retaining normal address updates.

In `@modules/cart/presentation/components/cart-view.tsx`:
- Around line 229-236: Actualiza el enlace del botón `ctaButton` en el
componente de vista del carrito para construir la ruta con `locale` sin la barra
final, de modo que genere `'/es'` en lugar de `'/es/'`; conserva intactos el
texto `labels.browseProducts` y el resto de la navegación.

In `@tests/unit/app/`[locale]/profile/profile-form.test.tsx:
- Around line 40-72: Amplía las pruebas de ProfileForm alrededor de las
mutaciones PATCH y DELETE para comprobar que, cuando la respuesta falla, se
muestra el mensaje de error y termina el estado de carga. Añade también un caso
que vacíe completamente la dirección y verifique el payload o comportamiento
esperado para valores vacíos. Conserva las aserciones existentes sobre los
métodos PATCH y DELETE en mockFetch.

---

Nitpick comments:
In `@app/`[locale]/products/[id]/error.module.css:
- Around line 6-16: Actualiza las declaraciones de color en el fondo del módulo,
el contenedor .card y el estado focus-visible del botón, reemplazando todas las
formas rgba() por la sintaxis moderna rgb() con el canal alfa expresado como
porcentaje. Conserva exactamente los mismos valores visuales y gradientes.

In `@modules/cart/presentation/components/cart-view.tsx`:
- Around line 311-327: Actualiza el render alrededor de buildCustomizationHref
para calcular el enlace una sola vez por elemento, reutilizando ese resultado
tanto en la condición como en la prop href del componente Link. Puedes
encapsular la evaluación en una IIFE, manteniendo el comportamiento actual y el
fallback a '#' cuando no haya URL.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e04a3e6b-036b-41fa-8bd0-fe19f134e7c2

📥 Commits

Reviewing files that changed from the base of the PR and between ee15f32 and e5c77ab.

📒 Files selected for processing (29)
  • app/[locale]/admin/sellers/page.tsx
  • app/[locale]/auth/signin/page.tsx
  • app/[locale]/auth/signup/page.tsx
  • app/[locale]/layout.tsx
  • app/[locale]/orders/page.tsx
  • app/[locale]/products/[id]/customization-experience.tsx
  • app/[locale]/products/[id]/error.module.css
  • app/[locale]/products/[id]/error.tsx
  • app/[locale]/products/[id]/page.tsx
  • app/[locale]/profile/page.tsx
  • app/[locale]/profile/profile-form.tsx
  • app/[locale]/seller/orders/page.tsx
  • app/[locale]/seller/products/page.tsx
  • modules/cart/presentation/components/cart-view.tsx
  • modules/products/application/get-product-by-id-use-case.ts
  • shared/i18n/locales/cat.json
  • shared/i18n/locales/es.json
  • shared/layout/header-nav.tsx
  • shared/layout/login-modal.tsx
  • shared/ui/pagination.tsx
  • tests/unit/app/[locale]/auth/signin/signin-page.test.tsx
  • tests/unit/app/[locale]/products/[id]/customization-experience.test.tsx
  • tests/unit/app/[locale]/products/[id]/error.test.tsx
  • tests/unit/app/[locale]/products/[id]/page.test.tsx
  • tests/unit/app/[locale]/profile/profile-form.test.tsx
  • tests/unit/app/[locale]/profile/profile-page.test.tsx
  • tests/unit/app/cart/cart-view.test.tsx
  • tests/unit/modules/presentation/components/login-modal.test.tsx
  • tests/unit/modules/products/application/get-product-by-id-use-case.test.ts

Comment thread app/[locale]/profile/page.tsx
Comment thread app/[locale]/profile/profile-form.tsx Outdated
Comment on lines 229 to 236
<div className={styles.empty}>
<h2>{labels.emptyTitle}</h2>
<p>{labels.emptyDescription}</p>
<a href={`/${locale}/`} className={styles.ctaButton}>
<Link href={`/${locale}/`} className={styles.ctaButton}>
{labels.browseProducts}
</a>
</Link>
</div>
);

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Elimina la barra final (trailing slash) para alinear el enlace con las pruebas.

El test unitario en cart-view.test.tsx fue actualizado en este PR para esperar '/es' en lugar de '/es/'. Mantener la barra final aquí causará que la aserción del test falle, además de generar inconsistencias con la navegación del logo en el layout principal.

🐛 Fix sugerido
-        <Link href={`/${locale}/`} className={styles.ctaButton}>
+        <Link href={`/${locale}`} className={styles.ctaButton}>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div className={styles.empty}>
<h2>{labels.emptyTitle}</h2>
<p>{labels.emptyDescription}</p>
<a href={`/${locale}/`} className={styles.ctaButton}>
<Link href={`/${locale}/`} className={styles.ctaButton}>
{labels.browseProducts}
</a>
</Link>
</div>
);
<div className={styles.empty}>
<h2>{labels.emptyTitle}</h2>
<p>{labels.emptyDescription}</p>
<Link href={`/${locale}`} className={styles.ctaButton}>
{labels.browseProducts}
</Link>
</div>
);
🤖 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 `@modules/cart/presentation/components/cart-view.tsx` around lines 229 - 236,
Actualiza el enlace del botón `ctaButton` en el componente de vista del carrito
para construir la ruta con `locale` sin la barra final, de modo que genere
`'/es'` en lugar de `'/es/'`; conserva intactos el texto `labels.browseProducts`
y el resto de la navegación.

Comment on lines +40 to +72
it('preserves profile PATCH mutations', async () => {
const user = userEvent.setup();
mockFetch.mockResolvedValueOnce({ ok: true, json: async () => ({}) });
render(<ProfileForm locale="es" profile={profile} role="CUSTOMER" />);

await user.clear(screen.getByLabelText('Nombre'));
await user.type(screen.getByLabelText('Nombre'), 'Jane');
await user.click(screen.getByRole('button', { name: 'Enviar' }));

expect(mockFetch).toHaveBeenCalledWith('/api/users/me', {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: expect.stringContaining('"firstName":"Jane"'),
});
});

it('preserves profile DELETE mutations', async () => {
const user = userEvent.setup();
mockFetch.mockResolvedValueOnce({
ok: false,
json: async () => ({ error: 'Failed to delete account' }),
});
render(<ProfileForm locale="es" profile={profile} role="CUSTOMER" />);

await user.click(screen.getByRole('button', { name: 'Eliminar cuenta' }));
await user.click(
screen.getAllByRole('button', { name: 'Eliminar cuenta' })[1],
);

expect(mockFetch).toHaveBeenCalledWith('/api/users/me', {
method: 'DELETE',
});
});

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.

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Completa las pruebas de errores y estados vacíos.

Añade casos que verifiquen el mensaje y el fin de la carga tras fallos de PATCH/DELETE, además del comportamiento al vaciar completamente la dirección. El test de DELETE actual seguiría pasando aunque el error dejara de mostrarse.

As per coding guidelines: «Write tests before implementing business logic, including empty states, invalid inputs, error conditions, and fakes or mocks for infrastructure dependencies.»

🤖 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 `@tests/unit/app/`[locale]/profile/profile-form.test.tsx around lines 40 - 72,
Amplía las pruebas de ProfileForm alrededor de las mutaciones PATCH y DELETE
para comprobar que, cuando la respuesta falla, se muestra el mensaje de error y
termina el estado de carga. Añade también un caso que vacíe completamente la
dirección y verifique el payload o comportamiento esperado para valores vacíos.
Conserva las aserciones existentes sobre los métodos PATCH y DELETE en
mockFetch.

Source: Coding guidelines

@henri318
henri318 merged commit ae5b1dc into main Jul 17, 2026
5 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.

1 participant