Skip to content

Commit

Permalink
OrderInformation
Browse files Browse the repository at this point in the history
  • Loading branch information
LauraPinilla committed Mar 25, 2024
1 parent 97c07f8 commit 21b0374
Show file tree
Hide file tree
Showing 10 changed files with 502 additions and 36 deletions.
40 changes: 28 additions & 12 deletions blocks/subscriptions-block/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
39 changes: 22 additions & 17 deletions blocks/subscriptions-block/components/OfferCard/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 <Icon name="ChevronRight" /> to Check <Icon name="Check"/>
export const FeatureDetails = ({ features, className }) => {
if (features.length) {
return (
<ul className={`${className}__card--features`}>
{features.map((feat) => (
<li
className={`${className}__card--features--feature-item`}
key={`feat-${feat.featureText}`}
>
<Icon name="Check" />
<span dangerouslySetInnerHTML={{ __html: feat.featureText }} />
</li>
))}
</ul>
);
}
return null;
};

const OfferCard = ({
headline,
subHeadline,
Expand All @@ -21,20 +39,7 @@ const OfferCard = ({
<span dangerouslySetInnerHTML={{ __html: actionText }} />
</Button>
) : null}

{features.length ? (
<ul className={`${className}__card--features`}>
{features.map((feat) => (
<li
className={`${className}__card--features--feature-item`}
key={`feat-${feat.featureText}`}
>
<Icon name="Check" />
<span dangerouslySetInnerHTML={{ __html: feat.featureText }} />
</li>
))}
</ul>
) : null}
<FeatureDetails features={features} className={className} />
</Stack>
);

Expand All @@ -46,8 +51,8 @@ OfferCard.propTypes = {
features: PropTypes.arrayOf(
PropTypes.shape({
featureText: PropTypes.string,
})
}),
),
};

export default OfferCard;
export default OfferCard;
19 changes: 13 additions & 6 deletions blocks/subscriptions-block/components/OfferToProductList/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -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];
Expand All @@ -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,
Expand Down Expand Up @@ -75,7 +82,7 @@ const OfferToProductList = ({ offer, isLoggedIn, checkoutURL, loginURL, classNam
className={className}
/>
))}
</Grid>
</Grid>
);
};

Expand Down
88 changes: 88 additions & 0 deletions blocks/subscriptions-block/components/OrderInformation/index.jsx
Original file line number Diff line number Diff line change
@@ -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 (
<Stack className={`${className}__summary`}>
<Heading>{phrases.t("checkout-block.order-summary")}</Heading>
<Stack className={`${className}__summary--details`}>
<Stack direction="horizontal" justification="space-between" className={`${className}__summary--details--item`}>
<p>{phrases.t("checkout-block.subtotal")}</p>
<p>{`${currency(orderDetails?.currency)}${orderDetails?.subtotal}`}</p>
</Stack>
<Stack direction="horizontal" justification="space-between" className={`${className}__summary--details--item`}>
<p>{phrases.t("checkout-block.salesTax")}</p>
<p>
{orderDetails?.tax > 0
? `${currency(orderDetails?.currency)}${orderDetails?.tax}`
: "--"}
</p>
</Stack>
</Stack>
<div className={`${className}__summary--dueToday`}>
<p>{phrases.t("checkout-block.due-today")}</p>
<p>{`${currency(orderDetails?.currency)}${orderDetails?.total}`}</p>
</div>
</Stack>
);
};

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 (
<Stack as="div" className={`${className}__orderCard--productPrice`}>
<Heading> {item.priceName}</Heading>
{showPriceDescription && (
<Paragraph dangerouslySetInnerHTML={{ __html: item?.priceDescription }} />
)}
{showProductFeatures && (
<FeatureDetails
features={item?.productAttributes}
className={`${className}__orderCard`}
/>
)}
</Stack>
);
});
}
return null;
};

return (
<section className={`${className}__orderCard`}>
<ProductPriceDetails
details={orderDetails}
showPriceDescription={showPriceDescription}
showProductFeatures={showProductFeatures}
className={className}
/>
{showOfferURL && (
<Link href={offerURL}>{phrases.t("checkout-block.view-subscription-offers")}</Link>
)}
<OrderSummary orderDetails={orderDetails} className={`${className}__orderCard`} />
</section>
);
};

export default OrderInformation;
104 changes: 104 additions & 0 deletions blocks/subscriptions-block/components/OrderInformation/index.test.js
Original file line number Diff line number Diff line change
@@ -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: "<p>with tax description price</p>",
priceName: "All access Annual",
priceSummary: "<p>with tax summary price</p>",
productDescription: "<p>COP Currency description</p>",
quantity: 1,
shortDescription: "<p>COP Currency description</p>",
sku: "0987",
subtotal: 20100,
tax: 0,
taxInclusive: undefined,
total: 20000,
productAttributes: [
{
featureText: "<p>Unlimited access to The Daily Intelligencer</p>",
},
{
featureText: "<p>Save $40</p>",
},
{
featureText: "<p>A <strong>bonus subscription</strong> to share</p>",
},
],
},
],
};

describe("OfferCard", () => {
it("renders order info", ()=>{
render(<OrderInformation orderDetails={orderDetails} offerURL={'/offer/'} showOfferURL={false} showPriceDescription={false} showProductFeatures={true} />);
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(<OrderInformation orderDetails={orderDetails} showOfferURL={false} showPriceDescription={true} showProductFeatures={true} />);
expect(screen.getByText("with tax description price")).toBeVisible();
});

it("renders features", () => {
render(<OrderInformation orderDetails={orderDetails} offerURL={'/offer/'} showOfferURL={true} showPriceDescription={false} showProductFeatures={true} />);
const list = screen.getByRole("list")
const { getAllByRole } = within(list)
const items = getAllByRole("listitem")
expect(items.length).toBe(3);
});

it("renders link to offer", ()=>{
render(<OrderInformation orderDetails={orderDetails} offerURL={'/offer/'} showOfferURL={true} showPriceDescription={false} showProductFeatures={true} />);
expect(screen.getByRole('link', { name: 'checkout-block.view-subscription-offers' })).toHaveAttribute('href', '/offer/');
});
});
Loading

0 comments on commit 21b0374

Please sign in to comment.