feat: reorder feature#3153
Conversation
|
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. |
eduardoformiga
left a comment
There was a problem hiding this comment.
Good Job! I left some comments in the review :)
|
Warning Rate limit exceeded
⌛ 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. 📝 WalkthroughWalkthroughAdds a reorder flow: new Changes
Sequence DiagramsequenceDiagram
actor User
participant UI as Reorder Button / Dropdown
participant Hook as useReorder
participant API as Cart GraphQL
participant Store as cartStore
participant Browser as Browser/Checkout
User->>UI: Click "Reorder"
UI->>Hook: reorder(order)
Hook->>Hook: Extract & validate items
alt no valid items
Hook-->>UI: Throw ReorderError
else valid items
Hook->>API: ValidateCartMutation(acceptedOffers)
API-->>Hook: Cart data
Hook->>Store: update cartStore
Hook->>Browser: redirectToCheckout(orderFormId?)
Browser->>Browser: Navigate to checkout
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 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 |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/core/src/components/account/orders/MyAccountOrderDetails/MyAccountOrderActions/MyAccountOrderActions.tsx (1)
33-66:⚠️ Potential issue | 🟡 MinorGuard against repeated reorder calls.
handleReorderdoesn’t checkloading, so repeated clicks can trigger overlapping mutations. Use the hook’s loading state to prevent reentry.🔧 Suggested change
- const { reorder } = useReorder() + const { reorder, loading: reorderLoading } = useReorder() ... - const handleReorder = () => { - reorder(order) - } + const handleReorder = () => { + if (reorderLoading) return + reorder(order) + }
🤖 Fix all issues with AI agents
In
`@packages/core/src/components/account/orders/MyAccountOrderDetails/MyAccountReorderButton/MyAccountReorderButton.tsx`:
- Around line 18-23: handleClick currently calls reorder(order) without awaiting
it, so onClick may run before the async reorder completes; make handleClick
async, await the call to reorder(order) (and optionally wrap in try/catch to
surface errors), and only invoke the optional onClick callback after the await
completes (i.e., after reorder resolves) so any dependent logic runs after the
reorder finishes; refer to handleClick, reorder, onClick and order when updating
the implementation.
In `@packages/core/src/sdk/account/useReorder.ts`:
- Around line 61-108: The code sets orderFormId = currentCart.id || '' and
always passes orderNumber into the ValidateCartMutation, which breaks schema
validation when no cart id exists; change the request payload construction in
the function (around currentCart, orderFormId and the ValidateCartMutation
request call) to omit orderNumber when currentCart.id is falsy (or set it to
undefined) so that the order object is only sent with orderNumber when
currentCart.id is present; update any related typing handling for the cart
payload accordingly.
🧹 Nitpick comments (3)
packages/core/src/sdk/error/ReorderError/ReorderError.ts (1)
1-6: Consider addingObject.setPrototypeOffor robust Error subclassing.When extending built-in classes like
Errorin TypeScript, the prototype chain can break in some transpilation targets (ES5), causinginstanceof ReorderErrorto returnfalse. AddingObject.setPrototypeOfensures correct behavior across all environments.♻️ Proposed fix
export default class ReorderError extends Error { constructor(message: string) { super(message) this.name = 'ReorderError' + Object.setPrototypeOf(this, ReorderError.prototype) } }packages/core/src/sdk/cart/redirectToCheckout.ts (1)
3-15: Simplify redundant conditional branches and encode the query parameter.Lines 9 and 13 are identical. The logic can be simplified. Additionally,
orderFormIdshould be URL-encoded for safety, even though it's typically a UUID.♻️ Proposed simplification
export const redirectToCheckout = (orderFormId?: string) => { const isDevEnv = window.location.host.includes('.vtex.app') || window.location.host.includes('localhost') - if (!isDevEnv) { - window.location.href = `${storeConfig.checkoutUrl}` - } else if (orderFormId) { - window.location.href = `${storeConfig.checkoutUrl}?orderFormId=${orderFormId}` - } else { - window.location.href = `${storeConfig.checkoutUrl}` - } + const baseUrl = storeConfig.checkoutUrl + const url = isDevEnv && orderFormId + ? `${baseUrl}?orderFormId=${encodeURIComponent(orderFormId)}` + : baseUrl + + window.location.href = url }packages/core/src/components/account/orders/MyAccountOrderDetails/MyAccountReorderButton/MyAccountReorderButton.tsx (1)
32-32: Consider externalizing the button label for internationalization.The "Reorder" text is hardcoded. If the application supports multiple languages, this string should be externalized using an i18n solution for consistency with the rest of the UI.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In
`@packages/core/src/components/account/orders/MyAccountOrderDetails/MyAccountReorderButton/MyAccountReorderButton.tsx`:
- Around line 18-22: handleClick currently calls onClick regardless because
useReorder's reorder(order) never rejects; update the contract and call site so
onClick only runs on real success: modify useReorder's reorder to either return
a boolean success flag or rethrow errors (pick one), then in
MyAccountReorderButton.handleClick await the reorder result and only call
onClick when the result indicates success (true) or when no error was thrown;
keep the existing try/catch for logging/UX but gate onClick behind the success
check and ensure the unique symbols referenced are useReorder and handleClick
(and the reorder(order) call).
| const handleClick = async () => { | ||
| try { | ||
| await reorder(order) | ||
| onClick?.() | ||
| } catch (error) { |
There was a problem hiding this comment.
onClick executes even when reorder fails.
useReorder catches errors internally, so await reorder(order) always resolves and onClick runs even on failure or missing order. Consider returning a success boolean (or rethrowing) and gating the callback on success.
🔧 Suggested adjustment (paired with useReorder returning a boolean)
- await reorder(order)
- onClick?.()
+ const ok = await reorder(order)
+ if (ok) onClick?.()🤖 Prompt for AI Agents
In
`@packages/core/src/components/account/orders/MyAccountOrderDetails/MyAccountReorderButton/MyAccountReorderButton.tsx`
around lines 18 - 22, handleClick currently calls onClick regardless because
useReorder's reorder(order) never rejects; update the contract and call site so
onClick only runs on real success: modify useReorder's reorder to either return
a boolean success flag or rethrow errors (pick one), then in
MyAccountReorderButton.handleClick await the reorder result and only call
onClick when the result indicates success (true) or when no error was thrown;
keep the existing try/catch for logging/UX but gate onClick behind the success
check and ensure the unique symbols referenced are useReorder and handleClick
(and the reorder(order) call).
There was a problem hiding this comment.
@ArthurTriis1, this suggestion makes sense to me. WDYT?
There was a problem hiding this comment.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In
`@packages/core/src/components/account/orders/MyAccountOrderDetails/MyAccountOrderActions/styles.scss`:
- Around line 15-19: The reorder action is being hidden on mobile because the
standalone MyAccountReorderButton and the dropdown item selector
[data-fs-order-actions-item-reorder] are both set to display:none below the
tablet breakpoint; either restore mobile access by removing or altering the
media("<tablet") rule that hides [data-fs-order-actions-item-reorder] so the
dropdown item remains visible as a fallback when MyAccountReorderButton is
hidden, or if the hide is intentional add an inline code comment next to the
MyAccountReorderButton and [data-fs-order-actions-item-reorder] rules
documenting the rationale and any plan to re-enable on mobile.
4b1b451 to
7885bbd
Compare
## What's the purpose of this pull request? This PR implements the "Reorder" button feature in the My Account order details page, allowing customers to quickly add all items from a previous order back to their cart with a single click. This improves the shopping experience by reducing friction when customers want to repurchase items they've bought before. ## How it works? The feature consists of: 1. **Reorder Button Component** (`MyAccountReorderButton`): A dedicated button component displayed in the order details header that triggers the reorder action. The button is styled as outlined by default and filled on hover, and is hidden on mobile devices. 2. **Reorder Hook** (`useReorder`): A custom hook that handles the reorder logic: - Extracts all items from the order's delivery options - Converts order items to the format required by the checkout API (`IStoreOffer[]`) - Uses the `validateCart` GraphQL mutation to add items to the cart - The mutation automatically handles cart synchronization (replacing existing items with the reordered items) - Updates the local cart store with the validated cart response - Redirects the user to the checkout page after successfully adding items 3. **Integration Points**: - The reorder button is displayed in the order details header alongside other order actions - A "Reorder" option is also available in the `MyAccountOrderActions` dropdown menu - Both trigger the same `useReorder` hook 4. **Cart Synchronization**: When the user already has items in their cart, the `validateCart` mutation handles the synchronization by replacing all existing cart items with the reordered items from the order. 5. **Redirect to Checkout**: After successfully adding items to the cart, users are automatically redirected to the checkout page using the `redirectToCheckout` utility function, which handles both development and production environments. ## How to test it? 1. Navigate to My Account > Orders 2. Open any completed order details page 3. Verify that the "Reorder" button is visible in the order header (desktop/tablet only) 4. Click the "Reorder" button 5. Verify that: - All items from the order are added to the cart - If there were existing items in the cart, they are replaced by the reordered items - The user is redirected to the checkout page - The cart displays the correct items and quantities 6. Test the "Reorder" option in the dropdown menu (three dots icon) - it should work the same way 7. Test on mobile - the reorder button should be hidden, but the dropdown option should still be available 8. Test with an empty cart and with a cart that already has items ### Starters Deploy Preview <!--- Add a link to a deploy preview from `starter.store` with this branch being used. ---> <!--- Tip: You can get an installable version of this branch from the CodeSandbox generated when this PR is created. ---> ## References - **Figma Design**: https://www.figma.com/design/Jyt5kWamjkdPC8xMfeuWfR/My-Account?node-id=5005-80468&p=f&t=lJwhSHXsKzeNhdUS-0 - **Task**: B2BTEAM-2988 - **Checkout API Documentation**: Used `validateCart` mutation to add items to the cart - Related components: - `MyAccountOrderDetails` - Main order details page - `MyAccountReorderButton` - Reorder button component - `MyAccountOrderActions` - Order actions dropdown - `useReorder` - Reorder functionality hook - `redirectToCheckout` - Checkout redirection utility ## Screenshots <img width="993" height="324" alt="Screenshot 2025-12-11 at 17 55 48" src="https://github.com/user-attachments/assets/033842ed-4769-4de1-8dbe-b8335d25bfc8" /> ## Checklist **PR Title and Commit Messages** - [x] PR title and commit messages follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification - Available prefixes: `feat`, `fix`, `chore`, `docs`, `style`, `refactor`, `ci` and `test` **PR Description** - [x] Added a label according to the PR goal - `breaking change`, `bug`, `contributing`, `performance`, `documentation`.. **Dependencies** - [ ] Committed the `pnpm-lock.yaml` file when there were changes to the packages **Documentation** - [x] PR description - [ ] For documentation changes, ping `@Mariana-Caetano` to review and update (Or submit a doc request) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added reorder flow: a Reorder button in order details and a Reorder item in the actions dropdown to quickly recreate previous orders and proceed to checkout. * Reorder button shows loading/disabled state while processing. * **Bug Fixes / Behavior** * Order actions now render consistently; cancellation remains available only when allowed. * **Style** * Updated styles and responsive behavior for order header actions and the reorder button (hidden on smaller viewports). <!-- end of auto-generated comment: release notes by coderabbit.ai -->
What's the purpose of this pull request?
This PR implements the "Reorder" button feature in the My Account order details page, allowing customers to quickly add all items from a previous order back to their cart with a single click. This improves the shopping experience by reducing friction when customers want to repurchase items they've bought before.
How it works?
The feature consists of:
Reorder Button Component (
MyAccountReorderButton): A dedicated button component displayed in the order details header that triggers the reorder action. The button is styled as outlined by default and filled on hover, and is hidden on mobile devices.Reorder Hook (
useReorder): A custom hook that handles the reorder logic:IStoreOffer[])validateCartGraphQL mutation to add items to the cartIntegration Points:
MyAccountOrderActionsdropdown menuuseReorderhookCart Synchronization: When the user already has items in their cart, the
validateCartmutation handles the synchronization by replacing all existing cart items with the reordered items from the order.Redirect to Checkout: After successfully adding items to the cart, users are automatically redirected to the checkout page using the
redirectToCheckoututility function, which handles both development and production environments.How to test it?
Starters Deploy Preview
References
validateCartmutation to add items to the cartMyAccountOrderDetails- Main order details pageMyAccountReorderButton- Reorder button componentMyAccountOrderActions- Order actions dropdownuseReorder- Reorder functionality hookredirectToCheckout- Checkout redirection utilityScreenshots
Checklist
PR Title and Commit Messages
feat,fix,chore,docs,style,refactor,ciandtestPR Description
breaking change,bug,contributing,performance,documentation..Dependencies
pnpm-lock.yamlfile when there were changes to the packagesDocumentation
@Mariana-Caetanoto review and update (Or submit a doc request)Summary by CodeRabbit
New Features
Bug Fixes / Behavior
Style