feat(orders): ORDERS-7681 add Cancel return button to return-detailsjs page#2688
feat(orders): ORDERS-7681 add Cancel return button to return-detailsjs page#2688jpajar wants to merge 2 commits into
Conversation
34bc18e to
38101ea
Compare
5ca4ef2 to
be004b0
Compare
There was a problem hiding this comment.
Pull request overview
Adds shopper-facing support for cancelling an OPEN return from the account return-details page, wiring the UI to a Storefront GraphQL cancelReturn mutation and displaying success/error states.
Changes:
- Adds a conditional Cancel return action (OPEN-only) with confirmation modal copy and page-level error container.
- Introduces a dedicated
return-detailspage module that performs thecancelReturnGraphQL call with loading/disabled-button handling. - Adds styles and English translations for the new action and error states; updates page routing to use the new module.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| templates/pages/account/return-details.html | Injects required context, adds cancel UI (OPEN-only), loading overlay, and error container. |
| lang/en.json | Adds UI strings for cancel action, confirmation modal, and error heading. |
| assets/scss/components/stencil/returnDetails/_returnDetails.scss | Styles the new action section and page-level error presentation. |
| assets/js/theme/return-details.js | Implements confirmation modal + Storefront GraphQL cancelReturn request flow and error handling. |
| assets/js/app.js | Routes return-details pages to the new return-details module instead of the generic account bundle. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // The return's entity ID is the `return_id` query param the page is reached with | ||
| // (/account.php?action=view_return&return_id={id}). | ||
| this.returnId = new URLSearchParams(window.location.search).get('return_id'); | ||
|
|
||
| cancelBtn.addEventListener('click', () => this.openCancelModal(cancelBtn)); |
| const getAccount = () => import('./theme/account'); | ||
| const getCreateReturn = () => import('./theme/create-return'); | ||
| const getReturnDetails = () => import('./theme/return-details'); | ||
| const getLogin = () => import('./theme/auth'); |
| this.root = document.querySelector('[data-return-details]'); | ||
| if (!this.root) return; | ||
|
|
||
| // The cancel action is only server-rendered for open returns. | ||
| const cancelBtn = this.root.querySelector('[data-return-cancel]'); | ||
| if (!cancelBtn) return; |
There was a problem hiding this comment.
Just to refresh my memory, what do the early returns here do if I open this page and it returns early without setting up the returnId and without adding the event listener to the cancel button?
There was a problem hiding this comment.
With the guards it will never try to attach an event listener if the cancel button doesn't exist (for non-open returns), and that handler is the only thing that uses the returnId so it should be fine I think 🤔
| if (errorMessages.length) { | ||
| this.showError(errorMessages.join(' ')); | ||
| return; | ||
| } |
There was a problem hiding this comment.
This should probably be an actual length check rather than just the presence of length, given that any calls to join, even with an empty array, will always return a string, even if it's just empty.
| clearError() { | ||
| const errorBox = document.getElementById('return-cancel-error'); | ||
| if (errorBox) errorBox.style.display = 'none'; | ||
| } |
There was a problem hiding this comment.
Should we also wipe the actual content of the error message to prevent anything on the page from picking up on it (as it still exists in the DOM and all that)?
There was a problem hiding this comment.
Yeah thats a fair concern I can do that
|
cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 5b4f55f. Configure here.
What?
This PR introduces the ability for shoppers to Cancel a return that is in
OPENstatus via the new shopper facing returns portal return details pageRequirements
Tickets / Documentation
Add links to any relevant tickets and documentation.
https://bigcommercecloud.atlassian.net/browse/ORDERS-7681
Screenshots (if appropriate)
Screen.Recording.2026-07-01.at.2.55.06.PM.mov
The return ends up cancelled

When the cancelation errors
Screen.Recording.2026-07-01.at.3.25.05.PM.mov
Note
Medium Risk
Mutates order return state through authenticated GraphQL; follows the same pattern as create-return but incorrect authorization or status handling could let shoppers cancel returns they should not.
Overview
Shoppers with OPEN returns can cancel them from the account return-details page instead of only viewing static details.
Return detail routes (
account_return_detail,return_detail) now load a dedicatedreturn-detailsmodule (extending account behavior) that wires a sidebar Cancel return button to a confirmation modal, then calls the Storefront GraphQLcancelReturnmutation using the injected API token andreturn_idfrom the URL. Success reloads the page; failures show a page-level error with loading/disabled state while the request runs.The template adds the cancel action (OPEN only), loading overlay, error region, and context injections; en.json adds cancel copy; SCSS styles the action block and error alert.
Reviewed by Cursor Bugbot for commit 5b4f55f. Bugbot is set up for automated code reviews on this repo. Configure here.