@edx/frontend-app-subscription-manage 1.25.0 → 1.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,9 +3,8 @@ interface OrderCardProps {
3
3
  purchaseDate: string;
4
4
  totalCost: string;
5
5
  orderNumber: string;
6
- isReceiptDisabled?: boolean;
7
- onViewReceipt: () => void;
6
+ receiptUrl?: string | null;
8
7
  onViewOrderDetails: () => void;
9
8
  }
10
- declare const OrderHistoryCard: ({ title, purchaseDate, totalCost, orderNumber, isReceiptDisabled, onViewReceipt, onViewOrderDetails, }: OrderCardProps) => import("react/jsx-runtime").JSX.Element;
9
+ declare const OrderHistoryCard: ({ title, purchaseDate, totalCost, orderNumber, receiptUrl, onViewOrderDetails, }: OrderCardProps) => import("react/jsx-runtime").JSX.Element;
11
10
  export default OrderHistoryCard;
@@ -3,11 +3,11 @@ import { Card, Button, Icon } from '@openedx/paragon';
3
3
  import { useIntl } from 'react-intl';
4
4
  import { Launch } from '@openedx/paragon/icons';
5
5
  import messages from './messages';
6
- const OrderHistoryCard = ({ title, purchaseDate, totalCost, orderNumber, isReceiptDisabled = false, onViewReceipt, onViewOrderDetails, }) => {
6
+ const OrderHistoryCard = ({ title, purchaseDate, totalCost, orderNumber, receiptUrl, onViewOrderDetails, }) => {
7
7
  const { formatMessage } = useIntl();
8
8
  const receiptDescriptionId = `receipt-description-${orderNumber.replace(/\s+/g, '-').toLowerCase()}`;
9
9
  const detailsDescriptionId = `details-description-${orderNumber.replace(/\s+/g, '-').toLowerCase()}`;
10
- return (_jsx("section", { "aria-labelledby": `order-title-${orderNumber}`, children: _jsx(Card, { className: "order-card", "aria-label": `${title} order details`, children: _jsx(Card.Body, { className: "p-3", children: _jsxs("div", { className: "d-flex justify-content-between align-items-start flex-wrap", children: [_jsxs("div", { children: [_jsx("h6", { className: "mb-2", children: title }), _jsxs("div", { className: "d-flex gap-1", children: [_jsxs("div", { className: "x-small", children: [_jsxs("p", { className: "text-muted orderHistoryCard__details mr1-1 mb-0", children: [formatMessage(messages.dateOfPurchaseLabel), ":"] }), _jsxs("p", { className: "text-muted mr-1 orderHistoryCard__details mb-0", children: [formatMessage(messages.totalCostLabel), ":"] }), _jsxs("p", { className: "text-muted mr-1 orderHistoryCard__details mb-0", children: [formatMessage(messages.orderNumberLabel), ":"] })] }), _jsxs("div", { className: "x-small", children: [_jsx("p", { className: "mb-0", children: purchaseDate }), _jsx("p", { className: "mb-0", children: totalCost }), _jsx("p", { className: "mb-0", children: orderNumber })] })] })] }), _jsxs("div", { className: "d-flex align-items-center gap-3 mt-2 mt-md-auto", children: [_jsxs(Button, { variant: "link", size: "sm", onClick: isReceiptDisabled ? undefined : onViewReceipt, disabled: isReceiptDisabled, className: "d-flex gap-1 p-0 orderHistoryCard__link", "aria-describedby": receiptDescriptionId, "aria-label": `View receipt for order ${orderNumber}`, children: [formatMessage(messages.viewReceiptButton), " ", _jsx("span", { children: _jsx(Icon, { size: "xs", src: Launch, "aria-hidden": true }) }), _jsxs("span", { id: receiptDescriptionId, className: "sr-only", children: [' ', "for ", title] })] }), _jsxs(Button, { variant: "link", size: "sm", onClick: onViewOrderDetails, className: "p-0 orderHistoryCard__link", "aria-describedby": detailsDescriptionId, "aria-label": `View details for order ${orderNumber}`, children: [formatMessage(messages.viewOrderDetailsButton), _jsxs("span", { id: detailsDescriptionId, className: "sr-only", children: [' ', "for ", title] })] })] })] }) }) }) }));
10
+ return (_jsx("section", { "aria-labelledby": `order-title-${orderNumber}`, children: _jsx(Card, { className: "order-card", "aria-label": `${title} order details`, children: _jsx(Card.Body, { className: "p-3", children: _jsxs("div", { className: "d-flex justify-content-between align-items-start flex-wrap", children: [_jsxs("div", { children: [_jsx("h6", { className: "mb-2", children: title }), _jsxs("div", { className: "d-flex gap-1", children: [_jsxs("div", { className: "x-small", children: [_jsxs("p", { className: "text-muted orderHistoryCard__details mr1-1 mb-0", children: [formatMessage(messages.dateOfPurchaseLabel), ":"] }), _jsxs("p", { className: "text-muted mr-1 orderHistoryCard__details mb-0", children: [formatMessage(messages.totalCostLabel), ":"] }), _jsxs("p", { className: "text-muted mr-1 orderHistoryCard__details mb-0", children: [formatMessage(messages.orderNumberLabel), ":"] })] }), _jsxs("div", { className: "x-small", children: [_jsx("p", { className: "mb-0", children: purchaseDate }), _jsx("p", { className: "mb-0", children: totalCost }), _jsx("p", { className: "mb-0", children: orderNumber })] })] })] }), _jsxs("div", { className: "d-flex align-items-center gap-3 mt-2 mt-md-auto", children: [_jsxs(Button, { variant: "link", size: "sm", as: "a", href: receiptUrl !== null && receiptUrl !== void 0 ? receiptUrl : undefined, target: "_blank", rel: "noopener noreferrer", disabled: !receiptUrl, className: "d-flex gap-1 p-0 orderHistoryCard__link", "aria-describedby": receiptDescriptionId, "aria-label": `View receipt for order ${orderNumber}`, children: [formatMessage(messages.viewReceiptButton), " ", _jsx("span", { children: _jsx(Icon, { size: "xs", src: Launch, "aria-hidden": true }) }), _jsxs("span", { id: receiptDescriptionId, className: "sr-only", children: [' ', "for ", title] })] }), _jsxs(Button, { variant: "link", size: "sm", onClick: onViewOrderDetails, className: "p-0 orderHistoryCard__link", "aria-describedby": detailsDescriptionId, "aria-label": `View details for order ${orderNumber}`, children: [formatMessage(messages.viewOrderDetailsButton), _jsxs("span", { id: detailsDescriptionId, className: "sr-only", children: [' ', "for ", title] })] })] })] }) }) }) }));
11
11
  };
12
12
  export default OrderHistoryCard;
13
13
  //# sourceMappingURL=OrderHistoryCard.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"OrderHistoryCard.js","sourceRoot":"","sources":["../../../src/components/OrderHistory/OrderHistoryCard.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,QAAQ,MAAM,YAAY,CAAC;AAYlC,MAAM,gBAAgB,GAAG,CAAC,EACxB,KAAK,EACL,YAAY,EACZ,SAAS,EACT,WAAW,EACX,iBAAiB,GAAG,KAAK,EACzB,aAAa,EACb,kBAAkB,GACH,EAAE,EAAE;IACnB,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC;IACpC,MAAM,oBAAoB,GAAG,uBAAuB,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;IACrG,MAAM,oBAAoB,GAAG,uBAAuB,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;IAErG,OAAO,CACL,qCAA0B,eAAe,WAAW,EAAE,YACpD,KAAC,IAAI,IAAC,SAAS,EAAC,YAAY,gBAAa,GAAG,KAAK,gBAAgB,YAC/D,KAAC,IAAI,CAAC,IAAI,IAAC,SAAS,EAAC,KAAK,YACxB,eAAK,SAAS,EAAC,4DAA4D,aACzE,0BACE,aAAI,SAAS,EAAC,MAAM,YAAE,KAAK,GAAM,EAEjC,eAAK,SAAS,EAAC,cAAc,aAC3B,eAAK,SAAS,EAAC,SAAS,aACtB,aAAG,SAAS,EAAC,iDAAiD,aAAE,aAAa,CAAC,QAAQ,CAAC,mBAAmB,CAAC,SAAM,EACjH,aAAG,SAAS,EAAC,gDAAgD,aAAE,aAAa,CAAC,QAAQ,CAAC,cAAc,CAAC,SAAM,EAC3G,aAAG,SAAS,EAAC,gDAAgD,aAAE,aAAa,CAAC,QAAQ,CAAC,gBAAgB,CAAC,SAAM,IACzG,EAEN,eAAK,SAAS,EAAC,SAAS,aACtB,YAAG,SAAS,EAAC,MAAM,YAAE,YAAY,GAAK,EACtC,YAAG,SAAS,EAAC,MAAM,YAAE,SAAS,GAAK,EACnC,YAAG,SAAS,EAAC,MAAM,YAAE,WAAW,GAAK,IACjC,IACF,IACF,EAEN,eAAK,SAAS,EAAC,iDAAiD,aAC9D,MAAC,MAAM,IACL,OAAO,EAAC,MAAM,EACd,IAAI,EAAC,IAAI,EACT,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,EACtD,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,EAAC,yCAAyC,sBACjC,oBAAoB,gBAC1B,0BAA0B,WAAW,EAAE,aAElD,aAAa,CAAC,QAAQ,CAAC,iBAAiB,CAAC,OAAE,yBAAM,KAAC,IAAI,IAAC,IAAI,EAAC,IAAI,EAAC,GAAG,EAAE,MAAM,wBAAgB,GAAO,EACpG,gBAAM,EAAE,EAAE,oBAAoB,EAAE,SAAS,EAAC,SAAS,aAChD,GAAG,UAAM,KAAK,IACV,IACA,EAET,MAAC,MAAM,IACL,OAAO,EAAC,MAAM,EACd,IAAI,EAAC,IAAI,EACT,OAAO,EAAE,kBAAkB,EAC3B,SAAS,EAAC,4BAA4B,sBACpB,oBAAoB,gBAC1B,0BAA0B,WAAW,EAAE,aAElD,aAAa,CAAC,QAAQ,CAAC,sBAAsB,CAAC,EAC/C,gBAAM,EAAE,EAAE,oBAAoB,EAAE,SAAS,EAAC,SAAS,aAChD,GAAG,UAAM,KAAK,IACV,IACA,IACL,IACF,GACI,GACP,GACC,CACX,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,gBAAgB,CAAC","sourcesContent":["import { Card, Button, Icon } from '@openedx/paragon';\nimport { useIntl } from 'react-intl';\nimport { Launch } from '@openedx/paragon/icons';\nimport messages from './messages';\n\ninterface OrderCardProps {\n title: string,\n purchaseDate: string,\n totalCost: string,\n orderNumber: string,\n isReceiptDisabled?: boolean,\n onViewReceipt: () => void,\n onViewOrderDetails: () => void,\n}\n\nconst OrderHistoryCard = ({\n title,\n purchaseDate,\n totalCost,\n orderNumber,\n isReceiptDisabled = false,\n onViewReceipt,\n onViewOrderDetails,\n}: OrderCardProps) => {\n const { formatMessage } = useIntl();\n const receiptDescriptionId = `receipt-description-${orderNumber.replace(/\\s+/g, '-').toLowerCase()}`;\n const detailsDescriptionId = `details-description-${orderNumber.replace(/\\s+/g, '-').toLowerCase()}`;\n\n return (\n <section aria-labelledby={`order-title-${orderNumber}`}>\n <Card className=\"order-card\" aria-label={`${title} order details`}>\n <Card.Body className=\"p-3\">\n <div className=\"d-flex justify-content-between align-items-start flex-wrap\">\n <div>\n <h6 className=\"mb-2\">{title}</h6>\n\n <div className=\"d-flex gap-1\">\n <div className=\"x-small\">\n <p className=\"text-muted orderHistoryCard__details mr1-1 mb-0\">{formatMessage(messages.dateOfPurchaseLabel)}:</p>\n <p className=\"text-muted mr-1 orderHistoryCard__details mb-0\">{formatMessage(messages.totalCostLabel)}:</p>\n <p className=\"text-muted mr-1 orderHistoryCard__details mb-0\">{formatMessage(messages.orderNumberLabel)}:</p>\n </div>\n\n <div className=\"x-small\">\n <p className=\"mb-0\">{purchaseDate}</p>\n <p className=\"mb-0\">{totalCost}</p>\n <p className=\"mb-0\">{orderNumber}</p>\n </div>\n </div>\n </div>\n\n <div className=\"d-flex align-items-center gap-3 mt-2 mt-md-auto\">\n <Button\n variant=\"link\"\n size=\"sm\"\n onClick={isReceiptDisabled ? undefined : onViewReceipt}\n disabled={isReceiptDisabled}\n className=\"d-flex gap-1 p-0 orderHistoryCard__link\"\n aria-describedby={receiptDescriptionId}\n aria-label={`View receipt for order ${orderNumber}`}\n >\n {formatMessage(messages.viewReceiptButton)} <span><Icon size=\"xs\" src={Launch} aria-hidden /></span>\n <span id={receiptDescriptionId} className=\"sr-only\">\n {' '}for {title}\n </span>\n </Button>\n\n <Button\n variant=\"link\"\n size=\"sm\"\n onClick={onViewOrderDetails}\n className=\"p-0 orderHistoryCard__link\"\n aria-describedby={detailsDescriptionId}\n aria-label={`View details for order ${orderNumber}`}\n >\n {formatMessage(messages.viewOrderDetailsButton)}\n <span id={detailsDescriptionId} className=\"sr-only\">\n {' '}for {title}\n </span>\n </Button>\n </div>\n </div>\n </Card.Body>\n </Card>\n </section>\n );\n};\n\nexport default OrderHistoryCard;\n"]}
1
+ {"version":3,"file":"OrderHistoryCard.js","sourceRoot":"","sources":["../../../src/components/OrderHistory/OrderHistoryCard.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,QAAQ,MAAM,YAAY,CAAC;AAWlC,MAAM,gBAAgB,GAAG,CAAC,EACxB,KAAK,EACL,YAAY,EACZ,SAAS,EACT,WAAW,EACX,UAAU,EACV,kBAAkB,GACH,EAAE,EAAE;IACnB,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC;IACpC,MAAM,oBAAoB,GAAG,uBAAuB,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;IACrG,MAAM,oBAAoB,GAAG,uBAAuB,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;IAErG,OAAO,CACL,qCAA0B,eAAe,WAAW,EAAE,YACpD,KAAC,IAAI,IAAC,SAAS,EAAC,YAAY,gBAAa,GAAG,KAAK,gBAAgB,YAC/D,KAAC,IAAI,CAAC,IAAI,IAAC,SAAS,EAAC,KAAK,YACxB,eAAK,SAAS,EAAC,4DAA4D,aACzE,0BACE,aAAI,SAAS,EAAC,MAAM,YAAE,KAAK,GAAM,EAEjC,eAAK,SAAS,EAAC,cAAc,aAC3B,eAAK,SAAS,EAAC,SAAS,aACtB,aAAG,SAAS,EAAC,iDAAiD,aAAE,aAAa,CAAC,QAAQ,CAAC,mBAAmB,CAAC,SAAM,EACjH,aAAG,SAAS,EAAC,gDAAgD,aAAE,aAAa,CAAC,QAAQ,CAAC,cAAc,CAAC,SAAM,EAC3G,aAAG,SAAS,EAAC,gDAAgD,aAAE,aAAa,CAAC,QAAQ,CAAC,gBAAgB,CAAC,SAAM,IACzG,EAEN,eAAK,SAAS,EAAC,SAAS,aACtB,YAAG,SAAS,EAAC,MAAM,YAAE,YAAY,GAAK,EACtC,YAAG,SAAS,EAAC,MAAM,YAAE,SAAS,GAAK,EACnC,YAAG,SAAS,EAAC,MAAM,YAAE,WAAW,GAAK,IACjC,IACF,IACF,EAEN,eAAK,SAAS,EAAC,iDAAiD,aAC9D,MAAC,MAAM,IACL,OAAO,EAAC,MAAM,EACd,IAAI,EAAC,IAAI,EACT,EAAE,EAAC,GAAG,EACN,IAAI,EAAE,UAAU,aAAV,UAAU,cAAV,UAAU,GAAI,SAAS,EAC7B,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,qBAAqB,EACzB,QAAQ,EAAE,CAAC,UAAU,EACrB,SAAS,EAAC,yCAAyC,sBACjC,oBAAoB,gBAC1B,0BAA0B,WAAW,EAAE,aAElD,aAAa,CAAC,QAAQ,CAAC,iBAAiB,CAAC,OAAE,yBAAM,KAAC,IAAI,IAAC,IAAI,EAAC,IAAI,EAAC,GAAG,EAAE,MAAM,wBAAgB,GAAO,EACpG,gBAAM,EAAE,EAAE,oBAAoB,EAAE,SAAS,EAAC,SAAS,aAChD,GAAG,UAAM,KAAK,IACV,IACA,EAET,MAAC,MAAM,IACL,OAAO,EAAC,MAAM,EACd,IAAI,EAAC,IAAI,EACT,OAAO,EAAE,kBAAkB,EAC3B,SAAS,EAAC,4BAA4B,sBACpB,oBAAoB,gBAC1B,0BAA0B,WAAW,EAAE,aAElD,aAAa,CAAC,QAAQ,CAAC,sBAAsB,CAAC,EAC/C,gBAAM,EAAE,EAAE,oBAAoB,EAAE,SAAS,EAAC,SAAS,aAChD,GAAG,UAAM,KAAK,IACV,IACA,IACL,IACF,GACI,GACP,GACC,CACX,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,gBAAgB,CAAC","sourcesContent":["import { Card, Button, Icon } from '@openedx/paragon';\nimport { useIntl } from 'react-intl';\nimport { Launch } from '@openedx/paragon/icons';\nimport messages from './messages';\n\ninterface OrderCardProps {\n title: string,\n purchaseDate: string,\n totalCost: string,\n orderNumber: string,\n receiptUrl?: string | null,\n onViewOrderDetails: () => void,\n}\n\nconst OrderHistoryCard = ({\n title,\n purchaseDate,\n totalCost,\n orderNumber,\n receiptUrl,\n onViewOrderDetails,\n}: OrderCardProps) => {\n const { formatMessage } = useIntl();\n const receiptDescriptionId = `receipt-description-${orderNumber.replace(/\\s+/g, '-').toLowerCase()}`;\n const detailsDescriptionId = `details-description-${orderNumber.replace(/\\s+/g, '-').toLowerCase()}`;\n\n return (\n <section aria-labelledby={`order-title-${orderNumber}`}>\n <Card className=\"order-card\" aria-label={`${title} order details`}>\n <Card.Body className=\"p-3\">\n <div className=\"d-flex justify-content-between align-items-start flex-wrap\">\n <div>\n <h6 className=\"mb-2\">{title}</h6>\n\n <div className=\"d-flex gap-1\">\n <div className=\"x-small\">\n <p className=\"text-muted orderHistoryCard__details mr1-1 mb-0\">{formatMessage(messages.dateOfPurchaseLabel)}:</p>\n <p className=\"text-muted mr-1 orderHistoryCard__details mb-0\">{formatMessage(messages.totalCostLabel)}:</p>\n <p className=\"text-muted mr-1 orderHistoryCard__details mb-0\">{formatMessage(messages.orderNumberLabel)}:</p>\n </div>\n\n <div className=\"x-small\">\n <p className=\"mb-0\">{purchaseDate}</p>\n <p className=\"mb-0\">{totalCost}</p>\n <p className=\"mb-0\">{orderNumber}</p>\n </div>\n </div>\n </div>\n\n <div className=\"d-flex align-items-center gap-3 mt-2 mt-md-auto\">\n <Button\n variant=\"link\"\n size=\"sm\"\n as=\"a\"\n href={receiptUrl ?? undefined}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n disabled={!receiptUrl}\n className=\"d-flex gap-1 p-0 orderHistoryCard__link\"\n aria-describedby={receiptDescriptionId}\n aria-label={`View receipt for order ${orderNumber}`}\n >\n {formatMessage(messages.viewReceiptButton)} <span><Icon size=\"xs\" src={Launch} aria-hidden /></span>\n <span id={receiptDescriptionId} className=\"sr-only\">\n {' '}for {title}\n </span>\n </Button>\n\n <Button\n variant=\"link\"\n size=\"sm\"\n onClick={onViewOrderDetails}\n className=\"p-0 orderHistoryCard__link\"\n aria-describedby={detailsDescriptionId}\n aria-label={`View details for order ${orderNumber}`}\n >\n {formatMessage(messages.viewOrderDetailsButton)}\n <span id={detailsDescriptionId} className=\"sr-only\">\n {' '}for {title}\n </span>\n </Button>\n </div>\n </div>\n </Card.Body>\n </Card>\n </section>\n );\n};\n\nexport default OrderHistoryCard;\n"]}
@@ -1,3 +1,3 @@
1
1
  import type { OrdersListProps } from '../../types';
2
- declare const OrdersList: ({ orders, onViewReceipt }: OrdersListProps) => import("react/jsx-runtime").JSX.Element;
2
+ declare const OrdersList: ({ orders, receiptUrls }: OrdersListProps) => import("react/jsx-runtime").JSX.Element;
3
3
  export default OrdersList;
@@ -3,9 +3,9 @@ import { useNavigate } from 'react-router-dom';
3
3
  import getFormattedCurrency from '../../utils/currency';
4
4
  import { ORDER_DETAILS_PATH } from '../../constants';
5
5
  import OrderHistoryCard from './OrderHistoryCard';
6
- const OrdersList = ({ orders, onViewReceipt }) => {
6
+ const OrdersList = ({ orders, receiptUrls = {} }) => {
7
7
  const navigate = useNavigate();
8
- return (_jsx("ul", { className: "list-unstyled mb-0", role: "list", children: orders.map((order) => (_jsx("li", { className: "mb-3", role: "listitem", children: _jsx(OrderHistoryCard, { title: order.name, purchaseDate: new Date(order.purchasedAt).toLocaleDateString('en-US'), totalCost: getFormattedCurrency(order.total), orderNumber: order.orderNumber, isReceiptDisabled: false, onViewReceipt: () => onViewReceipt === null || onViewReceipt === void 0 ? void 0 : onViewReceipt(order), onViewOrderDetails: () => navigate(`${ORDER_DETAILS_PATH}/${encodeURIComponent(order.orderNumber)}`) }) }, order.orderId))) }));
8
+ return (_jsx("ul", { className: "list-unstyled mb-0", role: "list", children: orders.map((order) => (_jsx("li", { className: "mb-3", role: "listitem", children: _jsx(OrderHistoryCard, { title: order.name, purchaseDate: new Date(order.purchasedAt).toLocaleDateString('en-US'), totalCost: getFormattedCurrency(order.total), orderNumber: order.orderNumber, receiptUrl: receiptUrls[order.orderId], onViewOrderDetails: () => navigate(`${ORDER_DETAILS_PATH}/${encodeURIComponent(order.orderNumber)}`) }) }, order.orderId))) }));
9
9
  };
10
10
  export default OrdersList;
11
11
  //# sourceMappingURL=OrderList.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"OrderList.js","sourceRoot":"","sources":["../../../src/components/OrderHistory/OrderList.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,oBAAoB,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,gBAAgB,MAAM,oBAAoB,CAAC;AAElD,MAAM,UAAU,GAAG,CAAC,EAAE,MAAM,EAAE,aAAa,EAAmB,EAAE,EAAE;IAChE,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAE/B,OAAO,CACL,aAAI,SAAS,EAAC,oBAAoB,EAAC,IAAI,EAAC,MAAM,YAC3C,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CACrB,aAAwB,SAAS,EAAC,MAAM,EAAC,IAAI,EAAC,UAAU,YACtD,KAAC,gBAAgB,IACf,KAAK,EAAE,KAAK,CAAC,IAAI,EACjB,YAAY,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,EACrE,SAAS,EAAE,oBAAoB,CAAC,KAAK,CAAC,KAAK,CAAC,EAC5C,WAAW,EAAE,KAAK,CAAC,WAAW,EAC9B,iBAAiB,EAAE,KAAK,EACxB,aAAa,EAAE,GAAG,EAAE,CAAC,aAAa,aAAb,aAAa,uBAAb,aAAa,CAAG,KAAK,CAAC,EAC3C,kBAAkB,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,kBAAkB,IAAI,kBAAkB,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,GACpG,IATK,KAAK,CAAC,OAAO,CAUjB,CACN,CAAC,GACC,CACN,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,UAAU,CAAC","sourcesContent":["import { useNavigate } from 'react-router-dom';\n\nimport getFormattedCurrency from '../../utils/currency';\nimport type { OrdersListProps } from '../../types';\nimport { ORDER_DETAILS_PATH } from '../../constants';\nimport OrderHistoryCard from './OrderHistoryCard';\n\nconst OrdersList = ({ orders, onViewReceipt }: OrdersListProps) => {\n const navigate = useNavigate();\n\n return (\n <ul className=\"list-unstyled mb-0\" role=\"list\">\n {orders.map((order) => (\n <li key={order.orderId} className=\"mb-3\" role=\"listitem\">\n <OrderHistoryCard\n title={order.name}\n purchaseDate={new Date(order.purchasedAt).toLocaleDateString('en-US')}\n totalCost={getFormattedCurrency(order.total)}\n orderNumber={order.orderNumber}\n isReceiptDisabled={false}\n onViewReceipt={() => onViewReceipt?.(order)}\n onViewOrderDetails={() => navigate(`${ORDER_DETAILS_PATH}/${encodeURIComponent(order.orderNumber)}`)}\n />\n </li>\n ))}\n </ul>\n );\n};\n\nexport default OrdersList;\n"]}
1
+ {"version":3,"file":"OrderList.js","sourceRoot":"","sources":["../../../src/components/OrderHistory/OrderList.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,oBAAoB,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,gBAAgB,MAAM,oBAAoB,CAAC;AAElD,MAAM,UAAU,GAAG,CAAC,EAAE,MAAM,EAAE,WAAW,GAAG,EAAE,EAAmB,EAAE,EAAE;IACnE,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAE/B,OAAO,CACL,aAAI,SAAS,EAAC,oBAAoB,EAAC,IAAI,EAAC,MAAM,YAC3C,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CACrB,aAAwB,SAAS,EAAC,MAAM,EAAC,IAAI,EAAC,UAAU,YACtD,KAAC,gBAAgB,IACf,KAAK,EAAE,KAAK,CAAC,IAAI,EACjB,YAAY,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,EACrE,SAAS,EAAE,oBAAoB,CAAC,KAAK,CAAC,KAAK,CAAC,EAC5C,WAAW,EAAE,KAAK,CAAC,WAAW,EAC9B,UAAU,EAAE,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,EACtC,kBAAkB,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,kBAAkB,IAAI,kBAAkB,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,GACpG,IARK,KAAK,CAAC,OAAO,CASjB,CACN,CAAC,GACC,CACN,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,UAAU,CAAC","sourcesContent":["import { useNavigate } from 'react-router-dom';\n\nimport getFormattedCurrency from '../../utils/currency';\nimport type { OrdersListProps } from '../../types';\nimport { ORDER_DETAILS_PATH } from '../../constants';\nimport OrderHistoryCard from './OrderHistoryCard';\n\nconst OrdersList = ({ orders, receiptUrls = {} }: OrdersListProps) => {\n const navigate = useNavigate();\n\n return (\n <ul className=\"list-unstyled mb-0\" role=\"list\">\n {orders.map((order) => (\n <li key={order.orderId} className=\"mb-3\" role=\"listitem\">\n <OrderHistoryCard\n title={order.name}\n purchaseDate={new Date(order.purchasedAt).toLocaleDateString('en-US')}\n totalCost={getFormattedCurrency(order.total)}\n orderNumber={order.orderNumber}\n receiptUrl={receiptUrls[order.orderId]}\n onViewOrderDetails={() => navigate(`${ORDER_DETAILS_PATH}/${encodeURIComponent(order.orderNumber)}`)}\n />\n </li>\n ))}\n </ul>\n );\n};\n\nexport default OrdersList;\n"]}
@@ -1,18 +1,8 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
11
2
  import { Alert, Spinner } from '@openedx/paragon';
12
3
  import { getAppConfig, useIntl } from '@openedx/frontend-base';
13
4
  import { appId } from '../../constants';
14
- import { getStripePaymentReceipt } from '../../data/services/orderHistory/orderHistory';
15
- import { usePurchaseHistoryQuery } from '../../data/hooks/useOrderHistoryQueries';
5
+ import { isStripeReceiptOrder, usePurchaseHistoryQuery, useStripeReceiptUrls } from '../../data/hooks/useOrderHistoryQueries';
16
6
  import { useViaxClient, useViaxSession } from '../../data/hooks/useManageQueries';
17
7
  import OrdersList from './OrderList';
18
8
  import RefundNotice from '../RefundNotice/RefundNotice';
@@ -33,35 +23,14 @@ const OrderPurchases = () => {
33
23
  const { sessionReady } = useViaxSession(client);
34
24
  const purchaseHistoryQuery = usePurchaseHistoryQuery(client, sessionReady);
35
25
  const orders = (_a = purchaseHistoryQuery.data) !== null && _a !== void 0 ? _a : [];
36
- const handleViewReceipt = (order) => __awaiter(void 0, void 0, void 0, function* () {
37
- var _a, _b, _c;
38
- if (!client || !order.orderId) {
39
- return;
40
- }
41
- try {
42
- const paymentMethodType = ((_b = (_a = order.paymentMethod) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : '').toLowerCase();
43
- const isNotAppleOrGooglePay = !((_c = order.paymentMethod) === null || _c === void 0 ? void 0 : _c.wallet);
44
- if (paymentMethodType === 'paypal') {
45
- const paypalReceiptUrl = getPaypalReceiptUrl();
46
- if (!paypalReceiptUrl) {
47
- console.error('PayPal receipt URL is not configured.');
48
- return;
49
- }
50
- window.open(paypalReceiptUrl, '_blank', 'noopener,noreferrer');
51
- return;
52
- }
53
- else if (paymentMethodType === 'card' && isNotAppleOrGooglePay) {
54
- const receiptUrl = yield getStripePaymentReceipt(client.gql, order.orderId);
55
- if (receiptUrl) {
56
- window.open(receiptUrl, '_blank', 'noopener,noreferrer');
57
- }
58
- }
59
- }
60
- catch (error) {
61
- console.error('Unable to load payment receipt.', error);
62
- }
63
- });
64
- return (_jsxs("section", { className: "manage-section mt-5", "aria-labelledby": "order-purchases-title", "aria-live": "polite", "aria-busy": purchaseHistoryQuery.isLoading || purchaseHistoryQuery.isFetching, children: [_jsx("h2", { id: "order-purchases-title", className: "manage-section__title h3 font-weight-bold text-primary-500 mb-1", children: formatMessage(messages.otherPurchasesTitle) }), purchaseHistoryQuery.isError && (_jsx(Alert, { variant: "danger", children: formatMessage(messages.purchaseHistoryError) })), !purchaseHistoryQuery.isError && !purchaseHistoryQuery.isSuccess && (_jsx("div", { className: "d-flex justify-content-center py-4", children: _jsx(Spinner, { animation: "border", screenReaderText: formatMessage(messages.loadingOrders) }) })), purchaseHistoryQuery.isSuccess && orders.length === 0 && (_jsx("p", { className: "manage-section__subtitle text-gray-700 mb-3", children: formatMessage(messages.coursePurchasesMessage) })), purchaseHistoryQuery.isSuccess && orders.length > 0 && (_jsxs(_Fragment, { children: [_jsx("p", { className: "manage-section__subtitle text-gray-700 mb-3", children: formatMessage(messages.coursePurchasesMessage) }), _jsx(OrdersList, { orders: orders, onViewReceipt: handleViewReceipt }), _jsx(RefundNotice, {})] }))] }));
26
+ const stripeReceiptUrls = useStripeReceiptUrls(client, orders, sessionReady);
27
+ const receiptUrls = orders.reduce((urls, order) => {
28
+ var _a, _b;
29
+ const isPaypal = ((_b = (_a = order.paymentMethod) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : '').toLowerCase() === 'paypal';
30
+ urls[order.orderId] = isPaypal ? getPaypalReceiptUrl() : (isStripeReceiptOrder(order) ? stripeReceiptUrls[order.orderId] : null);
31
+ return urls;
32
+ }, {});
33
+ return (_jsxs("section", { className: "manage-section mt-5", "aria-labelledby": "order-purchases-title", "aria-live": "polite", "aria-busy": purchaseHistoryQuery.isLoading || purchaseHistoryQuery.isFetching, children: [_jsx("h2", { id: "order-purchases-title", className: "manage-section__title h3 font-weight-bold text-primary-500 mb-1", children: formatMessage(messages.otherPurchasesTitle) }), purchaseHistoryQuery.isError && (_jsx(Alert, { variant: "danger", children: formatMessage(messages.purchaseHistoryError) })), !purchaseHistoryQuery.isError && !purchaseHistoryQuery.isSuccess && (_jsx("div", { className: "d-flex justify-content-center py-4", children: _jsx(Spinner, { animation: "border", screenReaderText: formatMessage(messages.loadingOrders) }) })), purchaseHistoryQuery.isSuccess && orders.length === 0 && (_jsx("p", { className: "manage-section__subtitle text-gray-700 mb-3", children: formatMessage(messages.coursePurchasesMessage) })), purchaseHistoryQuery.isSuccess && orders.length > 0 && (_jsxs(_Fragment, { children: [_jsx("p", { className: "manage-section__subtitle text-gray-700 mb-3", children: formatMessage(messages.coursePurchasesMessage) }), _jsx(OrdersList, { orders: orders, receiptUrls: receiptUrls }), _jsx(RefundNotice, {})] }))] }));
65
34
  };
66
35
  export default OrderPurchases;
67
36
  //# sourceMappingURL=OrderPurchases.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"OrderPurchases.js","sourceRoot":"","sources":["../../../src/components/OrderHistory/OrderPurchases.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport { Alert, Spinner } from '@openedx/paragon';\nimport { getAppConfig, useIntl } from '@openedx/frontend-base';\n\nimport type { PurchaseHistoryItem } from '../../types';\nimport { appId } from '../../constants';\nimport { getStripePaymentReceipt } from '../../data/services/orderHistory/orderHistory';\nimport { usePurchaseHistoryQuery } from '../../data/hooks/useOrderHistoryQueries';\nimport { useViaxClient, useViaxSession } from '../../data/hooks/useManageQueries';\nimport OrdersList from './OrderList';\nimport RefundNotice from '../RefundNotice/RefundNotice';\nimport messages from './messages';\n\nconst getPaypalReceiptUrl = (): string | null => {\n const config = getAppConfig(appId) as { PAYPAL_RECEIPT_URL?: string };\n const paypalReceiptUrl = config.PAYPAL_RECEIPT_URL;\n\n if (typeof paypalReceiptUrl !== 'string') {\n return null;\n }\n\n return paypalReceiptUrl.trim() || null;\n};\n\n/** One-off course and program purchases, shown in the payment history tab. */\nconst OrderPurchases: React.FC = () => {\n const { formatMessage } = useIntl();\n const client = useViaxClient();\n const { sessionReady } = useViaxSession(client);\n const purchaseHistoryQuery = usePurchaseHistoryQuery(client, sessionReady);\n const orders = purchaseHistoryQuery.data ?? [];\n\n const handleViewReceipt = async (order: PurchaseHistoryItem) => {\n if (!client || !order.orderId) {\n return;\n }\n\n try {\n const paymentMethodType = (order.paymentMethod?.type ?? '').toLowerCase();\n const isNotAppleOrGooglePay = !order.paymentMethod?.wallet;\n\n if (paymentMethodType === 'paypal') {\n const paypalReceiptUrl = getPaypalReceiptUrl();\n if (!paypalReceiptUrl) {\n console.error('PayPal receipt URL is not configured.');\n return;\n }\n\n window.open(paypalReceiptUrl, '_blank', 'noopener,noreferrer');\n return;\n } else if (paymentMethodType === 'card' && isNotAppleOrGooglePay) {\n const receiptUrl = await getStripePaymentReceipt(client.gql, order.orderId);\n if (receiptUrl) {\n window.open(receiptUrl, '_blank', 'noopener,noreferrer');\n }\n }\n } catch (error) {\n console.error('Unable to load payment receipt.', error);\n }\n };\n\n return (\n <section\n className=\"manage-section mt-5\"\n aria-labelledby=\"order-purchases-title\"\n aria-live=\"polite\"\n aria-busy={purchaseHistoryQuery.isLoading || purchaseHistoryQuery.isFetching}\n >\n <h2 id=\"order-purchases-title\" className=\"manage-section__title h3 font-weight-bold text-primary-500 mb-1\">\n {formatMessage(messages.otherPurchasesTitle)}\n </h2>\n\n {purchaseHistoryQuery.isError && (\n <Alert variant=\"danger\">{formatMessage(messages.purchaseHistoryError)}</Alert>\n )}\n\n {!purchaseHistoryQuery.isError && !purchaseHistoryQuery.isSuccess && (\n <div className=\"d-flex justify-content-center py-4\">\n <Spinner animation=\"border\" screenReaderText={formatMessage(messages.loadingOrders)} />\n </div>\n )}\n\n {purchaseHistoryQuery.isSuccess && orders.length === 0 && (\n <p className=\"manage-section__subtitle text-gray-700 mb-3\">\n {formatMessage(messages.coursePurchasesMessage)}\n </p>\n )}\n\n {purchaseHistoryQuery.isSuccess && orders.length > 0 && (\n <>\n <p className=\"manage-section__subtitle text-gray-700 mb-3\">\n {formatMessage(messages.coursePurchasesMessage)}\n </p>\n <OrdersList orders={orders} onViewReceipt={handleViewReceipt} />\n <RefundNotice />\n </>\n )}\n </section>\n );\n};\n\nexport default OrderPurchases;\n"]}
1
+ {"version":3,"file":"OrderPurchases.js","sourceRoot":"","sources":["../../../src/components/OrderHistory/OrderPurchases.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport { Alert, Spinner } from '@openedx/paragon';\nimport { getAppConfig, useIntl } from '@openedx/frontend-base';\n\nimport { appId } from '../../constants';\nimport { isStripeReceiptOrder, usePurchaseHistoryQuery, useStripeReceiptUrls } from '../../data/hooks/useOrderHistoryQueries';\nimport { useViaxClient, useViaxSession } from '../../data/hooks/useManageQueries';\nimport OrdersList from './OrderList';\nimport RefundNotice from '../RefundNotice/RefundNotice';\nimport messages from './messages';\n\nconst getPaypalReceiptUrl = (): string | null => {\n const config = getAppConfig(appId) as { PAYPAL_RECEIPT_URL?: string };\n const paypalReceiptUrl = config.PAYPAL_RECEIPT_URL;\n\n if (typeof paypalReceiptUrl !== 'string') {\n return null;\n }\n\n return paypalReceiptUrl.trim() || null;\n};\n\n/** One-off course and program purchases, shown in the payment history tab. */\nconst OrderPurchases: React.FC = () => {\n const { formatMessage } = useIntl();\n const client = useViaxClient();\n const { sessionReady } = useViaxSession(client);\n const purchaseHistoryQuery = usePurchaseHistoryQuery(client, sessionReady);\n const orders = purchaseHistoryQuery.data ?? [];\n const stripeReceiptUrls = useStripeReceiptUrls(client, orders, sessionReady);\n\n const receiptUrls = orders.reduce<Record<string, string | null>>((urls, order) => {\n const isPaypal = (order.paymentMethod?.type ?? '').toLowerCase() === 'paypal';\n urls[order.orderId] = isPaypal ? getPaypalReceiptUrl() : (isStripeReceiptOrder(order) ? stripeReceiptUrls[order.orderId] : null);\n return urls;\n }, {});\n\n return (\n <section\n className=\"manage-section mt-5\"\n aria-labelledby=\"order-purchases-title\"\n aria-live=\"polite\"\n aria-busy={purchaseHistoryQuery.isLoading || purchaseHistoryQuery.isFetching}\n >\n <h2 id=\"order-purchases-title\" className=\"manage-section__title h3 font-weight-bold text-primary-500 mb-1\">\n {formatMessage(messages.otherPurchasesTitle)}\n </h2>\n\n {purchaseHistoryQuery.isError && (\n <Alert variant=\"danger\">{formatMessage(messages.purchaseHistoryError)}</Alert>\n )}\n\n {!purchaseHistoryQuery.isError && !purchaseHistoryQuery.isSuccess && (\n <div className=\"d-flex justify-content-center py-4\">\n <Spinner animation=\"border\" screenReaderText={formatMessage(messages.loadingOrders)} />\n </div>\n )}\n\n {purchaseHistoryQuery.isSuccess && orders.length === 0 && (\n <p className=\"manage-section__subtitle text-gray-700 mb-3\">\n {formatMessage(messages.coursePurchasesMessage)}\n </p>\n )}\n\n {purchaseHistoryQuery.isSuccess && orders.length > 0 && (\n <>\n <p className=\"manage-section__subtitle text-gray-700 mb-3\">\n {formatMessage(messages.coursePurchasesMessage)}\n </p>\n <OrdersList orders={orders} receiptUrls={receiptUrls} />\n <RefundNotice />\n </>\n )}\n </section>\n );\n};\n\nexport default OrderPurchases;\n"]}
@@ -11,4 +11,5 @@ export declare const orderHistoryKeys: {
11
11
  all: readonly ["orderHistory"];
12
12
  purchaseHistory: () => readonly ["orderHistory", "purchaseHistory"];
13
13
  orderDetails: (orderNumber: string) => readonly ["orderHistory", "orderDetails", string];
14
+ stripeReceipt: (orderId: string) => readonly ["orderHistory", "stripeReceipt", string];
14
15
  };
@@ -11,5 +11,6 @@ export const orderHistoryKeys = {
11
11
  all: ['orderHistory'],
12
12
  purchaseHistory: () => [...orderHistoryKeys.all, 'purchaseHistory'],
13
13
  orderDetails: (orderNumber) => [...orderHistoryKeys.all, 'orderDetails', orderNumber],
14
+ stripeReceipt: (orderId) => [...orderHistoryKeys.all, 'stripeReceipt', orderId],
14
15
  };
15
16
  //# sourceMappingURL=keys.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"keys.js","sourceRoot":"","sources":["../../../src/data/hooks/keys.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,GAAG,EAAE,CAAC,QAAQ,CAAU;IACxB,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,aAAa,CAAU;IAC9D,YAAY,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,yBAAyB,CAAU;IAC3E,YAAY,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,cAAc,CAAU;IAChE,WAAW,EAAE,CAAC,gBAAwB,EAAE,EAAE,CACxC,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,aAAa,EAAE,gBAAgB,CACpD;IACD,cAAc,EAAE,CAAC,gBAAwB,EAAE,EAAE,CAC3C,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,gBAAgB,EAAE,gBAAgB,CACvD;IACD,aAAa,EAAE,CAAC,gBAAwB,EAAE,EAAE,CAC1C,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,eAAe,EAAE,gBAAgB,CACtD;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,GAAG,EAAE,CAAC,cAAc,CAAU;IAC9B,eAAe,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,gBAAgB,CAAC,GAAG,EAAE,iBAAiB,CAAU;IAC5E,YAAY,EAAE,CAAC,WAAmB,EAAE,EAAE,CAAC,CAAC,GAAG,gBAAgB,CAAC,GAAG,EAAE,cAAc,EAAE,WAAW,CAAU;CACvG,CAAC","sourcesContent":["export const manageKeys = {\n all: ['manage'] as const,\n viaxSession: () => [...manageKeys.all, 'viaxSession'] as const,\n isSubscriber: () => [...manageKeys.all, 'isCurrentUserSubscriber'] as const,\n billingPlans: () => [...manageKeys.all, 'billingPlans'] as const,\n enrollments: (subscriptionBiId: string) => (\n [...manageKeys.all, 'enrollments', subscriptionBiId] as const\n ),\n paymentHistory: (subscriptionBiId: string) => (\n [...manageKeys.all, 'paymentHistory', subscriptionBiId] as const\n ),\n paymentMethod: (subscriptionBiId: string) => (\n [...manageKeys.all, 'paymentMethod', subscriptionBiId] as const\n ),\n};\n\nexport const orderHistoryKeys = {\n all: ['orderHistory'] as const,\n purchaseHistory: () => [...orderHistoryKeys.all, 'purchaseHistory'] as const,\n orderDetails: (orderNumber: string) => [...orderHistoryKeys.all, 'orderDetails', orderNumber] as const,\n};\n"]}
1
+ {"version":3,"file":"keys.js","sourceRoot":"","sources":["../../../src/data/hooks/keys.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,GAAG,EAAE,CAAC,QAAQ,CAAU;IACxB,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,aAAa,CAAU;IAC9D,YAAY,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,yBAAyB,CAAU;IAC3E,YAAY,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,cAAc,CAAU;IAChE,WAAW,EAAE,CAAC,gBAAwB,EAAE,EAAE,CACxC,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,aAAa,EAAE,gBAAgB,CACpD;IACD,cAAc,EAAE,CAAC,gBAAwB,EAAE,EAAE,CAC3C,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,gBAAgB,EAAE,gBAAgB,CACvD;IACD,aAAa,EAAE,CAAC,gBAAwB,EAAE,EAAE,CAC1C,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,eAAe,EAAE,gBAAgB,CACtD;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,GAAG,EAAE,CAAC,cAAc,CAAU;IAC9B,eAAe,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,gBAAgB,CAAC,GAAG,EAAE,iBAAiB,CAAU;IAC5E,YAAY,EAAE,CAAC,WAAmB,EAAE,EAAE,CAAC,CAAC,GAAG,gBAAgB,CAAC,GAAG,EAAE,cAAc,EAAE,WAAW,CAAU;IACtG,aAAa,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,CAAC,GAAG,gBAAgB,CAAC,GAAG,EAAE,eAAe,EAAE,OAAO,CAAU;CACjG,CAAC","sourcesContent":["export const manageKeys = {\n all: ['manage'] as const,\n viaxSession: () => [...manageKeys.all, 'viaxSession'] as const,\n isSubscriber: () => [...manageKeys.all, 'isCurrentUserSubscriber'] as const,\n billingPlans: () => [...manageKeys.all, 'billingPlans'] as const,\n enrollments: (subscriptionBiId: string) => (\n [...manageKeys.all, 'enrollments', subscriptionBiId] as const\n ),\n paymentHistory: (subscriptionBiId: string) => (\n [...manageKeys.all, 'paymentHistory', subscriptionBiId] as const\n ),\n paymentMethod: (subscriptionBiId: string) => (\n [...manageKeys.all, 'paymentMethod', subscriptionBiId] as const\n ),\n};\n\nexport const orderHistoryKeys = {\n all: ['orderHistory'] as const,\n purchaseHistory: () => [...orderHistoryKeys.all, 'purchaseHistory'] as const,\n orderDetails: (orderNumber: string) => [...orderHistoryKeys.all, 'orderDetails', orderNumber] as const,\n stripeReceipt: (orderId: string) => [...orderHistoryKeys.all, 'stripeReceipt', orderId] as const,\n};\n"]}
@@ -5,6 +5,10 @@
5
5
  import { type UseQueryResult } from '@tanstack/react-query';
6
6
  import type { PurchaseHistoryItem } from '../../types';
7
7
  import type { ViaxGqlClient } from '../../utils/graphqlClient';
8
+ /** Card payments that are not Apple/Google Pay have a Stripe receipt to look up. */
9
+ export declare const isStripeReceiptOrder: (order: PurchaseHistoryItem) => boolean;
10
+ /** Stripe receipt URLs keyed by orderId; only fetched for orders that need one. */
11
+ export declare function useStripeReceiptUrls(client: ViaxGqlClient | null, orders: PurchaseHistoryItem[], sessionReady: boolean): Record<string, string | null>;
8
12
  /** Learner's one-off course and program purchases. */
9
13
  export declare function usePurchaseHistoryQuery(client: ViaxGqlClient | null, sessionReady: boolean): UseQueryResult<PurchaseHistoryItem[]>;
10
14
  /** A single order's detailed payload for the order details page. */
@@ -2,9 +2,34 @@
2
2
  * Hooks for the order history page. Viax client and session come from
3
3
  * useManageQueries (useViaxClient / useViaxSession).
4
4
  */
5
- import { useQuery } from '@tanstack/react-query';
6
- import { getOrderDetails, getPurchaseHistory } from '../services/orderHistory/orderHistory';
5
+ import { useQueries, useQuery } from '@tanstack/react-query';
6
+ import { getOrderDetails, getPurchaseHistory, getStripePaymentReceipt } from '../services/orderHistory/orderHistory';
7
7
  import { orderHistoryKeys } from './keys';
8
+ /** Card payments that are not Apple/Google Pay have a Stripe receipt to look up. */
9
+ export const isStripeReceiptOrder = (order) => {
10
+ var _a, _b, _c;
11
+ return (!!order.orderId
12
+ && ((_b = (_a = order.paymentMethod) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : '').toLowerCase() === 'card'
13
+ && !((_c = order.paymentMethod) === null || _c === void 0 ? void 0 : _c.wallet));
14
+ };
15
+ /** Stripe receipt URLs keyed by orderId; only fetched for orders that need one. */
16
+ export function useStripeReceiptUrls(client, orders, sessionReady) {
17
+ const results = useQueries({
18
+ queries: orders.map((order) => ({
19
+ queryKey: orderHistoryKeys.stripeReceipt(order.orderId),
20
+ queryFn: () => getStripePaymentReceipt(client.gql, order.orderId),
21
+ enabled: !!client && sessionReady && isStripeReceiptOrder(order),
22
+ staleTime: 5 * 60 * 1000,
23
+ refetchOnWindowFocus: false,
24
+ retry: 1,
25
+ })),
26
+ });
27
+ return orders.reduce((urls, order, index) => {
28
+ var _a, _b;
29
+ urls[order.orderId] = (_b = (_a = results[index]) === null || _a === void 0 ? void 0 : _a.data) !== null && _b !== void 0 ? _b : null;
30
+ return urls;
31
+ }, {});
32
+ }
8
33
  /** Learner's one-off course and program purchases. */
9
34
  export function usePurchaseHistoryQuery(client, sessionReady) {
10
35
  return useQuery({
@@ -1 +1 @@
1
- {"version":3,"file":"useOrderHistoryQueries.js","sourceRoot":"","sources":["../../../src/data/hooks/useOrderHistoryQueries.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAuB,MAAM,uBAAuB,CAAC;AAItE,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAC5F,OAAO,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAE1C,sDAAsD;AACtD,MAAM,UAAU,uBAAuB,CACrC,MAA4B,EAC5B,YAAqB;IAErB,OAAO,QAAQ,CAAC;QACd,QAAQ,EAAE,gBAAgB,CAAC,eAAe,EAAE;QAC5C,OAAO,EAAE,CAAC,CAAC,MAAM,IAAI,YAAY;QACjC,OAAO,EAAE,GAAG,EAAE,CAAC,kBAAkB,CAAC,MAAO,CAAC,GAAG,CAAC;QAC9C,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI;QACxB,oBAAoB,EAAE,KAAK;QAC3B,KAAK,EAAE,CAAC;KACT,CAAC,CAAC;AACL,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,oBAAoB,CAClC,MAA4B,EAC5B,WAA0B,EAC1B,YAAqB;IAErB,OAAO,QAAQ,CAAC;QACd,QAAQ,EAAE,gBAAgB,CAAC,YAAY,CAAC,WAAW,aAAX,WAAW,cAAX,WAAW,GAAI,MAAM,CAAC;QAC9D,OAAO,EAAE,CAAC,CAAC,MAAM,IAAI,YAAY,IAAI,CAAC,CAAC,WAAW;QAClD,OAAO,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,MAAO,CAAC,GAAG,EAAE,WAAY,CAAC;QACzD,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI;QACxB,oBAAoB,EAAE,KAAK;QAC3B,KAAK,EAAE,CAAC;KACT,CAAC,CAAC;AACL,CAAC","sourcesContent":["/**\n * Hooks for the order history page. Viax client and session come from\n * useManageQueries (useViaxClient / useViaxSession).\n */\n\nimport { useQuery, type UseQueryResult } from '@tanstack/react-query';\n\nimport type { PurchaseHistoryItem } from '../../types';\nimport type { ViaxGqlClient } from '../../utils/graphqlClient';\nimport { getOrderDetails, getPurchaseHistory } from '../services/orderHistory/orderHistory';\nimport { orderHistoryKeys } from './keys';\n\n/** Learner's one-off course and program purchases. */\nexport function usePurchaseHistoryQuery(\n client: ViaxGqlClient | null,\n sessionReady: boolean,\n): UseQueryResult<PurchaseHistoryItem[]> {\n return useQuery({\n queryKey: orderHistoryKeys.purchaseHistory(),\n enabled: !!client && sessionReady,\n queryFn: () => getPurchaseHistory(client!.gql),\n staleTime: 5 * 60 * 1000,\n refetchOnWindowFocus: false,\n retry: 1,\n });\n}\n\n/** A single order's detailed payload for the order details page. */\nexport function useOrderDetailsQuery(\n client: ViaxGqlClient | null,\n orderNumber: string | null,\n sessionReady: boolean,\n): UseQueryResult<unknown> {\n return useQuery({\n queryKey: orderHistoryKeys.orderDetails(orderNumber ?? 'none'),\n enabled: !!client && sessionReady && !!orderNumber,\n queryFn: () => getOrderDetails(client!.gql, orderNumber!),\n staleTime: 5 * 60 * 1000,\n refetchOnWindowFocus: false,\n retry: 1,\n });\n}\n"]}
1
+ {"version":3,"file":"useOrderHistoryQueries.js","sourceRoot":"","sources":["../../../src/data/hooks/useOrderHistoryQueries.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAuB,MAAM,uBAAuB,CAAC;AAIlF,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAC;AACrH,OAAO,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAE1C,oFAAoF;AACpF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,KAA0B,EAAW,EAAE;;IAAC,OAAA,CAC3E,CAAC,CAAC,KAAK,CAAC,OAAO;WACZ,CAAC,MAAA,MAAA,KAAK,CAAC,aAAa,0CAAE,IAAI,mCAAI,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM;WAC1D,CAAC,CAAA,MAAA,KAAK,CAAC,aAAa,0CAAE,MAAM,CAAA,CAChC,CAAA;CAAA,CAAC;AAEF,mFAAmF;AACnF,MAAM,UAAU,oBAAoB,CAClC,MAA4B,EAC5B,MAA6B,EAC7B,YAAqB;IAErB,MAAM,OAAO,GAAG,UAAU,CAAC;QACzB,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC9B,QAAQ,EAAE,gBAAgB,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC;YACvD,OAAO,EAAE,GAAG,EAAE,CAAC,uBAAuB,CAAC,MAAO,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC;YAClE,OAAO,EAAE,CAAC,CAAC,MAAM,IAAI,YAAY,IAAI,oBAAoB,CAAC,KAAK,CAAC;YAChE,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI;YACxB,oBAAoB,EAAE,KAAK;YAC3B,KAAK,EAAE,CAAC;SACT,CAAC,CAAC;KACJ,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,MAAM,CAAgC,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;;QACzE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,MAAA,MAAA,OAAO,CAAC,KAAK,CAAC,0CAAE,IAAI,mCAAI,IAAI,CAAC;QACnD,OAAO,IAAI,CAAC;IACd,CAAC,EAAE,EAAE,CAAC,CAAC;AACT,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,uBAAuB,CACrC,MAA4B,EAC5B,YAAqB;IAErB,OAAO,QAAQ,CAAC;QACd,QAAQ,EAAE,gBAAgB,CAAC,eAAe,EAAE;QAC5C,OAAO,EAAE,CAAC,CAAC,MAAM,IAAI,YAAY;QACjC,OAAO,EAAE,GAAG,EAAE,CAAC,kBAAkB,CAAC,MAAO,CAAC,GAAG,CAAC;QAC9C,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI;QACxB,oBAAoB,EAAE,KAAK;QAC3B,KAAK,EAAE,CAAC;KACT,CAAC,CAAC;AACL,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,oBAAoB,CAClC,MAA4B,EAC5B,WAA0B,EAC1B,YAAqB;IAErB,OAAO,QAAQ,CAAC;QACd,QAAQ,EAAE,gBAAgB,CAAC,YAAY,CAAC,WAAW,aAAX,WAAW,cAAX,WAAW,GAAI,MAAM,CAAC;QAC9D,OAAO,EAAE,CAAC,CAAC,MAAM,IAAI,YAAY,IAAI,CAAC,CAAC,WAAW;QAClD,OAAO,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,MAAO,CAAC,GAAG,EAAE,WAAY,CAAC;QACzD,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI;QACxB,oBAAoB,EAAE,KAAK;QAC3B,KAAK,EAAE,CAAC;KACT,CAAC,CAAC;AACL,CAAC","sourcesContent":["/**\n * Hooks for the order history page. Viax client and session come from\n * useManageQueries (useViaxClient / useViaxSession).\n */\n\nimport { useQueries, useQuery, type UseQueryResult } from '@tanstack/react-query';\n\nimport type { PurchaseHistoryItem } from '../../types';\nimport type { ViaxGqlClient } from '../../utils/graphqlClient';\nimport { getOrderDetails, getPurchaseHistory, getStripePaymentReceipt } from '../services/orderHistory/orderHistory';\nimport { orderHistoryKeys } from './keys';\n\n/** Card payments that are not Apple/Google Pay have a Stripe receipt to look up. */\nexport const isStripeReceiptOrder = (order: PurchaseHistoryItem): boolean => (\n !!order.orderId\n && (order.paymentMethod?.type ?? '').toLowerCase() === 'card'\n && !order.paymentMethod?.wallet\n);\n\n/** Stripe receipt URLs keyed by orderId; only fetched for orders that need one. */\nexport function useStripeReceiptUrls(\n client: ViaxGqlClient | null,\n orders: PurchaseHistoryItem[],\n sessionReady: boolean,\n): Record<string, string | null> {\n const results = useQueries({\n queries: orders.map((order) => ({\n queryKey: orderHistoryKeys.stripeReceipt(order.orderId),\n queryFn: () => getStripePaymentReceipt(client!.gql, order.orderId),\n enabled: !!client && sessionReady && isStripeReceiptOrder(order),\n staleTime: 5 * 60 * 1000,\n refetchOnWindowFocus: false,\n retry: 1,\n })),\n });\n\n return orders.reduce<Record<string, string | null>>((urls, order, index) => {\n urls[order.orderId] = results[index]?.data ?? null;\n return urls;\n }, {});\n}\n\n/** Learner's one-off course and program purchases. */\nexport function usePurchaseHistoryQuery(\n client: ViaxGqlClient | null,\n sessionReady: boolean,\n): UseQueryResult<PurchaseHistoryItem[]> {\n return useQuery({\n queryKey: orderHistoryKeys.purchaseHistory(),\n enabled: !!client && sessionReady,\n queryFn: () => getPurchaseHistory(client!.gql),\n staleTime: 5 * 60 * 1000,\n refetchOnWindowFocus: false,\n retry: 1,\n });\n}\n\n/** A single order's detailed payload for the order details page. */\nexport function useOrderDetailsQuery(\n client: ViaxGqlClient | null,\n orderNumber: string | null,\n sessionReady: boolean,\n): UseQueryResult<unknown> {\n return useQuery({\n queryKey: orderHistoryKeys.orderDetails(orderNumber ?? 'none'),\n enabled: !!client && sessionReady && !!orderNumber,\n queryFn: () => getOrderDetails(client!.gql, orderNumber!),\n staleTime: 5 * 60 * 1000,\n refetchOnWindowFocus: false,\n retry: 1,\n });\n}\n"]}
@@ -488,3 +488,9 @@
488
488
  .divider {
489
489
  border-top: 1px solid #002B2B;
490
490
  }
491
+
492
+ .subscribe-header-navlink .pgn__hyperlink {
493
+ width: 5.375rem;
494
+ height: 1.625rem;
495
+ color: #CC4E0F;
496
+ }
package/dist/types.d.ts CHANGED
@@ -132,7 +132,7 @@ export interface PurchaseHistoryItem {
132
132
  }
133
133
  export interface OrdersListProps {
134
134
  orders: PurchaseHistoryItem[];
135
- onViewReceipt?: (order: PurchaseHistoryItem) => void;
135
+ receiptUrls?: Record<string, string | null>;
136
136
  }
137
137
  export interface MoneyAmount {
138
138
  amount: number;
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG","sourcesContent":["/**\n * Manage Subscription — domain types for Viax subscriber + enrollment data.\n */\n\n/** GraphQL runner used by VIAX fetchers. */\nexport type GqlRunner = (\n query: string,\n variables?: Record<string, unknown>,\n) => Promise<any>;\n\n/** Result of `tIsCurrentUserSubscriber` (JSON scalar). */\nexport interface CurrentUserSubscriberResult {\n /** Has/expects access — drive manage vs upsell messaging. */\n isSubscriber: boolean,\n /** Enrollable right now (ACTIVE / TRIAL_ACTIVE). */\n canEnroll: boolean,\n subscriptionBiId: string | null,\n /**\n * Every subscription the learner has held (all statuses, newest first),\n * e.g. a cancelled Stripe one plus a newer PayPal one. Payment history\n * lists invoices across all of them. Empty until the API returns it.\n */\n subscriptionBiIds?: string[],\n status: string | null,\n currentPeriodEnd: string | null,\n subscriptionStartDate: string | null,\n subscriptionEndDate: string | null,\n /**\n * Billing cycle / plan label used by UI (from `billingFrequency`,\n * `renewalType`, or `planName` on the API payload).\n */\n renewalType?: string | null,\n /** Optional cancel timestamp when present. */\n canceledAt?: string | null,\n /** Optional price display amount when present. */\n amount?: string | null,\n currency?: string | null,\n /**\n * Billing-plan fallback fields used when `renewalType` is missing\n * (e.g. PayPal payloads). See `resolvePlanLabel`.\n */\n billingPlanUid?: string | null,\n interval?: string | null,\n billingInterval?: string | null,\n bipOwnershipModel?: { uid?: string, omName?: string } | null,\n}\n\n/** Normalized enrollment for the cancel confirmation course list. */\nexport interface SubscriptionEnrollment {\n biId: string,\n courseMaId: string | null,\n courseName: string | null,\n courseSlug: string | null,\n /** Course card / thumbnail image. */\n imageUrl: string | null,\n orgName: string | null,\n orgLogoUrl: string | null,\n courseRunKey: string | null,\n /** TwouEnrollment bpStatus.code (ACTIVE, COMPLETED, …). */\n status: string | null,\n /** True when the enrollment has a certificate id and/or URL. */\n hasCertificate: boolean,\n /** Absolute certificate link (`COURSES_BASE_URL` + `tCertificateUrl`). */\n certificateUrl: string | null,\n}\n\nexport type PaymentProcessor = 'stripe' | 'paypal';\n\n/** Normalized invoice row for the Payment history tab. */\nexport interface PaymentHistoryItem {\n biId: string,\n /** Display order number, e.g. EDX-BI3X25N5SY30OSIK */\n orderNumber: string,\n stripeInvoiceId: string | null,\n /** PayPal sale id, or `trial:<PayPal subscription id>` for a $0 trial row. */\n paypalInvoiceId: string | null,\n /** Which processor billed this invoice; null when neither id is set. */\n paymentProcessor: PaymentProcessor | null,\n status: string | null,\n billDate: string | null,\n periodStart: string | null,\n periodEnd: string | null,\n /** Charged amount in major currency units (e.g. 59.00). */\n amount: number,\n currency: string,\n isTrial: boolean,\n}\n\n/** UI view derived from subscriber status. */\nexport type SubscriptionView =\n | 'none'\n | 'active'\n | 'canceled_access'\n | 'canceled_expired';\n\nexport type ManageTab = 'subscription' | 'payment-history';\n\nexport type BillingCycle = 'monthly' | 'annual';\n\nexport interface BillingPlanOwnershipModel {\n uid: string,\n omName: string,\n}\n\n/** Normalized row from `filterCustomerBillingPlan`. */\nexport interface BillingPlan {\n uid: string,\n stripePriceId: string,\n /** Price amount e.g. \"39.99\" */\n amount: string,\n /** Currency code e.g. \"USD\" */\n currency: string,\n isTemplate: boolean,\n ownershipModel: BillingPlanOwnershipModel,\n}\n\nexport interface BillingPlansResult {\n plans: BillingPlan[],\n}\n\n/** One course line on a program purchase receipt. */\nexport interface PurchaseHistoryCourse {\n courseId: string,\n name: string,\n price: number,\n discountAmount: number,\n}\n\n/** One-off course or program purchase from `tOrderHistory.orders`. */\nexport interface PurchaseHistoryItem {\n orderId: string,\n orderNumber: string,\n purchasedAt: string,\n paymentIntentId?: string,\n paymentMethod?: {\n type?: string,\n brand?: string,\n last4?: string,\n wallet?: string,\n } | null,\n name: string,\n total: {\n amount: number,\n currency: string,\n },\n /** Set when the payload reports a program purchase. */\n itemType?: 'course' | 'program',\n courses?: PurchaseHistoryCourse[],\n}\n\nexport interface OrdersListProps {\n orders: PurchaseHistoryItem[],\n onViewReceipt?: (order: PurchaseHistoryItem) => void,\n}\n\nexport interface MoneyAmount {\n amount: number,\n currency: string,\n}\n\n/** One line on a program order details payload. */\nexport interface OrderProgramItem {\n productId?: string,\n courseRunKey?: string,\n name: string,\n price?: MoneyAmount,\n discount?: MoneyAmount,\n total?: MoneyAmount,\n}\n\n/** Normalized `tOrderDetails` payload for the order details page. */\nexport interface OrderDetailsData {\n orderId: string,\n orderNumber: string,\n purchasedAt: string,\n paymentIntentId: string,\n name: string,\n subtotalAmount?: MoneyAmount,\n itemPriceAmount?: MoneyAmount,\n discountCode?: string | null,\n total: MoneyAmount,\n discountAmount?: MoneyAmount,\n itemType: 'course' | 'program',\n items?: OrderProgramItem[],\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG","sourcesContent":["/**\n * Manage Subscription — domain types for Viax subscriber + enrollment data.\n */\n\n/** GraphQL runner used by VIAX fetchers. */\nexport type GqlRunner = (\n query: string,\n variables?: Record<string, unknown>,\n) => Promise<any>;\n\n/** Result of `tIsCurrentUserSubscriber` (JSON scalar). */\nexport interface CurrentUserSubscriberResult {\n /** Has/expects access — drive manage vs upsell messaging. */\n isSubscriber: boolean,\n /** Enrollable right now (ACTIVE / TRIAL_ACTIVE). */\n canEnroll: boolean,\n subscriptionBiId: string | null,\n /**\n * Every subscription the learner has held (all statuses, newest first),\n * e.g. a cancelled Stripe one plus a newer PayPal one. Payment history\n * lists invoices across all of them. Empty until the API returns it.\n */\n subscriptionBiIds?: string[],\n status: string | null,\n currentPeriodEnd: string | null,\n subscriptionStartDate: string | null,\n subscriptionEndDate: string | null,\n /**\n * Billing cycle / plan label used by UI (from `billingFrequency`,\n * `renewalType`, or `planName` on the API payload).\n */\n renewalType?: string | null,\n /** Optional cancel timestamp when present. */\n canceledAt?: string | null,\n /** Optional price display amount when present. */\n amount?: string | null,\n currency?: string | null,\n /**\n * Billing-plan fallback fields used when `renewalType` is missing\n * (e.g. PayPal payloads). See `resolvePlanLabel`.\n */\n billingPlanUid?: string | null,\n interval?: string | null,\n billingInterval?: string | null,\n bipOwnershipModel?: { uid?: string, omName?: string } | null,\n}\n\n/** Normalized enrollment for the cancel confirmation course list. */\nexport interface SubscriptionEnrollment {\n biId: string,\n courseMaId: string | null,\n courseName: string | null,\n courseSlug: string | null,\n /** Course card / thumbnail image. */\n imageUrl: string | null,\n orgName: string | null,\n orgLogoUrl: string | null,\n courseRunKey: string | null,\n /** TwouEnrollment bpStatus.code (ACTIVE, COMPLETED, …). */\n status: string | null,\n /** True when the enrollment has a certificate id and/or URL. */\n hasCertificate: boolean,\n /** Absolute certificate link (`COURSES_BASE_URL` + `tCertificateUrl`). */\n certificateUrl: string | null,\n}\n\nexport type PaymentProcessor = 'stripe' | 'paypal';\n\n/** Normalized invoice row for the Payment history tab. */\nexport interface PaymentHistoryItem {\n biId: string,\n /** Display order number, e.g. EDX-BI3X25N5SY30OSIK */\n orderNumber: string,\n stripeInvoiceId: string | null,\n /** PayPal sale id, or `trial:<PayPal subscription id>` for a $0 trial row. */\n paypalInvoiceId: string | null,\n /** Which processor billed this invoice; null when neither id is set. */\n paymentProcessor: PaymentProcessor | null,\n status: string | null,\n billDate: string | null,\n periodStart: string | null,\n periodEnd: string | null,\n /** Charged amount in major currency units (e.g. 59.00). */\n amount: number,\n currency: string,\n isTrial: boolean,\n}\n\n/** UI view derived from subscriber status. */\nexport type SubscriptionView =\n | 'none'\n | 'active'\n | 'canceled_access'\n | 'canceled_expired';\n\nexport type ManageTab = 'subscription' | 'payment-history';\n\nexport type BillingCycle = 'monthly' | 'annual';\n\nexport interface BillingPlanOwnershipModel {\n uid: string,\n omName: string,\n}\n\n/** Normalized row from `filterCustomerBillingPlan`. */\nexport interface BillingPlan {\n uid: string,\n stripePriceId: string,\n /** Price amount e.g. \"39.99\" */\n amount: string,\n /** Currency code e.g. \"USD\" */\n currency: string,\n isTemplate: boolean,\n ownershipModel: BillingPlanOwnershipModel,\n}\n\nexport interface BillingPlansResult {\n plans: BillingPlan[],\n}\n\n/** One course line on a program purchase receipt. */\nexport interface PurchaseHistoryCourse {\n courseId: string,\n name: string,\n price: number,\n discountAmount: number,\n}\n\n/** One-off course or program purchase from `tOrderHistory.orders`. */\nexport interface PurchaseHistoryItem {\n orderId: string,\n orderNumber: string,\n purchasedAt: string,\n paymentIntentId?: string,\n paymentMethod?: {\n type?: string,\n brand?: string,\n last4?: string,\n wallet?: string,\n } | null,\n name: string,\n total: {\n amount: number,\n currency: string,\n },\n /** Set when the payload reports a program purchase. */\n itemType?: 'course' | 'program',\n courses?: PurchaseHistoryCourse[],\n}\n\nexport interface OrdersListProps {\n orders: PurchaseHistoryItem[],\n receiptUrls?: Record<string, string | null>,\n}\n\nexport interface MoneyAmount {\n amount: number,\n currency: string,\n}\n\n/** One line on a program order details payload. */\nexport interface OrderProgramItem {\n productId?: string,\n courseRunKey?: string,\n name: string,\n price?: MoneyAmount,\n discount?: MoneyAmount,\n total?: MoneyAmount,\n}\n\n/** Normalized `tOrderDetails` payload for the order details page. */\nexport interface OrderDetailsData {\n orderId: string,\n orderNumber: string,\n purchasedAt: string,\n paymentIntentId: string,\n name: string,\n subtotalAmount?: MoneyAmount,\n itemPriceAmount?: MoneyAmount,\n discountCode?: string | null,\n total: MoneyAmount,\n discountAmount?: MoneyAmount,\n itemType: 'course' | 'program',\n items?: OrderProgramItem[],\n}\n"]}
@@ -13,11 +13,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
13
13
  step((generator = generator.apply(thisArg, _arguments || [])).next());
14
14
  });
15
15
  };
16
- import { EnvironmentTypes, getSiteConfig } from '@openedx/frontend-base';
16
+ import { EnvironmentTypes, getAppConfig, getSiteConfig } from '@openedx/frontend-base';
17
+ import { appId } from '../constants';
17
18
  /** Hardcoded edX JWT used only for local/dev against Viax (same pattern as enroll/checkout MFEs). */
18
19
  const DEV_SESSION_BODY = {
19
- payload: 'eyJhbGciOiJSUzUxMiIsImtpZCI6Imxtc3N0YWdlMDAyIiwidHlwIjoiSldUIn0.eyJhdWQiOiJJbmtvY3VqTGlreXVjc0Vkd2lXYXRkZWJyRWFja21ldkxha0R1aWZLb29zaGtha1dvdyIsImV4cCI6MTc5MTUyODA4OSwiZ3JhbnRfdHlwZSI6InBhc3N3b3JkIiwiaWF0IjoxNzkxNTI0NDg5LCJpc3MiOiJodHRwczovL2NvdXJzZXMuc3RhZ2UuZWR4Lm9yZy9vYXV0aDIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJUVV8yNjA4X0pFRzMiLCJzY29wZXMiOlsidXNlcl9pZCIsImVtYWlsIiwicHJvZmlsZSJdLCJ2ZXJzaW9uIjoiMS4yLjAiLCJzdWIiOiJiMTM0NGUxYWFjNGI5MWExZDBiZGU0NzFkMjdlMTkwNCIsImZpbHRlcnMiOlsidXNlcjptZSJdLCJpc19yZXN0cmljdGVkIjpmYWxzZSwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJ1c2VyX2lkIjo1Mjg0NzAwLCJlbWFpbCI6InRlc3QtdXNlckBnbWFpbC5jb20iLCJuYW1lIjoiVGVzdCBVc2VyIiwiZmFtaWx5X25hbWUiOiIiLCJnaXZlbl9uYW1lIjoiIiwiYWRtaW5pc3RyYXRvciI6ZmFsc2UsInN1cGVydXNlciI6ZmFsc2V9',
20
- signature: 'Ho60pm9qWXSiU9yWPJ6srgKxlDtAgiBH3kMbzCFOBZq7qm8Qi_z-iNMqxVl5dozvQNtJAuS5A--lvzkIk9fEb2u0tS_L_QKBdrEg28yvPcjwlgOsGGZ5wUOu5Vi2NN9cbNH-TiPA0zLIMVifvh8NhuWTzk6Q4yIAqU28H1Xz6Mwiz0ftHcARvdIYA-IGaWJt0YEVOw_nDLWui7V4AXSeAV50rHAlqsHzAfUnmpBxW2KAve-ZWMxmDCiF3xEaiwKtQXBsUCJ1xjGxub4dzZjry4ELRQf6EpW2l6sL5vGjD2FrlSMyt08D7lUCMBAbzpr8-ycuTRicMpnS2l64VMOp1g'
20
+ payload: 'eyJhbGciOiJSUzUxMiIsImtpZCI6Imxtc3N0YWdlMDAyIiwidHlwIjoiSldUIn0.eyJhdWQiOiJJbmtvY3VqTGlreXVjc0Vkd2lXYXRkZWJyRWFja21ldkxha0R1aWZLb29zaGtha1dvdyIsImV4cCI6MTc5NDIzNzMzNywiZ3JhbnRfdHlwZSI6InBhc3N3b3JkIiwiaWF0IjoxNzk0MjMzNzM3LCJpc3MiOiJodHRwczovL2NvdXJzZXMuc3RhZ2UuZWR4Lm9yZy9vYXV0aDIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJBQ18yNjEwXzRUTVMiLCJzY29wZXMiOlsidXNlcl9pZCIsImVtYWlsIiwicHJvZmlsZSJdLCJ2ZXJzaW9uIjoiMS4yLjAiLCJzdWIiOiJiNmQ3NzM0NWUyMTZmNzc1MTM5NzAwOTZlYjAxMTJkNyIsImZpbHRlcnMiOlsidXNlcjptZSJdLCJpc19yZXN0cmljdGVkIjpmYWxzZSwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJ1c2VyX2lkIjo1Mjg3NjAzLCJlbWFpbCI6ImFsYWNhcnQuY2hlY2tvdXQxQGV4YW1wbGUuY29tIiwibmFtZSI6ImFsYWNhcnQgY2hlY2tvdXQgdGVzdCIsImZhbWlseV9uYW1lIjoiIiwiZ2l2ZW5fbmFtZSI6IiIsImFkbWluaXN0cmF0b3IiOmZhbHNlLCJzdXBlcnVzZXIiOmZhbHNlfQ',
21
+ signature: 'J4DKTY_Cqpy-C-H0TznUxQ4aGECLdWcUHV2hATgdZVnlabSHN_pY2DywaFnaxdCgMWgYGK_DGTzH7fph7iDuJo2zCl7Lwrg2wvPvR6z5fzqZli_RkAs4ja7RCHMSvocRavQdeEeGwzBpRpyB97bV1vZbN76mw2kxRqIyxF-YJsMbQq01eROe2XtglPffZ5LwZ1SVgTY2MLdGRhsIoeKgFX7M81jK-ODD5swdGDKibk0yn9YAGe-ZobVic4BkesQUCBgRbq3IXqFnhm8cuaV-tniH-n61TcnPvY5r_qXy5eG2s4cbNRzik7_e8db_YV_1hLz56cZ-OdbHt5T_ERwxUA'
21
22
  };
22
23
  function parseSessionResponse(data) {
23
24
  var _a, _b, _c, _d;
@@ -43,9 +44,7 @@ function isDevelopment() {
43
44
  }
44
45
  /** LMS edx-session endpoint for the current site. */
45
46
  export function getEdxSessionUrl() {
46
- return isDevelopment()
47
- ? `${getSiteConfig().lmsBaseUrl}/api/edx-session`
48
- : ''; // same url but static was used before.
47
+ return `${getAppConfig(appId).COURSES_BASE_URL}/api/edx-session`; // same url but static was used before.
49
48
  }
50
49
  /** Exchange the learner's edX session for a Viax token. */
51
50
  export function fetchEdxSession(sessionUrl) {
@@ -1 +1 @@
1
- {"version":3,"file":"edxSession.js","sourceRoot":"","sources":["../../src/utils/edxSession.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;;;;AAEH,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAWzE,qGAAqG;AACrG,MAAM,gBAAgB,GAAG;IACvB,OAAO,EAAE,kuBAAkuB;IAC3uB,SAAS,EAAE,wVAAwV;CACpW,CAAC;AAEF,SAAS,oBAAoB,CAAC,IAA6B;;IACzD,MAAM,SAAS,GAAG,CAChB,MAAA,MAAA,MAAA,IAAI,CAAC,SAAS,mCAAI,IAAI,CAAC,KAAK,mCAAI,IAAI,CAAC,YAAY,mCAAI,IAAI,CAAC,WAAW,CAChD,CAAC;IACxB,MAAM,WAAW,GAAG,CAAC,MAAA,IAAI,CAAC,WAAW,mCAAI,IAAI,CAAC,YAAY,CAAuB,CAAC;IAElF,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IACD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO;QACL,SAAS;QACT,WAAW;QACX,QAAQ,EAAE,IAAI,CAAC,QAA8B;QAC7C,SAAS,EAAE,IAAI,CAAC,SAA+B;QAC/C,QAAQ,EAAE,IAAI,CAAC,QAA8B;QAC7C,KAAK,EAAE,IAAI,CAAC,KAA2B;KACxC,CAAC;AACJ,CAAC;AAED,SAAS,aAAa;IACpB,OAAO,aAAa,EAAE,CAAC,WAAW,KAAK,gBAAgB,CAAC,WAAW,CAAC;AACtE,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,gBAAgB;IAC9B,OAAO,aAAa,EAAE;QACpB,CAAC,CAAC,GAAG,aAAa,EAAE,CAAC,UAAU,kBAAkB;QACjD,CAAC,CAAC,EAAE,CAAC,CAAC,uCAAuC;AACjD,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAgB,eAAe,CAAC,UAAkB;;QACtD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE;YAClC,MAAM,EAAE,MAAM;YACd,WAAW,EAAE,SAAS;YACtB,OAAO,EAAE;gBACP,MAAM,EAAE,kBAAkB;gBAC1B,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS;SACrE,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CACb,gCAAgC,GAAG,CAAC,MAAM,uCAAuC,CAClF,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAkD,CAAC;QAC9E,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACtC,CAAC;QAED,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;CAAA","sourcesContent":["/**\n * Exchange the learner's edX session for a Viax JWT.\n *\n * Dev uses POST with a hardcoded JWT payload (local LMS cookie exchange is\n * unavailable). Stage/prod use POST with browser session cookies.\n */\n\nimport { EnvironmentTypes, getSiteConfig } from '@openedx/frontend-base';\n\nexport interface EdxSessionResult {\n viaxToken: string,\n customerUid: string,\n partyUid?: string,\n edxUserId?: string,\n username?: string,\n email?: string,\n}\n\n/** Hardcoded edX JWT used only for local/dev against Viax (same pattern as enroll/checkout MFEs). */\nconst DEV_SESSION_BODY = {\n payload: 'eyJhbGciOiJSUzUxMiIsImtpZCI6Imxtc3N0YWdlMDAyIiwidHlwIjoiSldUIn0.eyJhdWQiOiJJbmtvY3VqTGlreXVjc0Vkd2lXYXRkZWJyRWFja21ldkxha0R1aWZLb29zaGtha1dvdyIsImV4cCI6MTc5MTUyODA4OSwiZ3JhbnRfdHlwZSI6InBhc3N3b3JkIiwiaWF0IjoxNzkxNTI0NDg5LCJpc3MiOiJodHRwczovL2NvdXJzZXMuc3RhZ2UuZWR4Lm9yZy9vYXV0aDIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJUVV8yNjA4X0pFRzMiLCJzY29wZXMiOlsidXNlcl9pZCIsImVtYWlsIiwicHJvZmlsZSJdLCJ2ZXJzaW9uIjoiMS4yLjAiLCJzdWIiOiJiMTM0NGUxYWFjNGI5MWExZDBiZGU0NzFkMjdlMTkwNCIsImZpbHRlcnMiOlsidXNlcjptZSJdLCJpc19yZXN0cmljdGVkIjpmYWxzZSwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJ1c2VyX2lkIjo1Mjg0NzAwLCJlbWFpbCI6InRlc3QtdXNlckBnbWFpbC5jb20iLCJuYW1lIjoiVGVzdCBVc2VyIiwiZmFtaWx5X25hbWUiOiIiLCJnaXZlbl9uYW1lIjoiIiwiYWRtaW5pc3RyYXRvciI6ZmFsc2UsInN1cGVydXNlciI6ZmFsc2V9',\n signature: 'Ho60pm9qWXSiU9yWPJ6srgKxlDtAgiBH3kMbzCFOBZq7qm8Qi_z-iNMqxVl5dozvQNtJAuS5A--lvzkIk9fEb2u0tS_L_QKBdrEg28yvPcjwlgOsGGZ5wUOu5Vi2NN9cbNH-TiPA0zLIMVifvh8NhuWTzk6Q4yIAqU28H1Xz6Mwiz0ftHcARvdIYA-IGaWJt0YEVOw_nDLWui7V4AXSeAV50rHAlqsHzAfUnmpBxW2KAve-ZWMxmDCiF3xEaiwKtQXBsUCJ1xjGxub4dzZjry4ELRQf6EpW2l6sL5vGjD2FrlSMyt08D7lUCMBAbzpr8-ycuTRicMpnS2l64VMOp1g'\n};\n\nfunction parseSessionResponse(data: Record<string, unknown>): EdxSessionResult {\n const viaxToken = (\n data.viaxToken ?? data.token ?? data.access_token ?? data.accessToken\n ) as string | undefined;\n const customerUid = (data.customerUid ?? data.customer_uid) as string | undefined;\n\n if (!viaxToken) {\n throw new Error('Session response missing viax token.');\n }\n if (!customerUid) {\n throw new Error('Session response missing customerUid.');\n }\n\n return {\n viaxToken,\n customerUid,\n partyUid: data.partyUid as string | undefined,\n edxUserId: data.edxUserId as string | undefined,\n username: data.username as string | undefined,\n email: data.email as string | undefined,\n };\n}\n\nfunction isDevelopment(): boolean {\n return getSiteConfig().environment === EnvironmentTypes.DEVELOPMENT;\n}\n\n/** LMS edx-session endpoint for the current site. */\nexport function getEdxSessionUrl(): string {\n return isDevelopment()\n ? `${getSiteConfig().lmsBaseUrl}/api/edx-session`\n : ''; // same url but static was used before.\n}\n\n/** Exchange the learner's edX session for a Viax token. */\nexport async function fetchEdxSession(sessionUrl: string): Promise<EdxSessionResult> {\n const res = await fetch(sessionUrl, {\n method: 'POST',\n credentials: 'include',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n body: isDevelopment() ? JSON.stringify(DEV_SESSION_BODY) : undefined,\n });\n\n if (!res.ok) {\n throw new Error(\n `Failed to establish session (${res.status}). Please log into edX and try again.`,\n );\n }\n\n const data = await res.json() as Record<string, unknown> & { error?: string };\n if (data.error) {\n throw new Error(String(data.error));\n }\n\n return parseSessionResponse(data);\n}\n"]}
1
+ {"version":3,"file":"edxSession.js","sourceRoot":"","sources":["../../src/utils/edxSession.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;;;;AAEH,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvF,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAWvC,qGAAqG;AACrG,MAAM,gBAAgB,GAAG;IACvB,OAAO,EAAE,gwBAAgwB;IACzwB,SAAS,EAAE,wVAAwV;CACpW,CAAC;AAEF,SAAS,oBAAoB,CAAC,IAA6B;;IACzD,MAAM,SAAS,GAAG,CAChB,MAAA,MAAA,MAAA,IAAI,CAAC,SAAS,mCAAI,IAAI,CAAC,KAAK,mCAAI,IAAI,CAAC,YAAY,mCAAI,IAAI,CAAC,WAAW,CAChD,CAAC;IACxB,MAAM,WAAW,GAAG,CAAC,MAAA,IAAI,CAAC,WAAW,mCAAI,IAAI,CAAC,YAAY,CAAuB,CAAC;IAElF,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IACD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO;QACL,SAAS;QACT,WAAW;QACX,QAAQ,EAAE,IAAI,CAAC,QAA8B;QAC7C,SAAS,EAAE,IAAI,CAAC,SAA+B;QAC/C,QAAQ,EAAE,IAAI,CAAC,QAA8B;QAC7C,KAAK,EAAE,IAAI,CAAC,KAA2B;KACxC,CAAC;AACJ,CAAC;AAED,SAAS,aAAa;IACpB,OAAO,aAAa,EAAE,CAAC,WAAW,KAAK,gBAAgB,CAAC,WAAW,CAAC;AACtE,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,gBAAgB;IAC9B,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,gBAAgB,kBAAkB,CAAC,CAAA,uCAAuC;AAC1G,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAgB,eAAe,CAAC,UAAkB;;QACtD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE;YAClC,MAAM,EAAE,MAAM;YACd,WAAW,EAAE,SAAS;YACtB,OAAO,EAAE;gBACP,MAAM,EAAE,kBAAkB;gBAC1B,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS;SACrE,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CACb,gCAAgC,GAAG,CAAC,MAAM,uCAAuC,CAClF,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAkD,CAAC;QAC9E,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACtC,CAAC;QAED,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;CAAA","sourcesContent":["/**\n * Exchange the learner's edX session for a Viax JWT.\n *\n * Dev uses POST with a hardcoded JWT payload (local LMS cookie exchange is\n * unavailable). Stage/prod use POST with browser session cookies.\n */\n\nimport { EnvironmentTypes, getAppConfig, getSiteConfig } from '@openedx/frontend-base';\nimport { appId } from '@src/constants';\n\nexport interface EdxSessionResult {\n viaxToken: string,\n customerUid: string,\n partyUid?: string,\n edxUserId?: string,\n username?: string,\n email?: string,\n}\n\n/** Hardcoded edX JWT used only for local/dev against Viax (same pattern as enroll/checkout MFEs). */\nconst DEV_SESSION_BODY = {\n payload: 'eyJhbGciOiJSUzUxMiIsImtpZCI6Imxtc3N0YWdlMDAyIiwidHlwIjoiSldUIn0.eyJhdWQiOiJJbmtvY3VqTGlreXVjc0Vkd2lXYXRkZWJyRWFja21ldkxha0R1aWZLb29zaGtha1dvdyIsImV4cCI6MTc5NDIzNzMzNywiZ3JhbnRfdHlwZSI6InBhc3N3b3JkIiwiaWF0IjoxNzk0MjMzNzM3LCJpc3MiOiJodHRwczovL2NvdXJzZXMuc3RhZ2UuZWR4Lm9yZy9vYXV0aDIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJBQ18yNjEwXzRUTVMiLCJzY29wZXMiOlsidXNlcl9pZCIsImVtYWlsIiwicHJvZmlsZSJdLCJ2ZXJzaW9uIjoiMS4yLjAiLCJzdWIiOiJiNmQ3NzM0NWUyMTZmNzc1MTM5NzAwOTZlYjAxMTJkNyIsImZpbHRlcnMiOlsidXNlcjptZSJdLCJpc19yZXN0cmljdGVkIjpmYWxzZSwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJ1c2VyX2lkIjo1Mjg3NjAzLCJlbWFpbCI6ImFsYWNhcnQuY2hlY2tvdXQxQGV4YW1wbGUuY29tIiwibmFtZSI6ImFsYWNhcnQgY2hlY2tvdXQgdGVzdCIsImZhbWlseV9uYW1lIjoiIiwiZ2l2ZW5fbmFtZSI6IiIsImFkbWluaXN0cmF0b3IiOmZhbHNlLCJzdXBlcnVzZXIiOmZhbHNlfQ',\n signature: 'J4DKTY_Cqpy-C-H0TznUxQ4aGECLdWcUHV2hATgdZVnlabSHN_pY2DywaFnaxdCgMWgYGK_DGTzH7fph7iDuJo2zCl7Lwrg2wvPvR6z5fzqZli_RkAs4ja7RCHMSvocRavQdeEeGwzBpRpyB97bV1vZbN76mw2kxRqIyxF-YJsMbQq01eROe2XtglPffZ5LwZ1SVgTY2MLdGRhsIoeKgFX7M81jK-ODD5swdGDKibk0yn9YAGe-ZobVic4BkesQUCBgRbq3IXqFnhm8cuaV-tniH-n61TcnPvY5r_qXy5eG2s4cbNRzik7_e8db_YV_1hLz56cZ-OdbHt5T_ERwxUA'\n};\n\nfunction parseSessionResponse(data: Record<string, unknown>): EdxSessionResult {\n const viaxToken = (\n data.viaxToken ?? data.token ?? data.access_token ?? data.accessToken\n ) as string | undefined;\n const customerUid = (data.customerUid ?? data.customer_uid) as string | undefined;\n\n if (!viaxToken) {\n throw new Error('Session response missing viax token.');\n }\n if (!customerUid) {\n throw new Error('Session response missing customerUid.');\n }\n\n return {\n viaxToken,\n customerUid,\n partyUid: data.partyUid as string | undefined,\n edxUserId: data.edxUserId as string | undefined,\n username: data.username as string | undefined,\n email: data.email as string | undefined,\n };\n}\n\nfunction isDevelopment(): boolean {\n return getSiteConfig().environment === EnvironmentTypes.DEVELOPMENT;\n}\n\n/** LMS edx-session endpoint for the current site. */\nexport function getEdxSessionUrl(): string {\n return `${getAppConfig(appId).COURSES_BASE_URL}/api/edx-session`;// same url but static was used before.\n}\n\n/** Exchange the learner's edX session for a Viax token. */\nexport async function fetchEdxSession(sessionUrl: string): Promise<EdxSessionResult> {\n const res = await fetch(sessionUrl, {\n method: 'POST',\n credentials: 'include',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n body: isDevelopment() ? JSON.stringify(DEV_SESSION_BODY) : undefined,\n });\n\n if (!res.ok) {\n throw new Error(\n `Failed to establish session (${res.status}). Please log into edX and try again.`,\n );\n }\n\n const data = await res.json() as Record<string, unknown> & { error?: string };\n if (data.error) {\n throw new Error(String(data.error));\n }\n\n return parseSessionResponse(data);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edx/frontend-app-subscription-manage",
3
- "version": "1.25.0",
3
+ "version": "1.27.0",
4
4
  "description": "Subscription Manage Frontend application",
5
5
  "repository": {
6
6
  "type": "git",
@@ -34,7 +34,7 @@
34
34
  "build:packages": "make build-packages",
35
35
  "clean": "make clean",
36
36
  "clean:packages": "make clean-packages",
37
- "dev": "PORT=1996 PUBLIC_PATH=/manage-subscription openedx dev",
37
+ "dev": "PORT=1996 PUBLIC_PATH=/order-history openedx dev",
38
38
  "dev:site": "make dev-site",
39
39
  "dev:packages": "make dev-packages",
40
40
  "i18n_extract": "openedx formatjs extract",