Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
1e11b3b
feat(orders): ORDERS-7706 add new return page layout
jpajar May 4, 2026
2bbd8d8
feat(returns): ORDERS-7704 condition for new returns on orders page (…
bc-vivekaggarwal May 12, 2026
246d633
Merge pull request #2649 from bigcommerce/ORDERS-7706
jpajar May 8, 2026
1d7375a
feat(returns): ORDERS-7705 condition for new returns on order details…
bc-vivekaggarwal May 12, 2026
01392b8
Merge pull request #2649 from bigcommerce/ORDERS-7706
jpajar May 8, 2026
b5a0c9b
feat(orders): ORDERS-7734 add template for guest return portal
BC-SEven Apr 28, 2026
8498823
feat(returns): ORDERS-7717 - add new returns list ui
bc-bryan May 26, 2026
25cb72f
feat(returns): ORDERS-7717 - use rma number
bc-bryan May 27, 2026
ebc2fce
feat(orders): ORDERS-7734 add template for guest return portal
BC-SEven Apr 28, 2026
9aeda72
feat(returns): ORDERS-7708 new-return page — render items from order …
bc-vivekaggarwal May 27, 2026
e79ca2d
feat(orders): ORDERS-7331 add template for create return page
May 28, 2026
2737dbb
feat(returns): ORDERS-7717 - add CHANGELOG item
bc-bryan May 28, 2026
ac768ab
feat(returns): ORDERS-7717 - address copilot review
bc-bryan May 28, 2026
eb70fd3
Merge pull request #2669 from bigcommerce/ORDERS-7331
matt-evangelidis May 29, 2026
e51401e
Merge pull request #2664 from bigcommerce/ORDERS-7717-returns-pages-v2
bc-bryan Jun 2, 2026
5d1dc06
feat(orders): ORDERS-7718 add return details page layout
jpajar Jun 5, 2026
7c5e352
feat(orders): ORDERS-7718 add status mappping from enum
jpajar Jun 9, 2026
6ebc73c
Merge pull request #2675 from bigcommerce/ORDERS-7718
jpajar Jun 9, 2026
a12175b
Orders 7764 render create return page with context (#2673)
bc-vivekaggarwal Jun 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Draft
- Add new create-return page [#2669](https://github.com/bigcommerce/cornerstone/pull/2669)
- Fix duplicate `id="default_instrument"` on Update Payment Method page [#2661](https://github.com/bigcommerce/cornerstone/pull/2661)
- Respect `available_to_sell` on PDP so the Sold Out alert is hidden and the Add to Cart button stays enabled for backorderable products, and is disabled when quantity exceeds `available_to_sell` [#2659](https://github.com/bigcommerce/cornerstone/pull/2659)
- Updated accessibility features [2656](https://github.com/bigcommerce/cornerstone/pull/2656)
- Adds new guest-return-portal page. [2645](https://github.com/bigcommerce/cornerstone/pull/2645)
- Update 'Ship to' copy for multi address orders [#2655](https://github.com/bigcommerce/cornerstone/pull/2655)
- Fixed typo in category page reset-filters live region handler [#2643](https://github.com/bigcommerce/cornerstone/pull/2643)
- Swap content/data keys in onProductOptionsChanged event detail [#2640](https://github.com/bigcommerce/cornerstone/pull/2640)
- Gate Order Details "Return" button on `settings.returns_v2_enabled` with `settings.returns_enabled` fallback (ORDERS-7705)
- Fix shipment info showing for cancelled orders [#2654](https://github.com/bigcommerce/cornerstone/pull/2654)
- Render backorder prompts on My Account "Your orders" page [#2650](https://github.com/bigcommerce/cornerstone/pull/2650)
- Gate account orders list "Return Items" link on returns settings (ORDERS-7704) [#2653](https://github.com/bigcommerce/cornerstone/pull/2653)
- Added new Return list view (ORDERS-7717) [#2664] (https://github.com/bigcommerce/cornerstone/pull/2664)

## 6.19.1 (04-09-2026)
- Update stencil-utils versionto 6.23.0 [#2638](https://github.com/bigcommerce/cornerstone/pull/2638)
Expand Down
2 changes: 2 additions & 0 deletions assets/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ __webpack_public_path__ = window.__webpack_public_path__; // eslint-disable-line
import Global from './theme/global';

const getAccount = () => import('./theme/account');
const getCreateReturn = () => import('./theme/create-return');
const getLogin = () => import('./theme/auth');
const noop = null;

Expand All @@ -12,6 +13,7 @@ const pageClasses = {
account_addressbook: getAccount,
shippingaddressform: getAccount,
account_new_return: getAccount,
create_return: getCreateReturn,
'add-wishlist': () => import('./theme/wishlist'),
account_recentitems: getAccount,
account_downloaditem: getAccount,
Expand Down
72 changes: 72 additions & 0 deletions assets/js/theme/create-return.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import PageManager from './page-manager';

export default class CreateReturn extends PageManager {
onReady() {
const form = document.querySelector('[data-new-return-form]');
if (!form) return;

this.bindOrderLineItemEvents();
this.bindSubmit(form);
}

bindOrderLineItemEvents() {
// All three selects per row (qty, resolution, reason) trigger a submit-state check.
document.querySelectorAll('.newReturn-orderLineItem select').forEach(sel => {
sel.addEventListener('change', () => this.updateSubmitState());
});
}

updateSubmitState() {
const selectedItems = this.getSelectedItems();
const isValid = selectedItems.length > 0 && selectedItems.every(itemRow => {
const itemId = itemRow.dataset?.itemId;
if (!itemId) return false;
const resolutionEl = document.getElementById(`resolution-${itemId}`);
const reasonEl = document.getElementById(`reason-${itemId}`);
return resolutionEl && resolutionEl.value && reasonEl && reasonEl.value;
});

document.getElementById('return-new-submitBtn').disabled = !isValid;
}

// Returns only row containers (not buttons) with a non-zero quantity selected.
getSelectedItems() {
return [...document.querySelectorAll('.newReturn-orderLineItem')].filter(itemRow => {
const itemId = itemRow.dataset?.itemId;
if (!itemId) return false;
const qtyInput = document.getElementById(`qty-${itemId}`);
return qtyInput && parseInt(qtyInput.value, 10) > 0;
});
}

bindSubmit(form) {
form.addEventListener('submit', event => {
event.preventDefault();
// TODO ORDERS-7715: invoke createReturn Storefront GQL mutation using
// this.buildReturnInput() to get the payload.
});
}

/**
* Builds the createReturn mutation input.
* Called by ORDERS-7715 once the Storefront GQL mutation is wired up.
*
* @returns {{ orderEntityId: number, additionalNote: string, items: Array }}
*/
buildReturnInput() {
return {
orderEntityId: parseInt(this.context.order?.id, 10),
additionalNote: document.querySelector('[data-new-return-note]')?.value || '',
items: this.getSelectedItems().flatMap(itemRow => {
const itemId = itemRow.dataset?.itemId;
if (!itemId) return [];
return [{
lineItemEntityId: parseInt(itemId, 10),
quantity: parseInt(document.getElementById(`qty-${itemId}`)?.value, 10),
resolution: document.getElementById(`resolution-${itemId}`)?.value,
reasonEntityId: document.getElementById(`reason-${itemId}`)?.value,
}];
}),
};
}
}
189 changes: 189 additions & 0 deletions assets/js/theme/return-details.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
import { escape } from 'lodash';
import PageManager from './page-manager';

export default class ReturnDetails extends PageManager {
onReady() {
const root = document.querySelector('[data-return-details]');
if (!root) return;

this.root = root;

// ---------------------------------------------------------------------------
// Hardcoded page data which mirrors the returns-ui Return / Item interface
// Replace with the relevant stencil page context when it is surfaced.
// ---------------------------------------------------------------------------
this.pageData = {
id: '101',
rma: '101',
status: 'OPEN',
opened: 'January 1, 2024',
lastUpdated: 'January 1, 2024',
order: {
id: '222',
currency: 'USD',
},
shipping: {
address: {
fullName: 'John Doe',
address1: '1000 San Marcos Ave',
city: 'Austin',
state: 'TX',
zip: '78702',
country: 'United States',
},
method: 'UPS Ground',
trackingNumber: '1Z370170375602560',
dateShipped: 'May 15, 2024',
},
items: [
{
id: 'i1',
lineItemId: 'li1',
name: 'Product Name',
variant: 'Color: Blue · Size: Large',
thumbnailUrl: 'https://via.placeholder.com/72',
sku: 'SKU-001',
requestedResolution: { type: 'system', label: 'Exchange' },
requestedReason: 'Wrong item received',
quantity: 1,
formatted_price: '$123.99',
status: 'open',
},
{
id: 'i2',
lineItemId: 'li2',
name: 'Product Name',
variant: 'Color: Blue · Size: Large',
thumbnailUrl: 'https://via.placeholder.com/72',
sku: 'SKU-002',
requestedResolution: { type: 'system', label: 'Refund' },
requestedReason: 'Did not like',
quantity: 1,
formatted_price: '$123.99',
status: 'open',
},
{
id: 'i3',
lineItemId: 'li3',
name: 'Product Name',
variant: 'Color: Blue · Size: Large',
thumbnailUrl: 'https://via.placeholder.com/72',
sku: 'SKU-003',
requestedResolution: { type: 'system', label: 'Refund' },
requestedReason: 'Did not like',
quantity: 1,
formatted_price: '$123.99',
status: 'open',
},
],
};

this.renderHeader();
this.renderShipping();
this.renderItems();
this.renderSummary();
}

renderHeader() {
const { rma, status } = this.pageData;
const titleEl = this.root.querySelector('[data-return-title]');
const statusEl = this.root.querySelector('[data-return-status]');

if (titleEl) titleEl.textContent = `Return #${rma}`;
if (statusEl) {
// Map the raw status enum to the localized label injected by the
// template (same labels as the returns list); fall back to the raw value.
const statusLabels = {
OPEN: this.context.returnStatusOpen,
IN_PROGRESS: this.context.returnStatusInProgress,
CLOSED: this.context.returnStatusClosed,
};
statusEl.textContent = statusLabels[status] || status;
statusEl.classList.add(`returnDetails-statusBadge--${status.toLowerCase()}`);
}
}

renderShipping() {
const container = this.root.querySelector('[data-return-shipping]');
if (!container) return;

const { address, method, trackingNumber, dateShipped } = this.pageData.shipping;
const addressLine = [
address.fullName,
address.address1,
`${address.city}, ${address.state} ${address.zip}`,
address.country,
].filter(Boolean).join(', ');
const methodLine = `${method} (${trackingNumber}). Shipped on ${dateShipped}`;

const rows = [
{ label: 'Shipping address', value: addressLine },
{ label: 'Shipping method', value: methodLine },
];

container.innerHTML = rows.map(({ label, value }) => `
<div class="returnDetails-shippingRow">
<dt class="returnDetails-shippingLabel">${escape(label)}</dt>
<dd class="returnDetails-shippingValue">${escape(value)}</dd>
</div>`).join('');
}

renderItems() {
const list = this.root.querySelector('[data-return-items]');
if (!list) return;

const { items } = this.pageData;

list.innerHTML = items.map(item => this.itemTemplate(item)).join('');
}

itemTemplate(item) {
const resolutionLabel = item.requestedResolution ? item.requestedResolution.label : '';

return `
<li class="returnDetails-item" data-item-id="${escape(item.id)}">
<div class="returnDetails-itemThumbnailWrapper">
<img class="returnDetails-itemThumbnail"
src="${escape(item.thumbnailUrl)}"
alt="${escape(item.name)}">
</div>
<div class="returnDetails-itemInfo">
<p class="returnDetails-itemName">${escape(item.name)}</p>
${item.variant ? `<p class="returnDetails-itemVariant">${escape(item.variant)}</p>` : ''}
<p class="returnDetails-itemPrice">${escape(item.formatted_price)}</p>
</div>
<dl class="returnDetails-itemMeta">
<div class="returnDetails-itemMetaRow">
<dt class="returnDetails-itemMetaLabel">Return Quantity:</dt>
<dd class="returnDetails-itemMetaValue">${escape(item.quantity)}</dd>
</div>
<div class="returnDetails-itemMetaRow">
<dt class="returnDetails-itemMetaLabel">Request</dt>
<dd class="returnDetails-itemMetaValue">${escape(resolutionLabel)}</dd>
</div>
<div class="returnDetails-itemMetaRow">
<dt class="returnDetails-itemMetaLabel">Reason</dt>
<dd class="returnDetails-itemMetaValue">${escape(item.requestedReason)}</dd>
</div>
</dl>
</li>`;
}

renderSummary() {
const summary = this.root.querySelector('[data-return-summary]');
if (!summary) return;

const { opened, lastUpdated, order } = this.pageData;
const rows = [
{ label: 'Submitted:', value: opened },
{ label: 'Last update:', value: lastUpdated },
{ label: 'Order#:', value: order.id },
];

summary.innerHTML = rows.map(({ label, value }) => `
<div class="returnDetails-summaryRow">
<dt class="returnDetails-summaryLabel">${escape(label)}</dt>
<dd class="returnDetails-summaryValue">${escape(value)}</dd>
</div>`).join('');
}
}
8 changes: 7 additions & 1 deletion assets/scss/components/_components.scss
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,15 @@
// Write a Review
@import "stencil/writeReview/component";

// Add Return
// Add Return (legacy)
@import "stencil/addReturn/component";

// Return Details
@import "stencil/returnDetails/component";

// Create Return
@import "stencil/createReturn/component";

// Product Carousel
@import "stencil/productCarousel/component";

Expand Down
41 changes: 41 additions & 0 deletions assets/scss/components/stencil/account/_account.scss
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,32 @@
}
}

.account-listItem-summary {
align-items: center;
display: flex;
flex-wrap: wrap;
gap: spacing("single");
justify-content: space-between;
margin-bottom: spacing("single");
}

.account-listItem-summary-main {
align-items: center;
display: flex;
flex: 1 1 auto;
flex-wrap: wrap;
gap: spacing("half");
min-width: 0;

.account-product-title {
margin: 0;
}

.account-orderStatus-label {
margin: 0;
}
}

.account-listShipping {
border-bottom: container("border");
font-weight: fontWeight("bold");
Expand Down Expand Up @@ -341,6 +367,21 @@
padding: spacing("eighth") spacing("third");
}

.account-orderStatus-label--open {
background-color: color("warning", "light");
color: stencilColor("color-textBase");
}

.account-orderStatus-label--inProgress {
background-color: color("success", "light");
color: stencilColor("color-textBase");
}

.account-orderStatus-label--closed {
background-color: color("greys", "lighter");
color: stencilColor("color-textBase");
}

.account-orderStatus-action {
color: stencilColor("color-textSecondary");
display: inline-block;
Expand Down
2 changes: 2 additions & 0 deletions assets/scss/components/stencil/addReturn/_addReturn.scss
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,5 @@
width: grid-calc(6, $total-columns);
}
}


7 changes: 7 additions & 0 deletions assets/scss/components/stencil/createReturn/_component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// =============================================================================
// CREATE RETURN PAGE
// =============================================================================


// Component
@import "createReturn";
Loading