diff --git a/CHANGELOG.md b/CHANGELOG.md index 31953dca2f..b3f73a8613 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/assets/js/app.js b/assets/js/app.js index b9e92bfdc8..b9a03f8aad 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 getCreateReturn = () => import('./theme/create-return'); const getLogin = () => import('./theme/auth'); const noop = null; @@ -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, 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/js/theme/return-details.js b/assets/js/theme/return-details.js new file mode 100644 index 0000000000..6197a3c920 --- /dev/null +++ b/assets/js/theme/return-details.js @@ -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 }) => ` +
+
${escape(label)}
+
${escape(value)}
+
`).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 ` +
  • +
    + ${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..0bd4222272 100644 --- a/assets/scss/components/_components.scss +++ b/assets/scss/components/_components.scss @@ -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"; 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/assets/scss/components/stencil/addReturn/_addReturn.scss b/assets/scss/components/stencil/addReturn/_addReturn.scss index 1c120b9746..2360918089 100644 --- a/assets/scss/components/stencil/addReturn/_addReturn.scss +++ b/assets/scss/components/stencil/addReturn/_addReturn.scss @@ -137,3 +137,5 @@ width: grid-calc(6, $total-columns); } } + + 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/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 6234f8b366..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,11 +461,28 @@ "action": "Return Action", "comments": "Your Comments", "submit_request": "Submit Return Request", + "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", "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/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 @@

    {{lang 'account.orders.heading' }}

    - {{#if ../settings.returns_enabled}} - {{#if this.return_url}} + {{#if this.return_url}} + {{#or ../settings.returns_v2_enabled ../settings.returns_enabled}} - {{/if}} + {{/or}} {{/if}}
    diff --git a/templates/components/account/returns-list-v2.html b/templates/components/account/returns-list-v2.html new file mode 100644 index 0000000000..faf527db8f --- /dev/null +++ b/templates/components/account/returns-list-v2.html @@ -0,0 +1,36 @@ +

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

    + + \ No newline at end of file diff --git a/templates/pages/account/add-return.html b/templates/pages/account/add-return.html index 0bda0cc689..9130fc8813 100644 --- a/templates/pages/account/add-return.html +++ b/templates/pages/account/add-return.html @@ -20,7 +20,7 @@

    {{lang 'account.returns.from_order' id=forms.return. >
    - +
    @@ -44,8 +44,8 @@
    {{lang 'account.orders.return.order_item'}}{{price.formatted}} - - {{#for 0 quantity}} {{/for}} diff --git a/templates/pages/account/orders/details.html b/templates/pages/account/orders/details.html index c669ad5627..f10eb976b1 100644 --- a/templates/pages/account/orders/details.html +++ b/templates/pages/account/orders/details.html @@ -183,11 +183,11 @@ {{/each}} - {{#if settings.returns_enabled}} + {{#or settings.returns_v2_enabled settings.returns_enabled}} {{#if order.is_complete}} {{lang 'account.orders.details.return'}} {{/if}} - {{/if}} + {{/or}} diff --git a/templates/pages/account/return-details.html b/templates/pages/account/return-details.html new file mode 100644 index 0000000000..11e558e81b --- /dev/null +++ b/templates/pages/account/return-details.html @@ -0,0 +1,48 @@ +{{#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. +--}} + +{{!-- 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'}} + +
    +
    + +
    +
    +

    + +
    + +
    + +
    + +
      +
      + + + +
      +
      + +{{/partial}} +{{> layout/base}} diff --git a/templates/pages/account/returns.html b/templates/pages/account/returns.html index 15047bf7c1..8b1c4cf883 100644 --- a/templates/pages/account/returns.html +++ b/templates/pages/account/returns.html @@ -7,14 +7,30 @@

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

      {{/partial}} {{> layout/base}} + diff --git a/templates/pages/create-return.html b/templates/pages/create-return.html new file mode 100644 index 0000000000..6cfc282378 --- /dev/null +++ b/templates/pages/create-return.html @@ -0,0 +1,123 @@ +{{#partial "page"}} + +{{~inject 'order' order}} +
      + + {{#with order}} + +
      +
      +

      {{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}} 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}}