From 1e11b3b7b90c42180a0682e19470132a4931049b Mon Sep 17 00:00:00 2001 From: Jasper Pajar Date: Mon, 4 May 2026 10:24:00 +1000 Subject: [PATCH 01/16] feat(orders): ORDERS-7706 add new return page layout --- assets/js/app.js | 3 +- assets/js/theme/add-return-new.js | 245 +++++++++++++++++ .../stencil/addReturn/_addReturn.scss | 247 ++++++++++++++++++ templates/pages/account/add-return-new.html | 44 ++++ 4 files changed, 538 insertions(+), 1 deletion(-) create mode 100644 assets/js/theme/add-return-new.js create mode 100644 templates/pages/account/add-return-new.html diff --git a/assets/js/app.js b/assets/js/app.js index b9e92bfdc8..2d95c5bef2 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -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 getAddReturnNew = () => import('./theme/add-return-new'); const getLogin = () => import('./theme/auth'); const noop = null; @@ -11,7 +12,7 @@ const pageClasses = { account_order: getAccount, account_addressbook: getAccount, shippingaddressform: getAccount, - account_new_return: getAccount, + account_new_return: getAddReturnNew, 'add-wishlist': () => import('./theme/wishlist'), account_recentitems: getAccount, account_downloaditem: getAccount, diff --git a/assets/js/theme/add-return-new.js b/assets/js/theme/add-return-new.js new file mode 100644 index 0000000000..b735d038a0 --- /dev/null +++ b/assets/js/theme/add-return-new.js @@ -0,0 +1,245 @@ +import { escape } from 'lodash'; +import PageManager from './page-manager'; + +export default class AddReturnNew extends PageManager { + onReady() { + const $form = $('[data-new-return-form]'); + if (!$form.length) return; + + // --------------------------------------------------------------------------- + // Hardcoded page data which mirrors the TypeScript returns-ui interface. + // Replace with Stencil context when it is available. + // --------------------------------------------------------------------------- + this.pageData = { + order: { + id: '101', + datePlaced: new Date('2024-01-01'), + status: 'Completed', + currency: 'AUD', + isTaxInclusive: true, + shipping: { + address: { + fullName: 'Jane Smith', + address1: '1-3 Smail Street', + city: 'Ultimo', + state: 'NSW', + zip: '2007', + country: 'Australia', + }, + method: 'Australia Post', + dateShipped: 'May 15, 2024', + trackingNumber: '7E27315406641', + }, + items: [ + { + id: 'item-1', + name: 'Product Name', + variant: 'Blue / Black / Green', + sku: 'SKU-001', + quantity: 1, + returnableQuantity: 1, + thumbnailUrl: '', + totalIncTax: 123.99, + totalExTax: 110.71, + }, + { + id: 'item-2', + name: 'Product Name', + variant: 'Blue / Black / Green', + sku: 'SKU-002', + quantity: 1, + returnableQuantity: 1, + thumbnailUrl: '', + totalIncTax: 123.99, + totalExTax: 110.71, + }, + { + id: 'item-3', + name: 'Product Name', + variant: 'Blue / Black / Green', + sku: 'SKU-003', + quantity: 1, + returnableQuantity: 1, + thumbnailUrl: '', + totalIncTax: 123.99, + totalExTax: 110.71, + }, + ], + }, + reasons: [ + { id: 'reason-1', nameForMerchant: 'Damaged or defective', active: true }, + { id: 'reason-2', nameForMerchant: 'Wrong item received', active: true }, + { id: 'reason-3', nameForMerchant: 'Changed my mind', active: true }, + { id: 'reason-4', nameForMerchant: 'Item not as described', active: true }, + { id: 'reason-5', nameForMerchant: 'Arrived too late', active: true }, + ], + resolutions: [ + { resolutionType: 'Refund' }, + { resolutionType: 'Exchange' }, + { resolutionType: 'Store Credit' }, + ], + }; + + this.renderHeader(); + this.renderShippingAddress(); + this.renderShippingMethod(); + this.renderOrderLineItems(); + this.bindSubmit($form); + } + + renderHeader() { + const { order } = this.pageData; + const dateLabel = order.datePlaced.toLocaleDateString('en-AU', { year: 'numeric', month: 'long', day: 'numeric' }); + + document.getElementById('return-new-orderId').textContent = order.id; + document.getElementById('return-new-statusBadge').textContent = order.status.toUpperCase(); + document.getElementById('return-new-datePlaced').textContent = `Order date: ${dateLabel}`; + } + + renderShippingAddress() { + const { address } = this.pageData.order.shipping; + const shippingAddressHtml = `

Shipping address

+

${escape(address.fullName)}

+

${escape(address.address1)}

+

${escape(address.city)}, ${escape(address.state)} ${escape(address.zip)}

+

${escape(address.country)}

`; + + document.getElementById('return-new-shippingAddress').innerHTML = shippingAddressHtml; + } + + renderShippingMethod() { + const { shipping } = this.pageData.order; + const shippingMethodHtml = `

Shipping method

+

${escape(shipping.method)}

+

Shipped on ${escape(shipping.dateShipped)}

+

${escape(shipping.trackingNumber)}

`; + + document.getElementById('return-new-shippingMethod').innerHTML = shippingMethodHtml; + } + + renderOrderLineItems() { + const { order, reasons, resolutions } = this.pageData; + + const resolutionOptions = [ + '', + ...resolutions.map(resolution => { + const optionValue = this.isCustomResolution(resolution) ? escape(resolution.id) : escape(resolution.resolutionType); + const optionLabel = this.isCustomResolution(resolution) ? escape(resolution.nameForMerchant) : escape(resolution.resolutionType); + return ``; + }), + ].join(''); + + const reasonOptions = [ + '', + ...reasons + .filter(reason => reason.active) + .map(reason => ``), + ].join(''); + + const orderLineItemsHtml = order.items.map(item => { + const price = new Intl.NumberFormat('en-AU', { style: 'currency', currency: order.currency }).format(item.totalIncTax); + const thumbnailHtml = item.thumbnailUrl + ? `${escape(item.name)}` + : '
No image
'; + + return ` +
+ ${thumbnailHtml} +
+

${escape(item.name)}

+

${escape(item.variant)}

+

${price} x ${item.quantity}

+
+
+
+ + + +
+ + +
+
`; + }).join(''); + + document.getElementById('return-new-itemsList').innerHTML = orderLineItemsHtml; + this.bindOrderLineItemEvents(); + } + + bindOrderLineItemEvents() { + document.querySelectorAll('.form-increment .button--icon').forEach(button => { + button.addEventListener('click', () => { + const itemId = button.getAttribute('data-item-id'); + const action = button.getAttribute('data-action'); + const item = this.pageData.order.items.find(orderLineItem => orderLineItem.id === itemId); + const quantityInput = document.getElementById(`qty-${itemId}`); + let quantity = parseInt(quantityInput.value, 10); + + if (action === 'inc' && quantity < item.returnableQuantity) quantity++; + else if (action === 'dec' && quantity > 0) quantity--; + + quantityInput.value = quantity; + document.querySelector(`[data-action="dec"][data-item-id="${itemId}"]`).disabled = quantity === 0; + document.querySelector(`[data-action="inc"][data-item-id="${itemId}"]`).disabled = quantity >= item.returnableQuantity; + + this.updateSubmitState(); + }); + }); + + document.querySelectorAll('.newReturn-select').forEach(selectElement => { + selectElement.addEventListener('change', () => this.updateSubmitState()); + }); + } + + updateSubmitState() { + const selectedItems = this.pageData.order.items.filter(item => parseInt(document.getElementById(`qty-${item.id}`).value, 10) > 0); + + const isValid = selectedItems.length > 0 && selectedItems.every(item => ( + document.getElementById(`resolution-${item.id}`).value + && document.getElementById(`reason-${item.id}`).value + )); + + document.getElementById('return-new-submitBtn').disabled = !isValid; + } + + bindSubmit($form) { + $form.on('submit', event => { + event.preventDefault(); + + const selectedItems = this.pageData.order.items.filter(item => parseInt(document.getElementById(`qty-${item.id}`).value, 10) > 0); + + const newReturn = { + orderId: this.pageData.order.id, + items: selectedItems.map(item => ({ + id: item.id, + quantity: parseInt(document.getElementById(`qty-${item.id}`).value, 10), + reasonId: document.getElementById(`reason-${item.id}`).value, + resolution: document.getElementById(`resolution-${item.id}`).value, + })), + }; + + // TODO: wire up API call when available + console.log('Submitting return:', JSON.stringify(newReturn, null, 2)); + }); + } + + isCustomResolution(resolution) { + return 'id' in resolution; + } +} diff --git a/assets/scss/components/stencil/addReturn/_addReturn.scss b/assets/scss/components/stencil/addReturn/_addReturn.scss index 1c120b9746..e5d41bf84c 100644 --- a/assets/scss/components/stencil/addReturn/_addReturn.scss +++ b/assets/scss/components/stencil/addReturn/_addReturn.scss @@ -1,6 +1,10 @@ // ============================================================================= // ADD RETURN REQUEST (CSS) // ============================================================================= +// +// Styles shared by both the legacy add-return page (.account--addReturn) +// and the new add-return-new page (.newReturn). +// ============================================================================= .account--addReturn { @@ -137,3 +141,246 @@ width: grid-calc(6, $total-columns); } } + + +// ============================================================================= +// NEW RETURN PAGE (.newReturn) +// ============================================================================= + +.newReturn { + color: color("link"); + max-width: remCalc(1100px); + margin: 0 auto; + padding: 0 spacing("single") spacing("double"); +} + +.newReturn-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: spacing("eighth"); +} + +.newReturn-titleGroup { + display: flex; + align-items: center; + gap: spacing("half"); +} + +.newReturn-title { + font-size: remCalc(28px); + font-weight: fontWeight("bold"); + margin: 0; +} + +.newReturn-statusBadge { + display: inline-block; + padding: spacing("eighth") spacing("quarter"); + border: remCalc(1.5px) solid color("orderStatus", "completed"); + border-radius: remCalc(4px); + font-size: remCalc(11px); + font-weight: fontWeight("bold"); + letter-spacing: remCalc(1px); + color: color("orderStatus", "completed"); + text-transform: uppercase; +} + +.newReturn-headerActions { + display: flex; + align-items: center; + gap: spacing("half"); +} + +.newReturn-btnBack { + padding: spacing("quarter") spacing("single") * 0.83; + border: remCalc(1.5px) solid color("link"); + border-radius: remCalc(6px); + background: color("whites", "bright"); + font-size: fontSize("smallest"); + font-weight: fontWeight("medium"); + cursor: pointer; + text-decoration: none; + color: color("link"); +} + +.newReturn-btnPolicy { + padding: spacing("quarter") spacing("single") * 0.83; + border: 0; + border-radius: remCalc(6px); + background: color("greys", "darkest"); + color: color("whites", "bright"); + font-size: fontSize("smallest"); + font-weight: fontWeight("medium"); + cursor: pointer; + text-decoration: none; +} + +.newReturn-orderDate { + font-size: remCalc(13px); + color: color("greys", "base"); + margin: spacing("eighth") 0 spacing("single") * 0.83; +} + +.newReturn-divider { + border: 0; + border-top: container("border"); + margin: spacing("single") 0; +} + + +.newReturn-shippingGrid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: remCalc(32px); +} + +.newReturn-shippingSection { + + h4 { + font-size: fontSize("smallest"); + font-weight: fontWeight("semibold"); + color: color("link"); + margin: 0 0 spacing("quarter"); + } + + p, + a { + font-size: remCalc(13px); + margin: remCalc(2px) 0; + text-decoration: none; + } + + p { + color: color("greys", "dark"); + } +} + + +.newReturn-orderLineItem { + display: flex; + align-items: center; + gap: remCalc(16px); + padding: remCalc(16px) 0; + border-bottom: container("border"); + + &:last-child { + border-bottom: 0; + } +} + +.newReturn-orderLineItemThumbnail { + width: remCalc(72px); + height: remCalc(72px); + object-fit: cover; + border-radius: remCalc(6px); + flex-shrink: 0; + background: color("greys", "lighter"); +} + +.newReturn-orderLineItemThumbnail--placeholder { + width: remCalc(72px); + height: remCalc(72px); + border-radius: remCalc(6px); + flex-shrink: 0; + background: color("greys", "light"); + display: flex; + align-items: center; + justify-content: center; + color: color("greys", "medium"); + font-size: remCalc(11px); +} + +.newReturn-orderLineItemInfo { + flex: 1; + min-width: 0; +} + +.newReturn-orderLineItemName { + font-size: remCalc(15px); + font-weight: fontWeight("semibold"); + margin: 0 0 remCalc(2px); +} + +.newReturn-orderLineItemVariant { + font-size: remCalc(13px); + color: color("greys", "base"); + margin: 0 0 remCalc(2px); +} + +.newReturn-orderLineItemPrice { + font-size: remCalc(13px); + color: color("greys", "dark"); + margin: 0; +} + +.newReturn-orderLineItemControls { + display: flex; + align-items: center; + gap: spacing("half"); + flex-shrink: 0; + + //Override layout here so the counter sits in a horizontal row + // without touching the shared component. + .form-increment { + display: flex; + align-items: center; + + } + + .form-input--incrementTotal { + height: remCalc(36px); + line-height: remCalc(36px); + vertical-align: middle; + } +} + +.newReturn-select { + height: remCalc(36px); + padding: 0 remCalc(28px) 0 spacing("quarter") * 1.67; + border: remCalc(1.5px) solid color("greys", "medium"); + border-radius: remCalc(6px); + font-size: remCalc(13px); + color: color("greys", "dark"); + // stylelint-disable-next-line function-url-quotes + background: color("whites", "bright") url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23798289'/%3E%3C/svg%3E") no-repeat right spacing("quarter") * 1.67 center; + background-size: remCalc(10px); + appearance: none; + cursor: pointer; + min-width: remCalc(180px); + + &:disabled { + background-color: color("greys", "lighter"); + color: color("greys", "medium"); + cursor: not-allowed; + border-color: color("greys", "light"); + } +} + +.newReturn-submitRow { + display: flex; + justify-content: flex-end; + margin-top: spacing("half"); +} + +.newReturn-submitBtn { + width: 100%; + max-width: remCalc(520px); + padding: remCalc(14px); + background: color("greys", "darkest"); + color: color("whites", "bright"); + border: 0; + border-radius: remCalc(8px); + font-size: remCalc(15px); + font-weight: fontWeight("semibold"); + cursor: pointer; + transition: background 0.2s; + + &:hover { + background: color("greys", "dark"); + } + + &:disabled { + background: color("greys", "medium"); + cursor: not-allowed; + } +} diff --git a/templates/pages/account/add-return-new.html b/templates/pages/account/add-return-new.html new file mode 100644 index 0000000000..24dcc3fa65 --- /dev/null +++ b/templates/pages/account/add-return-new.html @@ -0,0 +1,44 @@ +{{#partial "page"}} + +{{> components/common/breadcrumbs breadcrumbs=breadcrumbs}} +{{> components/account/navigation account_page='returns'}} + +
+ +
+
+

Request Return for Order #

+ +
+ +
+

+ +
+ +
+
+
+
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +{{/partial}} +{{> layout/base}} From 2bbd8d84cd3fd86f0364fb074f03ae8fa2b69030 Mon Sep 17 00:00:00 2001 From: Vivek Aggarwal Date: Tue, 12 May 2026 10:51:45 +1000 Subject: [PATCH 02/16] feat(returns): ORDERS-7704 condition for new returns on orders page (#2653) * feat(returns): ORDERS-7704 condition for new returns on orders page * feat(returns): ORDERS-7704 condition for new returns on orders page - confirmed --- CHANGELOG.md | 1 + templates/components/account/orders-list.html | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31953dca2f..972f80d37d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Swap content/data keys in onProductOptionsChanged event detail [#2640](https://github.com/bigcommerce/cornerstone/pull/2640) - 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) ## 6.19.1 (04-09-2026) - Update stencil-utils versionto 6.23.0 [#2638](https://github.com/bigcommerce/cornerstone/pull/2638) diff --git a/templates/components/account/orders-list.html b/templates/components/account/orders-list.html index d54f78c772..7da8381ccd 100644 --- a/templates/components/account/orders-list.html +++ b/templates/components/account/orders-list.html @@ -23,12 +23,12 @@ From 01392b85900e942f33ab1f0210ac1f26bf27b8b1 Mon Sep 17 00:00:00 2001 From: Jasper Pajar <45197791+jpajar@users.noreply.github.com> Date: Fri, 8 May 2026 15:33:55 +1000 Subject: [PATCH 05/16] Merge pull request #2649 from bigcommerce/ORDERS-7706 feat(orders): ORDERS-7706 add new return page layout From b5a0c9b2b7cc77ba6900acec3a28c56ecac2fcb1 Mon Sep 17 00:00:00 2001 From: Shayne Even Date: Tue, 28 Apr 2026 18:37:00 +1000 Subject: [PATCH 06/16] feat(orders): ORDERS-7734 add template for guest return portal --- CHANGELOG.md | 1 + templates/pages/guest-return-portal.html | 9 +++++++++ 2 files changed, 10 insertions(+) create mode 100644 templates/pages/guest-return-portal.html diff --git a/CHANGELOG.md b/CHANGELOG.md index c61023c12a..25873e184b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 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) diff --git a/templates/pages/guest-return-portal.html b/templates/pages/guest-return-portal.html new file mode 100644 index 0000000000..9546e3843d --- /dev/null +++ b/templates/pages/guest-return-portal.html @@ -0,0 +1,9 @@ +{{#partial "page"}} + +{{> components/common/breadcrumbs breadcrumbs=breadcrumbs}} + +

Guest Return Portal

+ +{{/partial}} + +{{> layout/base}} From 84988236cd60626271a2aac1eda182da85a7e4a3 Mon Sep 17 00:00:00 2001 From: bc-bryan Date: Tue, 26 May 2026 11:18:51 +1000 Subject: [PATCH 07/16] feat(returns): ORDERS-7717 - add new returns list ui --- .../components/stencil/account/_account.scss | 41 +++++++++++++++++++ lang/en.json | 9 +++- .../components/account/returns-list-v2.html | 36 ++++++++++++++++ templates/pages/account/returns.html | 21 ++++++++-- 4 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 templates/components/account/returns-list-v2.html diff --git a/assets/scss/components/stencil/account/_account.scss b/assets/scss/components/stencil/account/_account.scss index 4c6e9d3a6d..6055fe1f3b 100644 --- a/assets/scss/components/stencil/account/_account.scss +++ b/assets/scss/components/stencil/account/_account.scss @@ -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"); @@ -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; diff --git a/lang/en.json b/lang/en.json index 6234f8b366..9a7b5af664 100755 --- a/lang/en.json +++ b/lang/en.json @@ -457,10 +457,17 @@ "comments": "Your Comments", "submit_request": "Submit Return Request", "list": { + "last_update":"Last Update", + "return_submitted": "Return Submitted", "return_number": "Return #{id}", - "product_details": "Returning {num_products}" + "product_details": "Returning {num_products}", + "return_items": "Return Items", + "view_details": "View details" }, "status": { + "open":"OPEN", + "closed": "CLOSED", + "in_progress":"IN PROGRESS", "pending": "Pending", "received": "Received", "authorized": "Authorized", diff --git a/templates/components/account/returns-list-v2.html b/templates/components/account/returns-list-v2.html new file mode 100644 index 0000000000..b0b405eb8e --- /dev/null +++ b/templates/components/account/returns-list-v2.html @@ -0,0 +1,36 @@ + + + \ No newline at end of file diff --git a/templates/pages/account/returns.html b/templates/pages/account/returns.html index 15047bf7c1..54c5594bda 100644 --- a/templates/pages/account/returns.html +++ b/templates/pages/account/returns.html @@ -7,14 +7,29 @@

{{lang 'account.returns.heading' }}

{{/partial}} {{> layout/base}} + From 25cb72fac96089224075b9293e79d9f4376df7c6 Mon Sep 17 00:00:00 2001 From: bc-bryan Date: Wed, 27 May 2026 11:28:02 +1000 Subject: [PATCH 08/16] feat(returns): ORDERS-7717 - use rma number --- templates/components/account/returns-list-v2.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/components/account/returns-list-v2.html b/templates/components/account/returns-list-v2.html index b0b405eb8e..faf527db8f 100644 --- a/templates/components/account/returns-list-v2.html +++ b/templates/components/account/returns-list-v2.html @@ -5,7 +5,7 @@
  • +
    + ${escape(item.name)} +
    +
    +

    ${escape(item.name)}

    + ${item.variant ? `

    ${escape(item.variant)}

    ` : ''} +

    ${escape(item.formatted_price)}

    +
    +
    +
    +
    Return Quantity:
    +
    ${escape(item.quantity)}
    +
    +
    +
    Request
    +
    ${escape(resolutionLabel)}
    +
    +
    +
    Reason
    +
    ${escape(item.requestedReason)}
    +
    +
    +
  • `; + } + + 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 }) => ` +
    +
    ${escape(label)}
    +
    ${escape(value)}
    +
    `).join(''); + } +} diff --git a/assets/scss/components/_components.scss b/assets/scss/components/_components.scss index 82482864d3..bd338e70cb 100644 --- a/assets/scss/components/_components.scss +++ b/assets/scss/components/_components.scss @@ -108,6 +108,9 @@ // Add Return @import "stencil/addReturn/component"; +// Return Details +@import "stencil/returnDetails/component"; + // Product Carousel @import "stencil/productCarousel/component"; diff --git a/assets/scss/components/stencil/returnDetails/_component.scss b/assets/scss/components/stencil/returnDetails/_component.scss new file mode 100644 index 0000000000..c7a8c1582a --- /dev/null +++ b/assets/scss/components/stencil/returnDetails/_component.scss @@ -0,0 +1,7 @@ +// ============================================================================= +// RETURN DETAILS +// ============================================================================= + + +// Component +@import "returnDetails"; diff --git a/assets/scss/components/stencil/returnDetails/_returnDetails.scss b/assets/scss/components/stencil/returnDetails/_returnDetails.scss new file mode 100644 index 0000000000..ba78ea6ea3 --- /dev/null +++ b/assets/scss/components/stencil/returnDetails/_returnDetails.scss @@ -0,0 +1,241 @@ +// ============================================================================= +// RETURN DETAILS PAGE (.returnDetails) +// ============================================================================= + + +.returnDetails { + color: stencilColor("color-textBase"); + max-width: remCalc(1200px); + margin: 0 auto; + padding: 0 spacing("single") spacing("double"); +} + +.returnDetails-titleGroup { + display: flex; + align-items: center; + gap: spacing("half"); +} + +.returnDetails-title { + font-family: $header-font-family; + font-size: $h1-font-size; + font-weight: $header-font-weight; + margin: 0; +} + +.returnDetails-statusBadge { + display: inline-block; + padding: spacing("eighth") spacing("quarter"); + border-radius: remCalc(4px); + font-size: remCalc(11px); + font-weight: fontWeight("bold"); + letter-spacing: remCalc(1px); + text-transform: uppercase; + background-color: stencilColor("label-backgroundColor"); + color: stencilColor("label-color"); +} + +.returnDetails-statusBadge--open { + background-color: color("warning", "light"); + color: stencilColor("color-textBase"); +} + +.returnDetails-statusBadge--in_progress { + background-color: color("success", "light"); + color: stencilColor("color-textBase"); +} + +.returnDetails-statusBadge--closed { + background-color: color("greys", "lighter"); + color: stencilColor("color-textBase"); +} + +.returnDetails-divider { + border: 0; + border-top: container("border"); + margin: spacing("single") 0; +} + +.returnDetails-sectionHeading { + font-family: $header-font-family; + font-size: $h1-font-size; + font-weight: $header-font-weight; + margin: 0; + color: stencilColor("color-textBase"); +} + + +// ============================================================================= +// SHIPPING — single address + method, shown above the line items +// ============================================================================= + +.returnDetails-shipping { + margin: 0 0 spacing("single"); + display: flex; + flex-direction: column; + gap: remCalc(6px); +} + +.returnDetails-shippingRow { + display: flex; + align-items: baseline; + gap: remCalc(8px); + font-size: remCalc(14px); +} + +.returnDetails-shippingLabel { + flex-shrink: 0; + font-weight: fontWeight("semibold"); + color: stencilColor("color-textSecondary"); + margin: 0; +} + +.returnDetails-shippingValue { + margin: 0; + color: stencilColor("color-textBase"); +} + + +// ============================================================================= +// LAYOUT — main items column + sidebar +// ============================================================================= + +.returnDetails-layout { + display: grid; + grid-template-columns: 1fr; + gap: spacing("single") * 2; + + @include breakpoint("medium") { + grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); + } +} + +.returnDetails-main { + min-width: 0; +} + +.returnDetails-sidebar { + min-width: 0; +} + + +// ============================================================================= +// ITEM LIST (flat, by line items) +// ============================================================================= + +.returnDetails-itemList { + list-style: none; + margin: 0; + padding: 0; +} + +.returnDetails-item { + display: flex; + align-items: flex-start; + gap: remCalc(16px); + padding: remCalc(16px) 0; + border-bottom: container("border"); + + &:last-child { + border-bottom: 0; + } + + @include breakpoint("large") { + align-items: center; + } +} + +.returnDetails-itemThumbnailWrapper { + flex-shrink: 0; + line-height: 0; +} + +.returnDetails-itemThumbnail { + width: remCalc(72px); + height: remCalc(72px); + object-fit: cover; + border-radius: remCalc(6px); + background: color("greys", "lighter"); +} + +.returnDetails-itemInfo { + flex: 1; + min-width: 0; +} + +.returnDetails-itemName { + font-size: remCalc(15px); + font-weight: fontWeight("semibold"); + margin: 0 0 remCalc(2px); + color: stencilColor("color-textBase"); +} + +.returnDetails-itemVariant { + font-size: remCalc(13px); + color: stencilColor("color-textSecondary"); + margin: 0 0 remCalc(2px); +} + +.returnDetails-itemPrice { + font-size: remCalc(13px); + color: color("greys", "dark"); + margin: 0; +} + +// Right-aligned key/value column for Return Quantity / Request / Reason. +.returnDetails-itemMeta { + flex-shrink: 0; + width: remCalc(240px); + margin: 0; + display: flex; + flex-direction: column; + gap: remCalc(4px); +} + +.returnDetails-itemMetaRow { + display: flex; + align-items: baseline; + gap: remCalc(6px); + font-size: remCalc(13px); +} + +.returnDetails-itemMetaLabel { + font-weight: fontWeight("semibold"); + color: stencilColor("color-textSecondary"); + margin: 0; +} + +.returnDetails-itemMetaValue { + margin: 0; + color: stencilColor("color-textBase"); +} + + +// ============================================================================= +// SIDEBAR — Summary +// ============================================================================= + +.returnDetails-summaryList { + margin: 0; + display: flex; + flex-direction: column; + gap: remCalc(6px); +} + +.returnDetails-summaryRow { + display: flex; + align-items: baseline; + gap: remCalc(6px); + font-size: remCalc(14px); +} + +.returnDetails-summaryLabel { + font-weight: fontWeight("semibold"); + color: stencilColor("color-textSecondary"); + margin: 0; +} + +.returnDetails-summaryValue { + margin: 0; + color: stencilColor("color-textBase"); +} diff --git a/lang/en.json b/lang/en.json index f1b2db81ac..748dacb232 100755 --- a/lang/en.json +++ b/lang/en.json @@ -459,6 +459,7 @@ "additional_note": "Additional note", "additional_note_placeholder": "Please describe any additional details of this return request.", "submit": "Submit Return", + "summary": "Summary", "list": { "last_update":"Last Update", "return_submitted": "Return Submitted", diff --git a/templates/pages/account/return-details.html b/templates/pages/account/return-details.html new file mode 100644 index 0000000000..b9ddb004d9 --- /dev/null +++ b/templates/pages/account/return-details.html @@ -0,0 +1,43 @@ +{{#partial "page"}} + +{{!-- + Standalone return-details page. Not yet routed — a page type still needs to be + mapped to this template (and `getReturnDetails` wired up in assets/js/app.js) + before it's reachable. For now it exists to hold the correct layout. + + The JS module at assets/js/theme/return-details.js owns the mock data + (shaped after the returns-ui Return/Item interfaces in + returns-ui/src/apps/ManageReturn/Page/index.tsx) and renders into the + [data-*] hooks below. +--}} + +{{> components/common/breadcrumbs breadcrumbs=breadcrumbs}} +{{> components/account/navigation account_page='returns'}} + +
    +
    + +
    +
    +

    + +
    + +
    + +
    + +
      +
      + + + +
      +
      + +{{/partial}} +{{> layout/base}} diff --git a/templates/pages/account/returns.html b/templates/pages/account/returns.html index 7b47f326f7..8b1c4cf883 100644 --- a/templates/pages/account/returns.html +++ b/templates/pages/account/returns.html @@ -11,6 +11,7 @@

      {{lang 'account.returns.heading' }}

      {{#if settings.returns_v2_enabled}} {{#if returns.length}} + {{!-- TODO: ORDERS-7751 When a per-return details route (e.g. action=view_return&return_id=X) exists, this list should link to it. --}} {{> components/account/returns-list-v2 returns=returns}} {{else}} {{> components/common/alert/alert-info (lang 'account.returns.none')}} From 7c5e3521d2043526873367c16512c28d4d6b9c1d Mon Sep 17 00:00:00 2001 From: Jasper Pajar Date: Tue, 9 Jun 2026 15:20:31 +1000 Subject: [PATCH 15/16] feat(orders): ORDERS-7718 add status mappping from enum --- assets/js/theme/return-details.js | 9 ++++++++- templates/pages/account/return-details.html | 5 +++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/assets/js/theme/return-details.js b/assets/js/theme/return-details.js index 0751bb5a4c..6197a3c920 100644 --- a/assets/js/theme/return-details.js +++ b/assets/js/theme/return-details.js @@ -91,7 +91,14 @@ export default class ReturnDetails extends PageManager { if (titleEl) titleEl.textContent = `Return #${rma}`; if (statusEl) { - statusEl.textContent = status; + // 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()}`); } } diff --git a/templates/pages/account/return-details.html b/templates/pages/account/return-details.html index b9ddb004d9..11e558e81b 100644 --- a/templates/pages/account/return-details.html +++ b/templates/pages/account/return-details.html @@ -11,6 +11,11 @@ [data-*] hooks below. --}} +{{!-- Localized status labels for the JS status badge (mirrors the returns list). --}} +{{~inject 'returnStatusOpen' (lang 'account.returns.status.open')}} +{{~inject 'returnStatusInProgress' (lang 'account.returns.status.in_progress')}} +{{~inject 'returnStatusClosed' (lang 'account.returns.status.closed')}} + {{> components/common/breadcrumbs breadcrumbs=breadcrumbs}} {{> components/account/navigation account_page='returns'}} From a12175ba1bf1bb218aa81696b0dd965b14f3901a Mon Sep 17 00:00:00 2001 From: Vivek Aggarwal Date: Thu, 11 Jun 2026 13:32:27 +1000 Subject: [PATCH 16/16] Orders 7764 render create return page with context (#2673) * feat(returns): ORDERS-7764 render create return page with stencil context * feat(returns): ORDERS-7764 render create return page with stencil context * feat(returns): ORDERS-7764 render create return page with stencil context * feat(returns): ORDERS-7764 render create return page with stencil context * feat(returns): ORDERS-7764 fix code review comments * feat(returns): ORDERS-7764 fix code review comments * feat(returns): ORDERS-7764 fix design feedback * feat(returns): ORDERS-7764 fix design feedback --- assets/js/app.js | 5 +- assets/js/theme/add-return-new.js | 93 ------- assets/js/theme/create-return.js | 72 +++++ assets/scss/components/_components.scss | 5 +- .../stencil/addReturn/_addReturn.scss | 246 ------------------ .../stencil/createReturn/_component.scss | 7 + .../stencil/createReturn/_createReturn.scss | 237 +++++++++++++++++ lang/en.json | 15 +- templates/pages/account/add-return-new.html | 114 -------- templates/pages/account/add-return.html | 198 +++++++------- templates/pages/create-return.html | 120 ++++++++- 11 files changed, 546 insertions(+), 566 deletions(-) delete mode 100644 assets/js/theme/add-return-new.js create mode 100644 assets/js/theme/create-return.js create mode 100644 assets/scss/components/stencil/createReturn/_component.scss create mode 100644 assets/scss/components/stencil/createReturn/_createReturn.scss delete mode 100644 templates/pages/account/add-return-new.html diff --git a/assets/js/app.js b/assets/js/app.js index 2d95c5bef2..b9a03f8aad 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -3,7 +3,7 @@ __webpack_public_path__ = window.__webpack_public_path__; // eslint-disable-line import Global from './theme/global'; const getAccount = () => import('./theme/account'); -const getAddReturnNew = () => import('./theme/add-return-new'); +const getCreateReturn = () => import('./theme/create-return'); const getLogin = () => import('./theme/auth'); const noop = null; @@ -12,7 +12,8 @@ const pageClasses = { account_order: getAccount, account_addressbook: getAccount, shippingaddressform: getAccount, - account_new_return: getAddReturnNew, + account_new_return: getAccount, + create_return: getCreateReturn, 'add-wishlist': () => import('./theme/wishlist'), account_recentitems: getAccount, account_downloaditem: getAccount, diff --git a/assets/js/theme/add-return-new.js b/assets/js/theme/add-return-new.js deleted file mode 100644 index 03c0d78bae..0000000000 --- a/assets/js/theme/add-return-new.js +++ /dev/null @@ -1,93 +0,0 @@ -import PageManager from './page-manager'; - -export default class AddReturnNew extends PageManager { - onReady() { - const $form = $('[data-new-return-form]'); - if (!$form.length) return; - - this.bindOrderLineItemEvents(); - this.bindSubmit($form); - } - - bindOrderLineItemEvents() { - document.querySelectorAll('.newReturn-stepperBtn').forEach(button => { - button.addEventListener('click', () => { - // Derive itemId from the parent row — buttons do not carry data-item-id, - // so the [data-item-id] selector stays scoped to the row container only. - const row = button.closest('.newReturn-orderLineItem'); - const itemId = row?.dataset?.itemId; - if (!itemId) return; - const action = button.getAttribute('data-action'); - const quantityInput = document.getElementById(`qty-${itemId}`); - // max is set server-side to returnableQuantity → quantity fallback - const maxQty = parseInt(quantityInput.max, 10) || 0; - let quantity = parseInt(quantityInput.value, 10) || 0; - - if (action === 'inc' && quantity < maxQty) quantity++; - else if (action === 'dec' && quantity > 0) quantity--; - - quantityInput.value = quantity; - const stepper = button.closest('.newReturn-stepper'); - stepper.querySelector('[data-action="dec"]').disabled = quantity === 0; - stepper.querySelector('[data-action="inc"]').disabled = quantity >= maxQty; - - this.updateSubmitState(); - }); - }); - - document.querySelectorAll('.newReturn-select').forEach(selectElement => { - selectElement.addEventListener('change', () => this.updateSubmitState()); - }); - - // Disable + button on load for any item where max=0 (non-returnable) - document.querySelectorAll('.newReturn-stepperInput').forEach(input => { - const maxQty = parseInt(input.max, 10) || 0; - const incBtn = input.closest('.newReturn-stepper')?.querySelector('[data-action="inc"]'); - if (incBtn && maxQty === 0) incBtn.disabled = true; - }); - } - - 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.on('submit', event => { - event.preventDefault(); - - const orderEntityId = parseInt(this.context.order?.id, 10); - const additionalNote = document.querySelector('[data-new-return-note]')?.value || ''; - const 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, - }]; - }); - - // TODO ORDERS-7715: invoke createReturn Storefront GQL mutation. - }); - } -} diff --git a/assets/js/theme/create-return.js b/assets/js/theme/create-return.js new file mode 100644 index 0000000000..498fcc70d8 --- /dev/null +++ b/assets/js/theme/create-return.js @@ -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, + }]; + }), + }; + } +} diff --git a/assets/scss/components/_components.scss b/assets/scss/components/_components.scss index bd338e70cb..0bd4222272 100644 --- a/assets/scss/components/_components.scss +++ b/assets/scss/components/_components.scss @@ -105,12 +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"; diff --git a/assets/scss/components/stencil/addReturn/_addReturn.scss b/assets/scss/components/stencil/addReturn/_addReturn.scss index c44242b10f..2360918089 100644 --- a/assets/scss/components/stencil/addReturn/_addReturn.scss +++ b/assets/scss/components/stencil/addReturn/_addReturn.scss @@ -139,249 +139,3 @@ } -// ============================================================================= -// NEW RETURN PAGE (.newReturn) -// ============================================================================= - -.newReturn { - color: color("link"); - max-width: remCalc(1100px); - margin: 0 auto; - padding: 0 spacing("single") spacing("double"); -} - -.newReturn-header { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: spacing("eighth"); -} - -.newReturn-titleGroup { - display: flex; - align-items: center; - gap: spacing("half"); -} - -.newReturn-title { - font-size: remCalc(28px); - font-weight: fontWeight("bold"); - margin: 0; -} - -.newReturn-statusBadge { - display: inline-block; - padding: spacing("eighth") spacing("quarter"); - border: remCalc(1.5px) solid color("orderStatus", "completed"); - border-radius: remCalc(4px); - font-size: remCalc(11px); - font-weight: fontWeight("bold"); - letter-spacing: remCalc(1px); - color: color("orderStatus", "completed"); - text-transform: uppercase; -} - -.newReturn-headerActions { - display: flex; - align-items: center; - gap: spacing("half"); -} - -.newReturn-btnBack { - padding: spacing("quarter") spacing("single") * 0.83; - border: remCalc(1.5px) solid color("link"); - border-radius: remCalc(6px); - background: color("whites", "bright"); - font-size: fontSize("smallest"); - font-weight: fontWeight("medium"); - cursor: pointer; - text-decoration: none; - color: color("link"); -} - -.newReturn-btnPolicy { - padding: spacing("quarter") spacing("single") * 0.83; - border: 0; - border-radius: remCalc(6px); - background: color("greys", "darkest"); - color: color("whites", "bright"); - font-size: fontSize("smallest"); - font-weight: fontWeight("medium"); - cursor: pointer; - text-decoration: none; -} - -.newReturn-orderDate { - font-size: remCalc(13px); - color: color("greys", "base"); - margin: spacing("eighth") 0 spacing("single") * 0.83; -} - -.newReturn-divider { - border: 0; - border-top: container("border"); - margin: spacing("single") 0; -} - - -.newReturn-orderLineItem { - display: flex; - align-items: flex-start; // controls column is tallest when stacked (mobile/tablet) - gap: remCalc(16px); - padding: remCalc(16px) 0; - - @include breakpoint("large") { - align-items: center; // desktop: everything inline so vertical-center is fine - } -} - -.newReturn-orderLineItemThumbnailWrapper { - flex-shrink: 0; - line-height: 0; // collapse inline whitespace around the img -} - -.newReturn-orderLineItemThumbnail { - width: remCalc(72px); - height: remCalc(72px); - object-fit: cover; - border-radius: remCalc(6px); - flex-shrink: 0; - background: color("greys", "lighter"); -} - -.newReturn-orderLineItemInfo { - flex: 1; - min-width: 0; -} - -.newReturn-orderLineItemName { - font-size: remCalc(15px); - font-weight: fontWeight("semibold"); - margin: 0 0 remCalc(2px); -} - -.newReturn-orderLineItemVariant { - font-size: remCalc(13px); - color: color("greys", "base"); - margin: 0 0 remCalc(2px); -} - -.newReturn-orderLineItemPrice { - font-size: remCalc(13px); - color: color("greys", "dark"); - margin: 0; -} - -// Per-item controls cluster: stepper + resolution-select + reason-select. -// Below large breakpoint they stack vertically (mobile + tablet); on large they -// sit inline as in the Figma desktop frame. -.newReturn-orderLineItemControls { - display: flex; - flex-direction: column; - align-items: stretch; - gap: spacing("quarter"); - flex-shrink: 0; - width: remCalc(180px); - - @include breakpoint("large") { - flex-direction: row; - align-items: center; - gap: spacing("half"); - width: auto; - } -} - -.newReturn-stepper { - display: inline-flex; - align-items: center; - height: remCalc(36px); - border: remCalc(1.5px) solid color("greys", "medium"); - border-radius: remCalc(6px); - overflow: hidden; - flex-shrink: 0; - align-self: flex-start; // keep compact when stacked; selects stretch instead - - @include breakpoint("large") { - align-self: auto; - } -} - -.newReturn-stepperBtn { - background: none; - border: none; - width: remCalc(32px); - height: 100%; - font-size: remCalc(18px); - line-height: 1; - cursor: pointer; - color: color("greys", "dark"); - padding: 0; - - &:disabled { - color: color("greys", "light"); - cursor: not-allowed; - } - - &:focus:not(:focus-visible) { - outline: none !important; - } - - &:hover:not(:disabled) { - background-color: color("greys", "lighter"); - } -} - -.newReturn-stepperInput { - width: remCalc(40px); - height: 100%; - border: none; - text-align: center; - font-size: remCalc(14px); - padding: 0; - outline: none; - background: transparent; - color: color("greys", "dark"); -} - -.newReturn-select { - width: 100%; // full width when stacked under stepper on mobile/tablet - height: remCalc(36px); - padding: 0 remCalc(28px) 0 spacing("quarter") * 1.67; - border: remCalc(1.5px) solid color("greys", "medium"); - border-radius: remCalc(6px); - font-size: remCalc(13px); - color: color("greys", "dark"); - // stylelint-disable-next-line function-url-quotes - background: color("whites", "bright") url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23798289'/%3E%3C/svg%3E") no-repeat right spacing("quarter") * 1.67 center; - background-size: remCalc(10px); - appearance: none; - cursor: pointer; - - @include breakpoint("large") { - width: auto; - min-width: remCalc(180px); - } - - &:disabled { - background-color: color("greys", "lighter"); - color: color("greys", "medium"); - cursor: not-allowed; - border-color: color("greys", "light"); - } -} - -// Right-aligned bottom column holding the additional-note textarea + submit button. -// Mirrors the controls column width on tablet+; collapses to full width on mobile. -.newReturn-footer { - margin-top: spacing("single"); - - @include breakpoint("medium") { - width: 50%; - margin-left: auto; - } - - .form-actions { - text-align: right; - } -} - diff --git a/assets/scss/components/stencil/createReturn/_component.scss b/assets/scss/components/stencil/createReturn/_component.scss new file mode 100644 index 0000000000..99d4c0f164 --- /dev/null +++ b/assets/scss/components/stencil/createReturn/_component.scss @@ -0,0 +1,7 @@ +// ============================================================================= +// CREATE RETURN PAGE +// ============================================================================= + + +// Component +@import "createReturn"; diff --git a/assets/scss/components/stencil/createReturn/_createReturn.scss b/assets/scss/components/stencil/createReturn/_createReturn.scss new file mode 100644 index 0000000000..18c4072c6f --- /dev/null +++ b/assets/scss/components/stencil/createReturn/_createReturn.scss @@ -0,0 +1,237 @@ +// ============================================================================= +// CREATE RETURN PAGE (.newReturn) +// ============================================================================= + +.newReturn { + color: color("link"); + max-width: remCalc(1100px); + margin: 0 auto; + padding: 0 spacing("single") spacing("double"); +} + +.newReturn-header { + display: flex; + align-items: center; + justify-content: space-between; + flex-wrap: wrap; + gap: spacing("quarter"); + margin-bottom: spacing("eighth"); +} + +.newReturn-titleGroup { + display: flex; + align-items: center; + gap: spacing("half"); +} + +.newReturn-title { + font-size: remCalc(28px); + font-weight: fontWeight("bold"); + margin: 0; +} + +.newReturn-statusBadge { + display: inline-block; + padding: spacing("eighth") spacing("quarter"); + border: remCalc(1.5px) solid color("orderStatus", "completed"); + border-radius: remCalc(4px); + font-size: remCalc(11px); + font-weight: fontWeight("bold"); + letter-spacing: remCalc(1px); + color: color("orderStatus", "completed"); + text-transform: uppercase; +} + +.newReturn-headerActions { + display: flex; + align-items: center; + gap: spacing("half"); +} + +.newReturn-headerActions .button { + font-size: fontSize("smallest"); + padding: spacing("quarter") spacing("half"); + margin: 0; +} + +.newReturn-orderDate { + font-size: remCalc(13px); + color: color("greys", "base"); + margin: spacing("eighth") 0 spacing("single") * 0.83; +} + +.newReturn-divider { + border: 0; + border-top: container("border"); + margin: spacing("single") 0; +} + + +.newReturn-orderLineItem { + display: flex; + align-items: flex-start; // controls column is tallest when stacked (mobile/tablet) + gap: remCalc(16px); + padding: remCalc(16px) 0; + + @include breakpoint("large") { + align-items: center; // desktop: everything inline so vertical-center is fine + } +} + +.newReturn-orderLineItemThumbnailWrapper { + flex-shrink: 0; + line-height: 0; // collapse inline whitespace around the img + + img { + border: remCalc(1px) solid color("greys", "lightest"); + } +} + +.newReturn-orderLineItemThumbnail { + width: remCalc(72px); + height: remCalc(72px); + object-fit: cover; + border-radius: remCalc(6px); + flex-shrink: 0; + background: color("greys", "lighter"); +} + +.newReturn-orderLineItemInfo { + flex: 1; + min-width: 0; +} + +.newReturn-orderLineItemName { + font-size: remCalc(15px); + font-weight: fontWeight("semibold"); + margin: 0 0 remCalc(2px); +} + +.newReturn-orderLineItemVariant { + font-size: remCalc(13px); + color: color("greys", "base"); + margin: 0 0 remCalc(2px); +} + +.newReturn-orderLineItemPrice { + font-size: remCalc(13px); + color: color("greys", "base"); + margin: 0; +} + +.newReturn-orderLineItemControls { + display: flex; + flex-direction: column; + align-items: stretch; + gap: spacing("quarter"); + flex-shrink: 0; + width: remCalc(180px); + + @include breakpoint("large") { + flex-direction: row; + align-items: center; + gap: spacing("half"); + width: auto; + } +} + +.newReturn-divider--headers { + display: none; + + @include breakpoint("large") { + display: block; + } +} + +.newReturn-columnHeaders { + display: none; + + @include breakpoint("large") { + display: flex; + align-items: center; + gap: remCalc(16px); + font-size: remCalc(12px); + font-weight: fontWeight("semibold"); + color: color("greys", "base"); + letter-spacing: remCalc(0.5px); + } +} + +// "Item" aligns with the thumbnail left edge, not the item name. +.newReturn-columnHeaders-spacer { + display: none; +} + +.newReturn-columnHeaders-item { + flex: 1; + min-width: 0; +} + +.newReturn-columnHeaders-controls { + display: flex; + align-items: center; + gap: spacing("half"); +} + +// Shared widths — keeps header labels and control cells in sync. +$newReturn-col-qty: remCalc(120px); +$newReturn-col-select: remCalc(200px); + +.newReturn-columnHeaders-quantity { + width: $newReturn-col-qty; + flex-shrink: 0; +} + +.newReturn-columnHeaders-request, +.newReturn-columnHeaders-reason { + width: $newReturn-col-select; + flex-shrink: 0; +} + +.newReturn-orderLineItemQtyWrapper { + display: flex; + align-items: center; + gap: spacing("quarter"); + + @include breakpoint("large") { + width: $newReturn-col-qty; + flex-shrink: 0; + } +} + +.newReturn-orderLineItemMaxQty { + font-size: remCalc(13px); + color: color("greys", "base"); + white-space: nowrap; +} + +.newReturn-orderLineItemControls [id^="qty-"] { + width: 100%; + + @include breakpoint("large") { + width: auto; + } +} + +.newReturn-orderLineItemControls [id^="resolution-"], +.newReturn-orderLineItemControls [id^="reason-"] { + width: 100%; + + @include breakpoint("large") { + width: $newReturn-col-select; + flex-shrink: 0; + } +} + +.newReturn-footer { + margin-top: spacing("single"); + + @include breakpoint("medium") { + width: 50%; + margin-left: auto; + } + + .form-actions { + text-align: right; + } +} diff --git a/lang/en.json b/lang/en.json index 748dacb232..c7c732a195 100755 --- a/lang/en.json +++ b/lang/en.json @@ -340,6 +340,8 @@ "order_item": "Item", "item_price": "Price", "quantity": "Qty To Return", + "of_max": "of {max}", + "items_label": "Items in this order", "why": "Why are you returning these items?", "reason": "Return Reason", "action": "Return Action", @@ -446,7 +448,10 @@ "error_no_qty": "Please select one or more items to return.", "none": "You haven't placed any returns with us. When you do, they will appear on this page.", "new_return": "New Return", - "from_order": "Return Items from Order #{id}", + "from_order": "Request Return for Order #{id}", + "order_date": "Order date", + "select_resolution": "Select preferred resolution", + "select_reason": "Select a return reason", "date_requested": "Return Requested", "successful_heading": "Return Request Submitted", "successful": "Your return was submitted successfully. We'll respond as soon as we can.", @@ -456,10 +461,16 @@ "action": "Return Action", "comments": "Your Comments", "submit_request": "Submit Return Request", - "additional_note": "Additional note", "additional_note_placeholder": "Please describe any additional details of this return request.", "submit": "Submit Return", "summary": "Summary", + "back": "Back", + "view_return_policy": "View return policy", + "additional_note": "Additional Note", + "request": "Preferred resolution", + "reason_header": "Return reason", + "qty": "Qty:", + "total_price": "Total:", "list": { "last_update":"Last Update", "return_submitted": "Return Submitted", diff --git a/templates/pages/account/add-return-new.html b/templates/pages/account/add-return-new.html deleted file mode 100644 index 63d9a97cc7..0000000000 --- a/templates/pages/account/add-return-new.html +++ /dev/null @@ -1,114 +0,0 @@ -{{~inject 'order' orders.[0]}} -
      - - {{#with orders.[0]}} - -
      -
      -

      {{lang 'account.returns.from_order' id=id}}

      - {{#if status}}{{status}}{{/if}} -
      - -
      - {{#if date}}

      {{date}}

      {{/if}} - -
      - -
      - - {{#each items}} -
      - -
      - {{> components/common/responsive-img - image=image - class="newReturn-orderLineItemThumbnail" - fallback_size=../../theme_settings.productthumb_size - lazyload=../../theme_settings.lazyload_mode - default_image=../../theme_settings.default_image_product - }} -
      - -
      -

      {{name}}

      - {{#if productAttributesList}} -

      - {{#each productAttributesList}}{{name}}: {{{sanitize value}}}{{#unless @last}} · {{/unless}}{{/each}} -

      - {{/if}} - {{!-- TODO ORDERS-7764: replace cross-ref with {{price.formatted}} directly on item once dedicated returns service includes item price --}} - {{#each ../../forms.return.order_products}} - {{#if id '==' ../id}} -

      {{price.formatted}} × {{../quantity}}

      - {{/if}} - {{/each}} -
      - -
      -
      - - {{!-- TODO ORDERS-7764: replace max={{quantity}} with returnableQuantity once dedicated returns service provides it --}} - - -
      - - -
      -
      - {{/each}} - -
      - - - - - -
      - - {{/with}} - -
      diff --git a/templates/pages/account/add-return.html b/templates/pages/account/add-return.html index f20848bd6d..9130fc8813 100644 --- a/templates/pages/account/add-return.html +++ b/templates/pages/account/add-return.html @@ -1,118 +1,106 @@ {{#partial "page"}} -{{#if settings.returns_v2_enabled}} +{{> components/common/breadcrumbs breadcrumbs=breadcrumbs}} +

      {{lang 'account.returns.new_return' }}

      +{{> components/account/navigation account_page='returns'}} - {{!-- New returns portal (ORDERS-7708) --}} - {{> components/common/breadcrumbs breadcrumbs=breadcrumbs}} - {{> components/account/navigation account_page='returns'}} - {{> pages/account/add-return-new}} +
      + +
      + +
      + + {{else}} +

      {{lang 'account.orders.return.already_returned'}}

      + {{lang 'account.orders.return.back_button'}} + {{/if}} -{{/if}} + + +
      {{/partial}} {{> layout/base}} diff --git a/templates/pages/create-return.html b/templates/pages/create-return.html index 7b2ef48912..6cfc282378 100644 --- a/templates/pages/create-return.html +++ b/templates/pages/create-return.html @@ -1,9 +1,123 @@ {{#partial "page"}} -{{> components/common/breadcrumbs breadcrumbs=breadcrumbs}} +{{~inject 'order' order}} +
      -

      Create Return

      + {{#with order}} -{{/partial}} +
      +
      +

      {{lang 'account.returns.from_order' id=id}}

      + {{#if status}}{{status}}{{/if}} +
      + +
      + {{#if date}}

      {{lang 'account.returns.order_date'}}: {{date}}

      {{/if}} + +
      + +
      + + + +
      + + {{#each items}} +
      + +
      + {{> components/common/responsive-img + image=image + class="newReturn-orderLineItemThumbnail" + fallback_size=../../theme_settings.productthumb_size + lazyload=../../theme_settings.lazyload_mode + default_image=../../theme_settings.default_image_product + }} +
      + +
      +

      {{name}}

      + {{#if productAttributesList}} +

      + {{#each productAttributesList}}{{name}}: {{value}}{{#unless @last}} · {{/unless}}{{/each}} +

      + {{/if}} +

      + {{lang 'account.returns.qty'}} {{quantity}}   {{lang 'account.returns.total_price'}} {{price.formatted}} +

      +
      + +
      +
      + + {{lang 'account.orders.return.of_max' max=returnableQuantity}} +
      + + +
      +
      + {{/each}} +
      + + + + + +
      + + {{/with}} + +
      + +{{/partial}} {{> layout/base}}