diff --git a/blocks/subscriptions-block/_index.scss b/blocks/subscriptions-block/_index.scss
index 9110d00343..6c263861e8 100644
--- a/blocks/subscriptions-block/_index.scss
+++ b/blocks/subscriptions-block/_index.scss
@@ -136,24 +136,40 @@
@include scss.block-properties("checkout-payment");
}
- &__test {
- &-1 {
- @include scss.block-components("checkout-payment-test-1");
- @include scss.block-properties("checkout-payment-test-1");
+ &__orderCard {
+ &--productPrice {
+ @include scss.block-components("checkout-order-card-productPrice");
+ @include scss.block-properties("checkout-order-card-productPrice");
}
- &-2 {
- @include scss.block-components("checkout-payment-test-2");
- @include scss.block-properties("checkout-payment-test-2");
+ &__card--features {
+ &--feature-item {
+ @include scss.block-components("checkout-order-card--features--item");
+ @include scss.block-properties("checkout-order-card--features--item");
+ }
+ @include scss.block-components("checkout-order-card--features");
+ @include scss.block-properties("checkout-order-card--features");
}
- &-row {
- @include scss.block-components("checkout-payment-test-row");
- @include scss.block-properties("checkout-payment-test-row");
+ &__summary {
+ &--dueToday{
+ @include scss.block-components("checkout-order-card--summary--dueToday");
+ @include scss.block-properties("checkout-order-card--summary--dueToday");
+ }
+ &--details{
+ &--item{
+ @include scss.block-components("checkout-order-card--summary--details--item");
+ @include scss.block-properties("checkout-order-card--summary--details--item");
+ }
+ @include scss.block-components("checkout-order-card--summary--details");
+ @include scss.block-properties("checkout-order-card--summary--details");
+ }
+ @include scss.block-components("checkout-order-card--summary");
+ @include scss.block-properties("checkout-order-card--summary");
}
- @include scss.block-components("checkout-payment-test");
- @include scss.block-properties("checkout-payment-test");
+ @include scss.block-components("checkout-order-card");
+ @include scss.block-properties("checkout-order-card");
}
@include scss.block-components("checkout");
diff --git a/blocks/subscriptions-block/components/OfferCard/index.jsx b/blocks/subscriptions-block/components/OfferCard/index.jsx
index 7cd4adb89d..f026511480 100644
--- a/blocks/subscriptions-block/components/OfferCard/index.jsx
+++ b/blocks/subscriptions-block/components/OfferCard/index.jsx
@@ -2,7 +2,25 @@ import React from "react";
import PropTypes from "@arc-fusion/prop-types";
import { Heading, Button, Stack, Paragraph, Icon } from "@wpmedia/arc-themes-components";
-// TO-DO: Change the Icon to Check
+export const FeatureDetails = ({ features, className }) => {
+ if (features.length) {
+ return (
+
+ {features.map((feat) => (
+ -
+
+
+
+ ))}
+
+ );
+ }
+ return null;
+};
+
const OfferCard = ({
headline,
subHeadline,
@@ -21,20 +39,7 @@ const OfferCard = ({
) : null}
-
- {features.length ? (
-
- {features.map((feat) => (
- -
-
-
-
- ))}
-
- ) : null}
+
);
@@ -46,8 +51,8 @@ OfferCard.propTypes = {
features: PropTypes.arrayOf(
PropTypes.shape({
featureText: PropTypes.string,
- })
+ }),
),
};
-export default OfferCard;
\ No newline at end of file
+export default OfferCard;
diff --git a/blocks/subscriptions-block/components/OfferToProductList/index.jsx b/blocks/subscriptions-block/components/OfferToProductList/index.jsx
index 2fc47c5a55..83b72bcc66 100644
--- a/blocks/subscriptions-block/components/OfferToProductList/index.jsx
+++ b/blocks/subscriptions-block/components/OfferToProductList/index.jsx
@@ -4,6 +4,9 @@ import useSales from "../useSales";
import { Grid } from "@wpmedia/arc-themes-components";
import OfferCard from "../OfferCard";
+export const ARCXP_CART = 'ArcXP_cart';
+export const ARCXP_CAMPAIGN = 'ArcXP_campaignName';
+
const OfferToProductList = ({ offer, isLoggedIn, checkoutURL, loginURL, className }) => {
const { Sales } = useSales();
@@ -21,7 +24,7 @@ const OfferToProductList = ({ offer, isLoggedIn, checkoutURL, loginURL, classNam
products[productIdx].attributes.length !== 0
? products[productIdx].attributes.map((feature) => ({
featureText: feature.value,
- }))
+ }))
: [];
const { sku } = products[productIdx];
const { priceCode } = strategies[strategiesIdx];
@@ -32,21 +35,25 @@ const OfferToProductList = ({ offer, isLoggedIn, checkoutURL, loginURL, classNam
actionText: strategies[strategiesIdx].summary,
actionEvent: () => {
Sales.clearCart()
- .then(() =>
+ .then(() => {
Sales.addItemToCart([
{
sku,
priceCode,
quantity: 1,
},
- ])
- )
+ ]);
+ const maxEndDate = Math.max(...offer?.campaigns?.map(c => c.validUntil));
+ const liveCampaing = offer?.campaigns?.find(c => c.validUntil === null || c.validUntil === maxEndDate);
+ localStorage.setItem(ARCXP_CAMPAIGN, liveCampaing?.name);
+ })
.then(() => {
if (isLoggedIn) {
window.location.href = checkoutURL;
return;
}
- window.location.href = `${loginURL}?redirect=${checkoutURL}`;
+ localStorage.setItem(ARCXP_CART, JSON.stringify({sku, priceCode}));
+ window.location.href = `${loginURL}&redirect=${checkoutURL}`;
});
},
features,
@@ -75,7 +82,7 @@ const OfferToProductList = ({ offer, isLoggedIn, checkoutURL, loginURL, classNam
className={className}
/>
))}
-
+
);
};
diff --git a/blocks/subscriptions-block/components/OrderInformation/index.jsx b/blocks/subscriptions-block/components/OrderInformation/index.jsx
new file mode 100644
index 0000000000..0b29fa355e
--- /dev/null
+++ b/blocks/subscriptions-block/components/OrderInformation/index.jsx
@@ -0,0 +1,88 @@
+import React from "react";
+
+import { usePhrases, Link, Heading, Paragraph, Stack } from "@wpmedia/arc-themes-components";
+import { FeatureDetails } from "../OfferCard";
+import currency from "../../utils/currency";
+
+const OrderSummary = ({ orderDetails, className }) => {
+ const phrases = usePhrases();
+
+ return (
+
+ {phrases.t("checkout-block.order-summary")}
+
+
+ {phrases.t("checkout-block.subtotal")}
+ {`${currency(orderDetails?.currency)}${orderDetails?.subtotal}`}
+
+
+ {phrases.t("checkout-block.salesTax")}
+
+ {orderDetails?.tax > 0
+ ? `${currency(orderDetails?.currency)}${orderDetails?.tax}`
+ : "--"}
+
+
+
+
+
{phrases.t("checkout-block.due-today")}
+
{`${currency(orderDetails?.currency)}${orderDetails?.total}`}
+
+
+ );
+};
+
+const OrderInformation = ({
+ offerURL,
+ showOfferURL,
+ showPriceDescription,
+ showProductFeatures,
+ orderDetails,
+ className,
+}) => {
+ const phrases = usePhrases();
+
+ const ProductPriceDetails = ({
+ details = [],
+ showPriceDescription,
+ showProductFeatures,
+ className,
+ }) => {
+ if (details?.items?.length) {
+ return details?.items?.map((item) => {
+ return (
+
+ {item.priceName}
+ {showPriceDescription && (
+
+ )}
+ {showProductFeatures && (
+
+ )}
+
+ );
+ });
+ }
+ return null;
+ };
+
+ return (
+
+
+ {showOfferURL && (
+ {phrases.t("checkout-block.view-subscription-offers")}
+ )}
+
+
+ );
+};
+
+export default OrderInformation;
diff --git a/blocks/subscriptions-block/components/OrderInformation/index.test.js b/blocks/subscriptions-block/components/OrderInformation/index.test.js
new file mode 100644
index 0000000000..74712e1e4f
--- /dev/null
+++ b/blocks/subscriptions-block/components/OrderInformation/index.test.js
@@ -0,0 +1,104 @@
+import React from "react";
+import { screen, render, within } from "@testing-library/react";
+import "@testing-library/jest-dom";
+import OrderInformation from "./index";
+import currency from "../../utils/currency";
+
+
+jest.mock("@arc-publishing/sdk-identity", () => ({
+ __esModule: true,
+ default: {
+ apiOrigin: "",
+ options: jest.fn(),
+ },
+}));
+
+jest.mock("fusion:properties", () =>
+ jest.fn(() => ({
+ api: {
+ identity: {
+ origin: "https://corecomponents-arc-demo-3-prod.api.cdn.arcpublishing.com",
+ },
+ retail: {
+ origin: "https://corecomponents-arc-demo-3-prod.api.cdn.arcpublishing.com",
+ endpoint: "/retail/public/v1/offer/live/",
+ },
+ },
+ })),
+);
+
+jest.mock("fusion:context", () => ({
+ __esModule: true,
+ useFusionContext: () => ({
+ arcSite: "Test Site",
+ }),
+}));
+
+const orderDetails = {
+ currency: "COP",
+ shipping: 0,
+ subtotal: 20000,
+ tax: 100,
+ taxSupported: true,
+ total: 20100,
+ items: [
+ {
+ name: "COP Currency",
+ price: 20000,
+ priceCode: "Q6R7UO",
+ priceDescription: "with tax description price
",
+ priceName: "All access Annual",
+ priceSummary: "with tax summary price
",
+ productDescription: "COP Currency description
",
+ quantity: 1,
+ shortDescription: "COP Currency description
",
+ sku: "0987",
+ subtotal: 20100,
+ tax: 0,
+ taxInclusive: undefined,
+ total: 20000,
+ productAttributes: [
+ {
+ featureText: "Unlimited access to The Daily Intelligencer
",
+ },
+ {
+ featureText: "Save $40
",
+ },
+ {
+ featureText: "A bonus subscription to share
",
+ },
+ ],
+ },
+ ],
+};
+
+describe("OfferCard", () => {
+ it("renders order info", ()=>{
+ render();
+ expect(screen.getByText(orderDetails?.items?.[0]?.priceName)).toBeVisible();
+ expect(screen.getByText("checkout-block.order-summary")).toBeVisible();
+ expect(screen.getByText("checkout-block.subtotal")).toBeVisible();
+ expect(screen.getByText(`${currency(orderDetails?.currency)}${orderDetails?.subtotal}`)).toBeVisible();
+ expect(screen.getByText("checkout-block.salesTax")).toBeVisible();
+ expect(screen.getByText(`${currency(orderDetails?.currency)}${orderDetails?.total}`)).toBeVisible();
+ expect(screen.getByText("checkout-block.due-today")).toBeVisible();
+ });
+
+ it("renders price description", ()=>{
+ render();
+ expect(screen.getByText("with tax description price")).toBeVisible();
+ });
+
+ it("renders features", () => {
+ render();
+ const list = screen.getByRole("list")
+ const { getAllByRole } = within(list)
+ const items = getAllByRole("listitem")
+ expect(items.length).toBe(3);
+ });
+
+ it("renders link to offer", ()=>{
+ render();
+ expect(screen.getByRole('link', { name: 'checkout-block.view-subscription-offers' })).toHaveAttribute('href', '/offer/');
+ });
+});
diff --git a/blocks/subscriptions-block/components/useOrder.jsx b/blocks/subscriptions-block/components/useOrder.jsx
new file mode 100644
index 0000000000..3e0fc1fc26
--- /dev/null
+++ b/blocks/subscriptions-block/components/useOrder.jsx
@@ -0,0 +1,114 @@
+import { useState, useEffect } from "react";
+
+import { useSales } from "@wpmedia/arc-themes-components";
+import { ARCXP_CAMPAIGN } from "./OfferToProductList";
+import useOffer from "./useOffer";
+
+const useOrder = (orderNumber) => {
+ const { Sales } = useSales();
+
+ const [order, setOrder] = useState();
+ const [orderDetails, setOrderDetails] = useState();
+ const [cart, setCart] = useState();
+ const [cartDetails, setCartDetails] = useState();
+ const [error, setError] = useState();
+
+ const [campaignName, setCampaignName] = useState();
+
+ const { offer } = useOffer({
+ campaignCode: campaignName,
+ });
+
+ useEffect(() => {
+ const getCart = async () => {
+ const cart = await Sales.getCart();
+ setCart(cart);
+ };
+ getCart();
+
+ const campaignName = localStorage.getItem(ARCXP_CAMPAIGN);
+ setCampaignName(campaignName);
+ }, []);
+
+ useEffect(() => {
+ const getOrder = async () => {
+ try{
+ const order = await Sales.getOrderDetails(orderNumber);
+ setOrder(order);
+ }catch(e){
+ setError(e);
+ }
+ };
+ if (orderNumber) {
+ getOrder();
+ }
+ }, [orderNumber]);
+
+ useEffect(() => {
+ const getProductPriceDetailsFromOffer = (sku, priceCode) => {
+ let productAttributes;
+ let productDescription;
+ let priceName;
+ let priceDescription;
+ let priceSummary;
+ let rates;
+
+ const productBySku = offer?.products?.find((item) => item?.sku === sku);
+
+ if (productBySku) {
+ productAttributes =
+ typeof productBySku?.attributes !== "undefined" && productBySku?.attributes?.length !== 0
+ ? productBySku?.attributes.map((feature) => ({
+ featureText: feature.value,
+ }))
+ : [];
+ productDescription = productBySku?.description;
+ const pricingStrategy = productBySku?.pricingStrategies?.find((price)=> price?.priceCode === priceCode);
+
+ priceName = pricingStrategy?.name;
+ priceDescription = pricingStrategy?.description;
+ priceSummary = pricingStrategy?.summary;
+ rates = pricingStrategy?.rates;
+ }
+
+ return {
+ productAttributes,
+ productDescription,
+ priceName,
+ priceDescription,
+ priceSummary,
+ rates,
+ };
+ };
+
+ if (offer) {
+ if (order) {
+ const itemsDetail = order?.items?.map((item) => {
+ const { productAttributes, productDescription, priceName, priceDescription, priceSummary, rates } = getProductPriceDetailsFromOffer(
+ item?.sku,
+ item?.priceCode,
+ );
+ return { ...item, productAttributes, productDescription, priceName, priceDescription, priceSummary, rates};
+ });
+ setOrderDetails({...order, items: itemsDetail})
+ } else if (cart) {
+ const itemsDetail = cart?.items?.map((item) => {
+ const { productAttributes, productDescription, priceName, priceDescription, priceSummary, rates, taxInclusive } = getProductPriceDetailsFromOffer(
+ item?.sku,
+ item?.priceCode,
+ );
+ return { ...item, productAttributes, productDescription, priceName, priceDescription, priceSummary, rates, taxInclusive};
+ });
+ setCartDetails({...cart, items: itemsDetail})
+ }
+ }
+ }, [order, cart, offer]);
+
+ return {
+ cartDetails,
+ orderDetails,
+ error
+ };
+};
+
+export default useOrder;
diff --git a/blocks/subscriptions-block/components/usePaymentRedirect.jsx b/blocks/subscriptions-block/components/usePaymentRedirect.jsx
index d1806039b3..570d6a4aa4 100644
--- a/blocks/subscriptions-block/components/usePaymentRedirect.jsx
+++ b/blocks/subscriptions-block/components/usePaymentRedirect.jsx
@@ -1,5 +1,5 @@
import { useState, useEffect } from "react";
-import useSales from "./useSales";
+import { useSales } from "@wpmedia/arc-themes-components";
import { LABEL_ORDER_NUMBER_PAYPAL } from "../features/checkout/default";
export const usePaymentRedirect = (
diff --git a/blocks/subscriptions-block/intl.json b/blocks/subscriptions-block/intl.json
index 07358dc45b..9f22f06403 100644
--- a/blocks/subscriptions-block/intl.json
+++ b/blocks/subscriptions-block/intl.json
@@ -6848,5 +6848,14 @@
"vi": "Cập nhật phương thức thanh toán",
"zh-CN": "更新付款方式",
"zh-TW": "更新付款方式"
+ },
+ "checkout-block.view-subscription-offers": {
+ "en": "View subscription offers"
+ },
+ "checkout-block.subtotal": {
+ "en": "Subtotal"
+ },
+ "checkout-block.salesTax": {
+ "en": "Sales tax"
}
}
\ No newline at end of file
diff --git a/blocks/subscriptions-block/themes/news.json b/blocks/subscriptions-block/themes/news.json
index a1223d662f..5c8940e0c7 100644
--- a/blocks/subscriptions-block/themes/news.json
+++ b/blocks/subscriptions-block/themes/news.json
@@ -401,6 +401,126 @@
}
}
},
+ "checkout-order-card": {
+ "styles": {
+ "default": {
+ "display": "flex",
+ "flex-direction": "column",
+ "padding-block-start": "var(--global-spacing-4)",
+ "padding-inline-end": "var(--global-spacing-4)",
+ "padding-block-end": "var(--global-spacing-4)",
+ "padding-inline-start": "var(--global-spacing-4)",
+ "gap": "var(--global-spacing-5)",
+ "column-gap": "var(--global-spacing-5)",
+ "components": {
+ "link": {
+ "color": "var(--text-color)",
+ "text-decoration": "underline",
+ "font-size": "var(--global-font-size-4)",
+ "font-weight": "var(--global-font-weight-4)"
+ }
+ }
+ }
+ }
+ },
+ "checkout-order-card-productPrice": {
+ "styles": {
+ "default": {
+ "display": "flex",
+ "flex-direction": "column",
+ "gap": "var(--global-spacing-5)",
+ "column-gap": "var(--global-spacing-5)",
+ "components": {
+ "heading": {
+ "font-size": "var(--global-font-size-9)",
+ "font-weight": "var(--global-font-weight-7)",
+ "line-height": "var(--global-line-height-6)"
+ }
+ }
+ }
+ }
+ },
+ "checkout-order-card--features": {
+ "styles": {
+ "default": {
+ "align-self": "baseline"
+ }
+ }
+ },
+ "checkout-order-card--features--item": {
+ "styles": {
+ "default": {
+ "align-items": "center",
+ "display": "flex",
+ "margin-block-end": "var(--global-spacing-2)",
+ "components": {
+ "icon": {
+ "fill": "var(--status-color-success)",
+ "display": "flex",
+ "inline-size": "var(--global-spacing-4)",
+ "block-size": "var(--global-spacing-4)",
+ "margin-block-start": "0",
+ "margin-inline-end": "var(--global-spacing-2)",
+ "margin-block-end": "0",
+ "margin-inline-start": "0"
+ }
+ }
+ }
+ }
+ },
+ "checkout-order-card--summary": {
+ "styles": {
+ "default": {
+ "gap": "var(--global-spacing-2)",
+ "components": {
+ "heading": {
+ "font-family": "var(--font-family-secondary)",
+ "font-weight": "var(--global-font-weight-7)",
+ "font-size": "var(--global-font-size-4)",
+ "padding-block-end": "var(--global-spacing-2)",
+ "border-block-end-width": "1px",
+ "border-block-end-style": "solid",
+ "border-block-end-color": "var(--border-color)"
+ }
+ }
+ }
+ }
+ },
+ "checkout-order-card--summary--dueToday": {
+ "styles": {
+ "default": {
+ "display": "flex",
+ "justify-content": "space-between",
+ "padding-block-start": "var(--global-spacing-2)",
+ "border-block-start-width": "1px",
+ "border-block-start-style": "solid",
+ "border-block-start-color": "var(--border-color)",
+ "font-family": "var(--font-family-secondary)",
+ "font-weight": "var(--global-font-weight-7)",
+ "font-size": "var(--global-font-size-7)",
+ "inline-size": "100%",
+ "align-items": "flex-start"
+ }
+ }
+ },
+ "checkout-order-card--summary--details":{
+ "styles": {
+ "default": {
+ "gap": "var(--global-spacing-2)"
+ }
+ }
+ },
+ "checkout-order-card--summary--details--item": {
+ "styles": {
+ "default": {
+ "flex-direction": "row",
+ "justify-content": "space-between",
+ "font-family": "var(--font-family-primary)",
+ "font-weight": "var(--global-font-weight-4)",
+ "font-size": "var(--global-font-size-3)"
+ }
+ }
+ },
"offer": {
"styles": {
"default": {
diff --git a/locale/en.json b/locale/en.json
index cb45782a46..77ed7228a4 100644
--- a/locale/en.json
+++ b/locale/en.json
@@ -455,6 +455,7 @@
"checkout-block.Zambia": "Zambia",
"checkout-block.Zimbabwe": "Zimbabwe",
"checkout-block.back-to-offer-page": "Back to subscription selection",
+ "checkout-block.view-subscription-offers": "View subscription offers",
"checkout-block.cardNumber": "Card number",
"checkout-block.cardholderName": "Name on card",
"checkout-block.cardholderName-requirements": "Please enter name on card",
@@ -463,6 +464,8 @@
"checkout-block.country": "Country or region",
"checkout-block.country-requirements": "Please select country or region",
"checkout-block.due-today": "Due today",
+ "checkout-block.subtotal": "Subtotal",
+ "checkout-block.salesTax": "Sales tax",
"checkout-block.email": "Email address",
"checkout-block.email-requirements": "Please enter a valid email address",
"checkout-block.empty-cart-message": "Select from one of our offers",