feat(admin,products): add seller detail page, product status actions, and confirm modal#101
Conversation
… and confirm modal - Add admin seller detail/edit page with inline form - Add ELIMINATED product status as terminal state with valid transitions - Add ChangeProductStatusUseCase with full validation - Add PATCH /api/products/[id]/status endpoint (ADMIN + DESIGNER) - Add ConfirmModal component using native <dialog> - Add ProductActions with suspend/activate/eliminate buttons - Add status badges to seller and admin products pages - Add eliminate confirmation popup (HTML modal, not alert) - Update seed: link designer@test.com to 728 Store - Update i18n for product statuses, actions, and seller detail - Fix pagination on admin seller products page - Full TDD coverage for all new features
|
Warning Review limit reached
Next review available in: 45 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughSe añade CambiosCiclo de vida de estado de producto y edición de vendedor
Sequence Diagram(s)sequenceDiagram
participant Usuario
participant ProductActions
participant ConfirmModal
participant PATCHHandler as PATCH /api/products/[id]/status
participant UseCase as ChangeProductStatusUseCase
participant ProductRepository
Usuario->>ProductActions: Click en una acción
ProductActions->>ConfirmModal: Abrir confirmación para ELIMINATED
Usuario->>ConfirmModal: Confirmar
ConfirmModal->>ProductActions: onConfirm()
ProductActions->>PATCHHandler: PATCH { status }
PATCHHandler->>UseCase: execute(productId, sellerId, status)
UseCase->>ProductRepository: findById(productId)
ProductRepository-->>UseCase: product
UseCase->>ProductRepository: update(product actualizado)
ProductRepository-->>UseCase: updatedProduct
UseCase-->>PATCHHandler: updatedProduct
PATCHHandler-->>ProductActions: 200 { id, status, updatedAt }
ProductActions->>ProductActions: actualizar estado local / refresh
Esfuerzo estimado de revisión🎯 4 (Complex) | ⏱️ ~60 minutos PRs posiblemente relacionados
Poema
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ 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 |
There was a problem hiding this comment.
Actionable comments posted: 11
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
shared/presentation/components/confirm-modal.module.css (1)
1-75: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winEste archivo sigue rompiendo el pipeline de calidad.
Stylelint ya está fallando aquí por los selectores en camelCase y por la notación de color, así que CI no va a pasar mientras no se ajuste al patrón configurado del repo.
🤖 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 `@shared/presentation/components/confirm-modal.module.css` around lines 1 - 75, La hoja de estilos de confirm-modal está rompiendo Stylelint por usar selectores en camelCase y por la notación de color; ajusta los nombres de clases en confirm-modal.module.css y cualquier referencia relacionada en el componente que use .dialog, .cancelButton, .confirmButton, etc., al patrón de nombres configurado en el repo, y normaliza los colores a la forma que exige la regla de lint.Sources: Linters/SAST tools, Pipeline failures
🧹 Nitpick comments (2)
modules/products/domain/value-objects/product-status.ts (1)
27-42: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winHaz que el mapa sea exhaustivo a nivel de tipos.
Partial<Record<...>>hace que una omisión accidental se interprete igual que un estado terminal intencional. Si más adelante añadís otroProductStatus, TypeScript no avisará y ese estado quedará terminal por defecto. Aquí compensa tiparlo comoRecord<Exclude<ProductStatus, ProductStatus.ELIMINATED>, readonly ProductStatus[]>para dejarELIMINATEDcomo excepción explícita.🤖 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/products/domain/value-objects/product-status.ts` around lines 27 - 42, The VALID_TRANSITIONS map in product-status.ts is typed too loosely with Partial<Record<...>>, so missing statuses can be mistaken for intentional terminal states. Update the type on VALID_TRANSITIONS to a fully exhaustive Record over all non-terminal ProductStatus values, keeping ProductStatus.ELIMINATED as the explicit exception, and ensure the existing DRAFT, ACTIVE, and ARCHIVED entries still satisfy the stricter type.tests/unit/app/[locale]/seller/products/product-actions.test.tsx (1)
35-110: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAñade una prueba del flujo real de eliminación.
La suite no verifica que pulsar
Eliminateabra el modal y que elPATCHsolo salga tras confirmar, ni que cancelar lo evite. Ese es el camino nuevo más frágil del componente y ahora mismo puede romperse sin que fallen los tests.🤖 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]/seller/products/product-actions.test.tsx around lines 35 - 110, The ProductActions test suite only covers the status-change click path and misses the real elimination flow. Add an interaction test around ProductActions that renders an ARCHIVED product, clicks the Eliminate button, verifies the confirmation modal opens, then confirms to assert the PATCH request is sent only after confirmation; also add the cancel path to ensure dismissing the modal does not call fetch. Use the existing ProductActions component, the Eliminate button, and the modal/confirm controls to locate the flow.
🤖 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]/admin/sellers/[sellerId]/page.module.css:
- Around line 11-18: This stylesheet is failing Stylelint because several class
selectors still use camelCase and some alpha colors use decimal notation. Update
the affected selectors in page.module.css (including backLink and the other
class names flagged in this module) to the configured kebab-case pattern, and
change all alpha values like 0.08 and 0.25 to the required percentage notation.
Make the edits across the same CSS module so the lint rules pass consistently.
In `@app/`[locale]/admin/sellers/[sellerId]/products/page.module.css:
- Around line 174-200: Rename the CSS module selector .statusBadge to kebab-case
to satisfy selector-class-pattern, and update every reference in the products
page to match the new class name. Use the existing status badge styling block in
page.module.css and the class usage in the page component (the span rendering
product status) to keep the class name consistent and prevent lint/CI failures.
In `@app/`[locale]/admin/sellers/[sellerId]/seller-detail-form.tsx:
- Around line 66-74: The fallback error message in seller save handling is
hardcoded, so it bypasses localization when `fetch` fails or the response has no
usable text. Update `SellerDetailForm` to source this fallback from the same
locale dictionary used for `saveLabel` and `savedLabel`, and use that translated
string in the `catch` path and any `throw new Error(...)` fallback so `setError`
always shows a localized message.
In `@app/`[locale]/admin/sellers/page.module.css:
- Around line 191-209: The `.editLink` selector is failing the
`selector-class-pattern` lint because it is not kebab-case. Rename the CSS class
in `page.module.css` to `.edit-link` and update the matching class reference in
`app/[locale]/admin/sellers/page.tsx` (where the sellers page uses this style)
so the component and stylesheet stay in sync.
In `@app/`[locale]/seller/products/page.module.css:
- Around line 163-189: The .statusBadge selector is violating the repo’s
selector-class-pattern naming convention and is causing lint failures. Rename
the class in this stylesheet to match the configured pattern and update any
corresponding references in the seller products page styles/components that use
statusBadge, while keeping the existing data-status variants for active, draft,
archived, and eliminated aligned with the new class name.
In `@app/`[locale]/seller/products/page.tsx:
- Around line 163-182: The product status badge can become stale because the
table row still renders from the server-provided product.status while
ProductActions only updates its own local state. Update the flow so the row
reflects the patched status after activate/suspend/delete, either by lifting the
status state into the parent table or by triggering a route refresh/invalidation
from ProductActions after the mutation; use ProductActions, the status badge
render, and the setStatus mutation path to keep the row and actions in sync.
In `@app/`[locale]/seller/products/product-actions.tsx:
- Around line 52-53: After the successful PATCH in ProductActions, the update
only calls setStatus with data.status and leaves the parent row stale. Update
the parent product state as well (or trigger a row refresh) from the same
success path so any UI still reading product.status from the page stays in sync
with the new status immediately after save.
In `@shared/i18n/dictionary-context.tsx`:
- Around line 7-13: The SellerDetailDictionary contract only includes success
strings, so the save-failure path in seller-detail-form.tsx still falls back to
a hardcoded English message. Add a new i18n key for the save error to
SellerDetailDictionary and then update the save flow in seller-detail-form.tsx
to use that dictionary entry instead of "Failed to save seller", keeping the new
seller detail screen fully localized.
In `@shared/presentation/components/confirm-modal.tsx`:
- Around line 29-40: The ConfirmModal logic is unmounting the <dialog> before
the close path runs, so the native close behavior is skipped. Update
confirm-modal.tsx in the ConfirmModal component so the dialog stays mounted even
when open becomes false, let the useEffect control showModal()/close() via
dialogRef, and remove the early return that nulls the component before
dialog.close() can execute.
In `@tests/unit/app/api/products/`[id]/status/route.test.ts:
- Around line 9-25: The test setup is missing a mock for getUserLookup(), so the
handler fails before reaching the intended status-route cases. Add a hoisted
mock for container.getUserLookup() that returns an object with findById, and
wire it into the existing mocks alongside getSessionMock, findByIdMock, and
updateMock so the route test can exercise the 400/403/404/200 paths correctly.
- Around line 94-103: The module-load wiring test for PATCH only verifies the
first requireRole argument, so it can miss removal of ADMIN from the route
guard. Update the test in route.test.ts around the route authorization block to
assert that route wiring for PATCH includes both ADMIN and DESIGNER in the
requireRole call(s), using the existing requireRoleMock calls captured from the
PATCH export so the contract is checked explicitly instead of only checking the
first role.
---
Outside diff comments:
In `@shared/presentation/components/confirm-modal.module.css`:
- Around line 1-75: La hoja de estilos de confirm-modal está rompiendo Stylelint
por usar selectores en camelCase y por la notación de color; ajusta los nombres
de clases en confirm-modal.module.css y cualquier referencia relacionada en el
componente que use .dialog, .cancelButton, .confirmButton, etc., al patrón de
nombres configurado en el repo, y normaliza los colores a la forma que exige la
regla de lint.
---
Nitpick comments:
In `@modules/products/domain/value-objects/product-status.ts`:
- Around line 27-42: The VALID_TRANSITIONS map in product-status.ts is typed too
loosely with Partial<Record<...>>, so missing statuses can be mistaken for
intentional terminal states. Update the type on VALID_TRANSITIONS to a fully
exhaustive Record over all non-terminal ProductStatus values, keeping
ProductStatus.ELIMINATED as the explicit exception, and ensure the existing
DRAFT, ACTIVE, and ARCHIVED entries still satisfy the stricter type.
In `@tests/unit/app/`[locale]/seller/products/product-actions.test.tsx:
- Around line 35-110: The ProductActions test suite only covers the
status-change click path and misses the real elimination flow. Add an
interaction test around ProductActions that renders an ARCHIVED product, clicks
the Eliminate button, verifies the confirmation modal opens, then confirms to
assert the PATCH request is sent only after confirmation; also add the cancel
path to ensure dismissing the modal does not call fetch. Use the existing
ProductActions component, the Eliminate button, and the modal/confirm controls
to locate the flow.
🪄 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: 8d6cf804-a307-4266-b927-4bfccdb5651f
📒 Files selected for processing (30)
app/[locale]/admin/sellers/[sellerId]/page.module.cssapp/[locale]/admin/sellers/[sellerId]/page.tsxapp/[locale]/admin/sellers/[sellerId]/products/page.module.cssapp/[locale]/admin/sellers/[sellerId]/products/page.tsxapp/[locale]/admin/sellers/[sellerId]/seller-detail-form.tsxapp/[locale]/admin/sellers/page.module.cssapp/[locale]/admin/sellers/page.tsxapp/[locale]/seller/products/page.module.cssapp/[locale]/seller/products/page.tsxapp/[locale]/seller/products/product-actions.module.cssapp/[locale]/seller/products/product-actions.tsxapp/api/products/[id]/status/route.tsmodules/products/application/change-product-status-use-case.tsmodules/products/domain/value-objects/product-status.tsmodules/products/presentation/schemas/change-product-status-schema.tsprisma/migrations/20260623140000_restore_category_slug_index/migration.sqlprisma/seed.tsshared/i18n/dictionary-context.tsxshared/i18n/locales/cat.jsonshared/i18n/locales/es.jsonshared/presentation/components/confirm-modal.module.cssshared/presentation/components/confirm-modal.tsxtests/unit/app/[locale]/admin/sellers/[sellerId]/page.test.tsxtests/unit/app/[locale]/admin/sellers/[sellerId]/products/page.test.tsxtests/unit/app/[locale]/admin/sellers/[sellerId]/seller-detail-form.test.tsxtests/unit/app/[locale]/admin/sellers/page.test.tsxtests/unit/app/[locale]/seller/products/page.test.tsxtests/unit/app/[locale]/seller/products/product-actions.test.tsxtests/unit/app/api/products/[id]/status/route.test.tstests/unit/modules/products/application/change-product-status-use-case.test.ts
| .backLink { | ||
| display: inline-flex; | ||
| margin-bottom: var(--spacing-sm); | ||
| color: var(--color-green-dark); | ||
| font-weight: var(--font-weight-medium); | ||
| } | ||
|
|
||
| .backLink:hover { |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Este módulo no pasa las reglas de Stylelint configuradas.
Ahora mismo hay errores por selector-class-pattern (selectores en camelCase) y alpha-value-notation (0.08/0.25), así que el lint seguirá fallando hasta normalizar esos selectores y valores alpha.
Also applies to: 41-41, 44-49, 57-57, 69-69, 72-72, 104-111
🧰 Tools
🪛 Stylelint (17.14.0)
[error] 11-11: Expected class selector ".backLink" to be kebab-case (selector-class-pattern)
(selector-class-pattern)
[error] 18-18: Expected class selector ".backLink" to be kebab-case (selector-class-pattern)
(selector-class-pattern)
🤖 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]/admin/sellers/[sellerId]/page.module.css around lines 11 - 18,
This stylesheet is failing Stylelint because several class selectors still use
camelCase and some alpha colors use decimal notation. Update the affected
selectors in page.module.css (including backLink and the other class names
flagged in this module) to the configured kebab-case pattern, and change all
alpha values like 0.08 and 0.25 to the required percentage notation. Make the
edits across the same CSS module so the lint rules pass consistently.
Source: Linters/SAST tools
| .statusBadge { | ||
| display: inline-block; | ||
| padding: 0.2rem 0.6rem; | ||
| border-radius: 4px; | ||
| font-size: 0.8rem; | ||
| font-weight: var(--font-weight-medium); | ||
| } | ||
|
|
||
| .statusBadge[data-status='active'] { | ||
| background: var(--color-green-light); | ||
| color: var(--color-green-dark); | ||
| } | ||
|
|
||
| .statusBadge[data-status='draft'] { | ||
| background: var(--color-lila); | ||
| color: var(--color-white); | ||
| } | ||
|
|
||
| .statusBadge[data-status='archived'] { | ||
| background: var(--color-coral); | ||
| color: var(--color-white); | ||
| } | ||
|
|
||
| .statusBadge[data-status='eliminated'] { | ||
| background: var(--color-gray); | ||
| color: var(--color-white); | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Renombra .statusBadge para no romper el lint.
La regla selector-class-pattern exige kebab-case y este selector falla en las cinco apariciones del bloque. Si no se renombra aquí y en el uso de la página, este cambio seguirá rompiendo CI.
💡 Cambio propuesto
-.statusBadge {
+.status-badge {
display: inline-block;
padding: 0.2rem 0.6rem;
border-radius: 4px;
font-size: 0.8rem;
font-weight: var(--font-weight-medium);
}
-.statusBadge[data-status='active'] {
+.status-badge[data-status='active'] {
background: var(--color-green-light);
color: var(--color-green-dark);
}
-.statusBadge[data-status='draft'] {
+.status-badge[data-status='draft'] {
background: var(--color-lila);
color: var(--color-white);
}
-.statusBadge[data-status='archived'] {
+.status-badge[data-status='archived'] {
background: var(--color-coral);
color: var(--color-white);
}
-.statusBadge[data-status='eliminated'] {
+.status-badge[data-status='eliminated'] {
background: var(--color-gray);
color: var(--color-white);
}<span className={styles['status-badge']} data-status={product.status.toLowerCase()}>🧰 Tools
🪛 Stylelint (17.14.0)
[error] 174-174: Expected class selector ".statusBadge" to be kebab-case (selector-class-pattern)
(selector-class-pattern)
[error] 182-182: Expected class selector ".statusBadge" to be kebab-case (selector-class-pattern)
(selector-class-pattern)
[error] 187-187: Expected class selector ".statusBadge" to be kebab-case (selector-class-pattern)
(selector-class-pattern)
[error] 192-192: Expected class selector ".statusBadge" to be kebab-case (selector-class-pattern)
(selector-class-pattern)
[error] 197-197: Expected class selector ".statusBadge" to be kebab-case (selector-class-pattern)
(selector-class-pattern)
🤖 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]/admin/sellers/[sellerId]/products/page.module.css around lines
174 - 200, Rename the CSS module selector .statusBadge to kebab-case to satisfy
selector-class-pattern, and update every reference in the products page to match
the new class name. Use the existing status badge styling block in
page.module.css and the class usage in the page component (the span rendering
product status) to keep the class name consistent and prevent lint/CI failures.
Source: Linters/SAST tools
| .editLink { | ||
| display: inline-flex; | ||
| align-items: center; | ||
| gap: var(--spacing-xs); | ||
| padding: 0.35rem 0.8rem; | ||
| border: 1px solid var(--color-green-dark); | ||
| border-radius: 4px; | ||
| color: var(--color-green-dark); | ||
| font-size: 0.8rem; | ||
| font-weight: var(--font-weight-medium); | ||
| transition: | ||
| background 0.15s ease, | ||
| color 0.15s ease; | ||
| } | ||
|
|
||
| .editLink:hover { | ||
| background: var(--color-green-dark); | ||
| color: var(--color-white); | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Renombra esta clase a kebab-case para pasar el lint.
Stylelint ya está marcando este bloque por selector-class-pattern. Aquí conviene usar algo como .edit-link y actualizar el acceso correspondiente en app/[locale]/admin/sellers/page.tsx.
🧰 Tools
🪛 Stylelint (17.14.0)
[error] 191-191: Expected class selector ".editLink" to be kebab-case (selector-class-pattern)
(selector-class-pattern)
[error] 206-206: Expected class selector ".editLink" to be kebab-case (selector-class-pattern)
(selector-class-pattern)
🤖 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]/admin/sellers/page.module.css around lines 191 - 209, The
`.editLink` selector is failing the `selector-class-pattern` lint because it is
not kebab-case. Rename the CSS class in `page.module.css` to `.edit-link` and
update the matching class reference in `app/[locale]/admin/sellers/page.tsx`
(where the sellers page uses this style) so the component and stylesheet stay in
sync.
Source: Linters/SAST tools
| .statusBadge { | ||
| display: inline-block; | ||
| padding: 0.2rem 0.6rem; | ||
| border-radius: 4px; | ||
| font-size: 0.8rem; | ||
| font-weight: var(--font-weight-medium); | ||
| } | ||
|
|
||
| .statusBadge[data-status='active'] { | ||
| background: var(--color-green-light); | ||
| color: var(--color-green-dark); | ||
| } | ||
|
|
||
| .statusBadge[data-status='draft'] { | ||
| background: var(--color-lila); | ||
| color: var(--color-white); | ||
| } | ||
|
|
||
| .statusBadge[data-status='archived'] { | ||
| background: var(--color-coral); | ||
| color: var(--color-white); | ||
| } | ||
|
|
||
| .statusBadge[data-status='eliminated'] { | ||
| background: var(--color-gray); | ||
| color: var(--color-white); | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Estos selectores no pasan la regla de naming del repo.
statusBadge está chocando con selector-class-pattern, así que esta hoja seguirá fallando el lint mientras no se adapte a la convención configurada.
🧰 Tools
🪛 Stylelint (17.14.0)
[error] 163-163: Expected class selector ".statusBadge" to be kebab-case (selector-class-pattern)
(selector-class-pattern)
[error] 171-171: Expected class selector ".statusBadge" to be kebab-case (selector-class-pattern)
(selector-class-pattern)
[error] 176-176: Expected class selector ".statusBadge" to be kebab-case (selector-class-pattern)
(selector-class-pattern)
[error] 181-181: Expected class selector ".statusBadge" to be kebab-case (selector-class-pattern)
(selector-class-pattern)
[error] 186-186: Expected class selector ".statusBadge" to be kebab-case (selector-class-pattern)
(selector-class-pattern)
🤖 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]/seller/products/page.module.css around lines 163 - 189, The
.statusBadge selector is violating the repo’s selector-class-pattern naming
convention and is causing lint failures. Rename the class in this stylesheet to
match the configured pattern and update any corresponding references in the
seller products page styles/components that use statusBadge, while keeping the
existing data-status variants for active, draft, archived, and eliminated
aligned with the new class name.
Source: Linters/SAST tools
| export interface SellerDetailDictionary { | ||
| editTitle: string; | ||
| nameLabel: string; | ||
| descriptionLabel: string; | ||
| save: string; | ||
| saved: string; | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Añade una clave i18n para el error de guardado.
seller-detail-form.tsx:33-79 todavía cae en "Failed to save seller" cuando falla el PATCH, y este contrato solo cubre el estado de éxito (save/saved). Sin una clave aquí, la pantalla nueva queda parcialmente en inglés.
🤖 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 `@shared/i18n/dictionary-context.tsx` around lines 7 - 13, The
SellerDetailDictionary contract only includes success strings, so the
save-failure path in seller-detail-form.tsx still falls back to a hardcoded
English message. Add a new i18n key for the save error to SellerDetailDictionary
and then update the save flow in seller-detail-form.tsx to use that dictionary
entry instead of "Failed to save seller", keeping the new seller detail screen
fully localized.
…s change, fix dialog close timing - SellerDetailForm: add errorLabel prop for localized error fallback instead of hardcoded English string - ProductActions: call router.refresh() after successful status change to sync parent server component - ConfirmModal: remove early return that unmounted dialog before native close() could execute
Summary
Changes
Test Plan
pm run typecheck\ passes
Notes
Slice D of the admin-seller-products SDD change. Slices A/B were merged in PR #96, Slice C in PR #99.
Summary by CodeRabbit