@edx/frontend-app-alacarte-checkout 1.19.0 → 1.20.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.
@@ -11,13 +11,16 @@ const CheckoutPage = () => {
11
11
  const stripePublishableKey = config.STRIPE_PUBLIC_KEY;
12
12
  const apiUrl = config.VIAX_API_URL;
13
13
  const isDevelopment = siteConfig.environment === 'development';
14
+ const disableComplianceCheck = config.DISABLE_COMPLIANCE_CHECK === true;
14
15
  const edxSessionUrl = `${isDevelopment ? 'https://courses.stage.edx.org' : LMS_BASE_URL}/api/edx-session`;
15
16
  const geolocationUrl = `${isDevelopment ? 'https://courses.stage.edx.org' : LMS_BASE_URL}/api/geolocation/lookup`;
16
- const complianceCheckUrl = `${isDevelopment ? 'https://courses.stage.edx.org' : LMS_BASE_URL}/api/compliance-check`;
17
+ const complianceCheckUrl = disableComplianceCheck
18
+ ? undefined
19
+ : `${isDevelopment ? 'https://courses.stage.edx.org' : LMS_BASE_URL}/api/compliance-check`;
17
20
  if (!stripePublishableKey || !apiUrl || !edxSessionUrl) {
18
21
  return (_jsx(PageWrapper, { children: _jsxs(Alert, { variant: "danger", children: ["We're having trouble loading the checkout. Please refresh the page or try again in a few moments. If the problem persists,", ' ', _jsx("a", { href: "https://courses.edx.org/support/contact_us", children: "contact support" }), "."] }) }));
19
22
  }
20
- return (_jsx(PageWrapper, { children: _jsx(CheckoutGate, { stripePublishableKey: stripePublishableKey, apiUrl: apiUrl, edxSessionUrl: edxSessionUrl, geolocationUrl: geolocationUrl, complianceCheckUrl: complianceCheckUrl, learnerDashboardUrl: `${LMS_BASE_URL}/dashboard`, homeUrl: LMS_BASE_URL || '/', onComplete: (_subscriptionBiId) => {
23
+ return (_jsx(PageWrapper, { children: _jsx(CheckoutGate, { stripePublishableKey: stripePublishableKey, apiUrl: apiUrl, edxSessionUrl: edxSessionUrl, geolocationUrl: geolocationUrl, complianceCheckUrl: complianceCheckUrl, disableComplianceCheck: disableComplianceCheck, learnerDashboardUrl: `${LMS_BASE_URL}/dashboard`, homeUrl: LMS_BASE_URL || '/', onComplete: (_subscriptionBiId) => {
21
24
  console.log(_subscriptionBiId);
22
25
  // window.location.href = `/checkout/confirmation?sub=${_subscriptionBiId ?? ''}`;
23
26
  // Success screen.
@@ -1 +1 @@
1
- {"version":3,"file":"CheckoutPage.js","sourceRoot":"","sources":["../../src/checkoutPage/CheckoutPage.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,YAAY,MAAM,yCAAyC,CAAC;AAEnE,MAAM,WAAW,GAA4C,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAC7E,KAAC,SAAS,cAAE,QAAQ,GAAa,CAClC,CAAC;AAEF,MAAM,YAAY,GAAa,GAAG,EAAE;IAClC,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,YAAY,GAAG,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC9D,MAAM,oBAAoB,GAAG,MAAM,CAAC,iBAA2B,CAAC;IAChE,MAAM,MAAM,GAAG,MAAM,CAAC,YAAsB,CAAC;IAC7C,MAAM,aAAa,GAAG,UAAU,CAAC,WAAW,KAAK,aAAa,CAAC;IAC/D,MAAM,aAAa,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,YAAY,kBAAkB,CAAC;IAC1G,MAAM,cAAc,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,YAAY,yBAAyB,CAAC;IAClH,MAAM,kBAAkB,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,YAAY,uBAAuB,CAAC;IAEpH,IAAI,CAAC,oBAAoB,IAAI,CAAC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QACvD,OAAO,CACL,KAAC,WAAW,cACV,MAAC,KAAK,IAAC,OAAO,EAAC,QAAQ,2IAEwC,GAAG,EAChE,YAAG,IAAI,EAAC,4CAA4C,gCAEhD,SAEE,GACI,CACf,CAAC;IACJ,CAAC;IAED,OAAO,CACL,KAAC,WAAW,cACV,KAAC,YAAY,IACX,oBAAoB,EAAE,oBAAoB,EAC1C,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,aAAa,EAC5B,cAAc,EAAE,cAAc,EAC9B,kBAAkB,EAAE,kBAAkB,EACtC,mBAAmB,EAAE,GAAG,YAAY,YAAY,EAChD,OAAO,EAAE,YAAY,IAAI,GAAG,EAC5B,UAAU,EAAE,CAAC,iBAAiB,EAAE,EAAE;gBAChC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;gBAC/B,kFAAkF;gBAClF,kBAAkB;YACpB,CAAC,GACD,GACU,CACf,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,YAAY,CAAC","sourcesContent":["import React from 'react';\nimport { Alert, Container } from '@openedx/paragon';\nimport { getAppConfig, getSiteConfig } from '@openedx/frontend-base';\nimport { appId } from '@src/constants';\nimport CheckoutGate from '../components/CheckoutGate/CheckoutGate';\n\nconst PageWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <Container>{children}</Container>\n);\n\nconst CheckoutPage: React.FC = () => {\n const config = getAppConfig(appId);\n const siteConfig = getSiteConfig();\n const LMS_BASE_URL = siteConfig.lmsBaseUrl.replace(/\\/$/, '');\n const stripePublishableKey = config.STRIPE_PUBLIC_KEY as string;\n const apiUrl = config.VIAX_API_URL as string;\n const isDevelopment = siteConfig.environment === 'development';\n const edxSessionUrl = `${isDevelopment ? 'https://courses.stage.edx.org' : LMS_BASE_URL}/api/edx-session`;\n const geolocationUrl = `${isDevelopment ? 'https://courses.stage.edx.org' : LMS_BASE_URL}/api/geolocation/lookup`;\n const complianceCheckUrl = `${isDevelopment ? 'https://courses.stage.edx.org' : LMS_BASE_URL}/api/compliance-check`;\n\n if (!stripePublishableKey || !apiUrl || !edxSessionUrl) {\n return (\n <PageWrapper>\n <Alert variant=\"danger\">\n We&apos;re having trouble loading the checkout. Please refresh the\n page or try again in a few moments. If the problem persists,{' '}\n <a href=\"https://courses.edx.org/support/contact_us\">\n contact support\n </a>\n .\n </Alert>\n </PageWrapper>\n );\n }\n\n return (\n <PageWrapper>\n <CheckoutGate\n stripePublishableKey={stripePublishableKey}\n apiUrl={apiUrl}\n edxSessionUrl={edxSessionUrl}\n geolocationUrl={geolocationUrl}\n complianceCheckUrl={complianceCheckUrl}\n learnerDashboardUrl={`${LMS_BASE_URL}/dashboard`}\n homeUrl={LMS_BASE_URL || '/'}\n onComplete={(_subscriptionBiId) => {\n console.log(_subscriptionBiId);\n // window.location.href = `/checkout/confirmation?sub=${_subscriptionBiId ?? ''}`;\n // Success screen.\n }}\n />\n </PageWrapper>\n );\n};\n\nexport default CheckoutPage;\n"]}
1
+ {"version":3,"file":"CheckoutPage.js","sourceRoot":"","sources":["../../src/checkoutPage/CheckoutPage.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,YAAY,MAAM,yCAAyC,CAAC;AAEnE,MAAM,WAAW,GAA4C,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAC7E,KAAC,SAAS,cAAE,QAAQ,GAAa,CAClC,CAAC;AAEF,MAAM,YAAY,GAAa,GAAG,EAAE;IAClC,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,YAAY,GAAG,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC9D,MAAM,oBAAoB,GAAG,MAAM,CAAC,iBAA2B,CAAC;IAChE,MAAM,MAAM,GAAG,MAAM,CAAC,YAAsB,CAAC;IAC7C,MAAM,aAAa,GAAG,UAAU,CAAC,WAAW,KAAK,aAAa,CAAC;IAC/D,MAAM,sBAAsB,GAAG,MAAM,CAAC,wBAAwB,KAAK,IAAI,CAAC;IACxE,MAAM,aAAa,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,YAAY,kBAAkB,CAAC;IAC1G,MAAM,cAAc,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,YAAY,yBAAyB,CAAC;IAClH,MAAM,kBAAkB,GAAG,sBAAsB;QAC/C,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,YAAY,uBAAuB,CAAC;IAE7F,IAAI,CAAC,oBAAoB,IAAI,CAAC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QACvD,OAAO,CACL,KAAC,WAAW,cACV,MAAC,KAAK,IAAC,OAAO,EAAC,QAAQ,2IAEwC,GAAG,EAChE,YAAG,IAAI,EAAC,4CAA4C,gCAEhD,SAEE,GACI,CACf,CAAC;IACJ,CAAC;IAED,OAAO,CACL,KAAC,WAAW,cACV,KAAC,YAAY,IACX,oBAAoB,EAAE,oBAAoB,EAC1C,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,aAAa,EAC5B,cAAc,EAAE,cAAc,EAC9B,kBAAkB,EAAE,kBAAkB,EACtC,sBAAsB,EAAE,sBAAsB,EAC9C,mBAAmB,EAAE,GAAG,YAAY,YAAY,EAChD,OAAO,EAAE,YAAY,IAAI,GAAG,EAC5B,UAAU,EAAE,CAAC,iBAAiB,EAAE,EAAE;gBAChC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;gBAC/B,kFAAkF;gBAClF,kBAAkB;YACpB,CAAC,GACD,GACU,CACf,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,YAAY,CAAC","sourcesContent":["import React from 'react';\nimport { Alert, Container } from '@openedx/paragon';\nimport { getAppConfig, getSiteConfig } from '@openedx/frontend-base';\nimport { appId } from '@src/constants';\nimport CheckoutGate from '../components/CheckoutGate/CheckoutGate';\n\nconst PageWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <Container>{children}</Container>\n);\n\nconst CheckoutPage: React.FC = () => {\n const config = getAppConfig(appId);\n const siteConfig = getSiteConfig();\n const LMS_BASE_URL = siteConfig.lmsBaseUrl.replace(/\\/$/, '');\n const stripePublishableKey = config.STRIPE_PUBLIC_KEY as string;\n const apiUrl = config.VIAX_API_URL as string;\n const isDevelopment = siteConfig.environment === 'development';\n const disableComplianceCheck = config.DISABLE_COMPLIANCE_CHECK === true;\n const edxSessionUrl = `${isDevelopment ? 'https://courses.stage.edx.org' : LMS_BASE_URL}/api/edx-session`;\n const geolocationUrl = `${isDevelopment ? 'https://courses.stage.edx.org' : LMS_BASE_URL}/api/geolocation/lookup`;\n const complianceCheckUrl = disableComplianceCheck\n ? undefined\n : `${isDevelopment ? 'https://courses.stage.edx.org' : LMS_BASE_URL}/api/compliance-check`;\n\n if (!stripePublishableKey || !apiUrl || !edxSessionUrl) {\n return (\n <PageWrapper>\n <Alert variant=\"danger\">\n We&apos;re having trouble loading the checkout. Please refresh the\n page or try again in a few moments. If the problem persists,{' '}\n <a href=\"https://courses.edx.org/support/contact_us\">\n contact support\n </a>\n .\n </Alert>\n </PageWrapper>\n );\n }\n\n return (\n <PageWrapper>\n <CheckoutGate\n stripePublishableKey={stripePublishableKey}\n apiUrl={apiUrl}\n edxSessionUrl={edxSessionUrl}\n geolocationUrl={geolocationUrl}\n complianceCheckUrl={complianceCheckUrl}\n disableComplianceCheck={disableComplianceCheck}\n learnerDashboardUrl={`${LMS_BASE_URL}/dashboard`}\n homeUrl={LMS_BASE_URL || '/'}\n onComplete={(_subscriptionBiId) => {\n console.log(_subscriptionBiId);\n // window.location.href = `/checkout/confirmation?sub=${_subscriptionBiId ?? ''}`;\n // Success screen.\n }}\n />\n </PageWrapper>\n );\n};\n\nexport default CheckoutPage;\n"]}
@@ -6,6 +6,8 @@ export interface CheckoutGateProps extends CheckoutProps {
6
6
  homeUrl?: string;
7
7
  /** ALC-307 compliance-check endpoint — decides whether the learner is embargoed. */
8
8
  complianceCheckUrl?: string;
9
+ /** When true, skip the compliance-check request. */
10
+ disableComplianceCheck?: boolean;
9
11
  }
10
- declare const CheckoutGate: ({ learnerDashboardUrl, homeUrl, complianceCheckUrl, ...checkoutProps }: CheckoutGateProps) => import("react/jsx-runtime").JSX.Element;
12
+ declare const CheckoutGate: ({ learnerDashboardUrl, homeUrl, complianceCheckUrl, disableComplianceCheck, ...checkoutProps }: CheckoutGateProps) => import("react/jsx-runtime").JSX.Element;
11
13
  export default CheckoutGate;
@@ -18,13 +18,14 @@ import Checkout from '../Checkout/Checkout';
18
18
  import CountryUnavailableModal from '../CountryUnavailableModal/CountryUnavailableModal';
19
19
  import messages from './Messages';
20
20
  const CheckoutGate = (_a) => {
21
- var { learnerDashboardUrl, homeUrl = '/', complianceCheckUrl } = _a, checkoutProps = __rest(_a, ["learnerDashboardUrl", "homeUrl", "complianceCheckUrl"]);
21
+ var { learnerDashboardUrl, homeUrl = '/', complianceCheckUrl, disableComplianceCheck } = _a, checkoutProps = __rest(_a, ["learnerDashboardUrl", "homeUrl", "complianceCheckUrl", "disableComplianceCheck"]);
22
22
  const { formatMessage } = useIntl();
23
23
  const { gateStatus, userCountry, gateMessage } = useCheckoutGate({
24
24
  apiUrl: checkoutProps.apiUrl,
25
25
  edxSessionUrl: checkoutProps.edxSessionUrl,
26
26
  geolocationUrl: checkoutProps.geolocationUrl,
27
27
  complianceCheckUrl,
28
+ disableComplianceCheck,
28
29
  learnerDashboardUrl,
29
30
  });
30
31
  if (gateStatus === 'loading') {
@@ -1 +1 @@
1
- {"version":3,"file":"CheckoutGate.js","sourceRoot":"","sources":["../../../src/components/CheckoutGate/CheckoutGate.tsx"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,QAAQ,MAAM,sBAAsB,CAAC;AAC5C,OAAO,uBAAuB,MAAM,oDAAoD,CAAC;AAEzF,OAAO,QAAQ,MAAM,YAAY,CAAC;AAWlC,MAAM,YAAY,GAAG,CAAC,EAKF,EAAE,EAAE;QALF,EACpB,mBAAmB,EACnB,OAAO,GAAG,GAAG,EACb,kBAAkB,OAEA,EADf,aAAa,cAJI,wDAKrB,CADiB;IAEhB,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC;IACpC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,eAAe,CAAC;QAC/D,MAAM,EAAE,aAAa,CAAC,MAAM;QAC5B,aAAa,EAAE,aAAa,CAAC,aAAa;QAC1C,cAAc,EAAE,aAAa,CAAC,cAAc;QAC5C,kBAAkB;QAClB,mBAAmB;KACpB,CAAC,CAAC;IAEH,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,CACL,cAAK,SAAS,EAAC,mBAAmB,EAAC,IAAI,EAAC,QAAQ,eAAW,QAAQ,YACjE,KAAC,OAAO,IAAC,SAAS,EAAC,QAAQ,EAAC,gBAAgB,EAAC,6BAAwB,GAAG,GACpE,CACP,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;QAC3B,OAAO,CACL,MAAC,KAAK,IAAC,OAAO,EAAC,QAAQ,EAAC,IAAI,EAAE,SAAS,aACpC,WAAW,aAAX,WAAW,cAAX,WAAW,GACT,aAAa,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,GAAG,EAClD,mBAAmB,IAAI,CACtB,YAAG,IAAI,EAAE,mBAAmB,EAAE,SAAS,EAAC,YAAY,6CAEhD,CACL,IACK,CACT,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,CACL,4BACE,KAAC,uBAAuB,IAAC,MAAM,QAAC,OAAO,EAAE,OAAO,GAAI,GACnD,CACJ,CAAC;IACJ,CAAC;IAED,OAAO,CACL,KAAC,QAAQ,oBACH,aAAa,IACjB,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,OAAO,EAChB,eAAe,EAAE,mBAAmB,IACpC,CACH,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,YAAY,CAAC","sourcesContent":["import { Alert, Spinner } from '@openedx/paragon';\nimport { Error as ErrorIcon } from '@openedx/paragon/icons';\nimport { useIntl } from '@openedx/frontend-base';\nimport { useCheckoutGate } from '../../data/hooks/useCheckoutGate';\nimport Checkout from '../Checkout/Checkout';\nimport CountryUnavailableModal from '../CountryUnavailableModal/CountryUnavailableModal';\nimport type { CheckoutProps } from '../Checkout/Checkout';\nimport messages from './Messages';\n\nexport interface CheckoutGateProps extends CheckoutProps {\n /** URL linked in session-error recovery messaging. */\n learnerDashboardUrl?: string,\n /** Homepage URL for the country-unavailable modal CTA. */\n homeUrl?: string,\n /** ALC-307 compliance-check endpoint — decides whether the learner is embargoed. */\n complianceCheckUrl?: string,\n}\n\nconst CheckoutGate = ({\n learnerDashboardUrl,\n homeUrl = '/',\n complianceCheckUrl,\n ...checkoutProps\n}: CheckoutGateProps) => {\n const { formatMessage } = useIntl();\n const { gateStatus, userCountry, gateMessage } = useCheckoutGate({\n apiUrl: checkoutProps.apiUrl,\n edxSessionUrl: checkoutProps.edxSessionUrl,\n geolocationUrl: checkoutProps.geolocationUrl,\n complianceCheckUrl,\n learnerDashboardUrl,\n });\n\n if (gateStatus === 'loading') {\n return (\n <div className=\"processing-screen\" role=\"status\" aria-live=\"polite\">\n <Spinner animation=\"border\" screenReaderText=\"Checking your account…\" />\n </div>\n );\n }\n\n if (gateStatus === 'error') {\n return (\n <Alert variant=\"danger\" icon={ErrorIcon}>\n {gateMessage\n ?? formatMessage(messages.defaultErrorMessage)}{' '}\n {learnerDashboardUrl && (\n <a href={learnerDashboardUrl} className=\"alert-link\">\n Go to your learner dashboard\n </a>\n )}\n </Alert>\n );\n }\n\n if (gateStatus === 'blocked') {\n return (\n <>\n <CountryUnavailableModal isOpen homeUrl={homeUrl} />\n </>\n );\n }\n\n return (\n <Checkout\n {...checkoutProps}\n userCountry={userCountry}\n homeUrl={homeUrl}\n orderHistoryUrl={learnerDashboardUrl}\n />\n );\n};\n\nexport default CheckoutGate;\n"]}
1
+ {"version":3,"file":"CheckoutGate.js","sourceRoot":"","sources":["../../../src/components/CheckoutGate/CheckoutGate.tsx"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,QAAQ,MAAM,sBAAsB,CAAC;AAC5C,OAAO,uBAAuB,MAAM,oDAAoD,CAAC;AAEzF,OAAO,QAAQ,MAAM,YAAY,CAAC;AAalC,MAAM,YAAY,GAAG,CAAC,EAMF,EAAE,EAAE;QANF,EACpB,mBAAmB,EACnB,OAAO,GAAG,GAAG,EACb,kBAAkB,EAClB,sBAAsB,OAEJ,EADf,aAAa,cALI,kFAMrB,CADiB;IAEhB,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC;IACpC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,eAAe,CAAC;QAC/D,MAAM,EAAE,aAAa,CAAC,MAAM;QAC5B,aAAa,EAAE,aAAa,CAAC,aAAa;QAC1C,cAAc,EAAE,aAAa,CAAC,cAAc;QAC5C,kBAAkB;QAClB,sBAAsB;QACtB,mBAAmB;KACpB,CAAC,CAAC;IAEH,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,CACL,cAAK,SAAS,EAAC,mBAAmB,EAAC,IAAI,EAAC,QAAQ,eAAW,QAAQ,YACjE,KAAC,OAAO,IAAC,SAAS,EAAC,QAAQ,EAAC,gBAAgB,EAAC,6BAAwB,GAAG,GACpE,CACP,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;QAC3B,OAAO,CACL,MAAC,KAAK,IAAC,OAAO,EAAC,QAAQ,EAAC,IAAI,EAAE,SAAS,aACpC,WAAW,aAAX,WAAW,cAAX,WAAW,GACT,aAAa,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,GAAG,EAClD,mBAAmB,IAAI,CACtB,YAAG,IAAI,EAAE,mBAAmB,EAAE,SAAS,EAAC,YAAY,6CAEhD,CACL,IACK,CACT,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,CACL,4BACE,KAAC,uBAAuB,IAAC,MAAM,QAAC,OAAO,EAAE,OAAO,GAAI,GACnD,CACJ,CAAC;IACJ,CAAC;IAED,OAAO,CACL,KAAC,QAAQ,oBACH,aAAa,IACjB,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,OAAO,EAChB,eAAe,EAAE,mBAAmB,IACpC,CACH,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,YAAY,CAAC","sourcesContent":["import { Alert, Spinner } from '@openedx/paragon';\nimport { Error as ErrorIcon } from '@openedx/paragon/icons';\nimport { useIntl } from '@openedx/frontend-base';\nimport { useCheckoutGate } from '../../data/hooks/useCheckoutGate';\nimport Checkout from '../Checkout/Checkout';\nimport CountryUnavailableModal from '../CountryUnavailableModal/CountryUnavailableModal';\nimport type { CheckoutProps } from '../Checkout/Checkout';\nimport messages from './Messages';\n\nexport interface CheckoutGateProps extends CheckoutProps {\n /** URL linked in session-error recovery messaging. */\n learnerDashboardUrl?: string,\n /** Homepage URL for the country-unavailable modal CTA. */\n homeUrl?: string,\n /** ALC-307 compliance-check endpoint — decides whether the learner is embargoed. */\n complianceCheckUrl?: string,\n /** When true, skip the compliance-check request. */\n disableComplianceCheck?: boolean,\n}\n\nconst CheckoutGate = ({\n learnerDashboardUrl,\n homeUrl = '/',\n complianceCheckUrl,\n disableComplianceCheck,\n ...checkoutProps\n}: CheckoutGateProps) => {\n const { formatMessage } = useIntl();\n const { gateStatus, userCountry, gateMessage } = useCheckoutGate({\n apiUrl: checkoutProps.apiUrl,\n edxSessionUrl: checkoutProps.edxSessionUrl,\n geolocationUrl: checkoutProps.geolocationUrl,\n complianceCheckUrl,\n disableComplianceCheck,\n learnerDashboardUrl,\n });\n\n if (gateStatus === 'loading') {\n return (\n <div className=\"processing-screen\" role=\"status\" aria-live=\"polite\">\n <Spinner animation=\"border\" screenReaderText=\"Checking your account…\" />\n </div>\n );\n }\n\n if (gateStatus === 'error') {\n return (\n <Alert variant=\"danger\" icon={ErrorIcon}>\n {gateMessage\n ?? formatMessage(messages.defaultErrorMessage)}{' '}\n {learnerDashboardUrl && (\n <a href={learnerDashboardUrl} className=\"alert-link\">\n Go to your learner dashboard\n </a>\n )}\n </Alert>\n );\n }\n\n if (gateStatus === 'blocked') {\n return (\n <>\n <CountryUnavailableModal isOpen homeUrl={homeUrl} />\n </>\n );\n }\n\n return (\n <Checkout\n {...checkoutProps}\n userCountry={userCountry}\n homeUrl={homeUrl}\n orderHistoryUrl={learnerDashboardUrl}\n />\n );\n};\n\nexport default CheckoutGate;\n"]}
@@ -68,10 +68,8 @@ export interface UseAlacarteCheckoutResult extends AlacartePhaseState {
68
68
  *
69
69
  * NOTE: course_run_key values look like "course-v1:HarvardX+CS50+X" — nuqs
70
70
  * decodes query values the standards-compliant way (literal `+` -> space),
71
- * same as native URLSearchParams. This assumes whoever generates links into
72
- * this page percent-encodes `+` as %2B. Verify this in practice; see the plan
73
- * doc for the fallback if it's ever violated (drop nuqs for course_run_key
74
- * specifically).
71
+ * same as native URLSearchParams. runKey is therefore read from the raw query
72
+ * string via getCourseRunKeyFromUrl(), which preserves literal `+`.
75
73
  */
76
74
  export declare function useProductSelector(): ProductSelector;
77
75
  /** Reads ?discount_code= — applied to the checkout right after it's created. */
@@ -109,6 +107,11 @@ export interface DeriveAlacartePhaseInput {
109
107
  /** Latest successful manual update (coupon / acceptPrice / terms). Wins over
110
108
  * select + URL coupon when present. */
111
109
  checkoutOverride?: AlacarteCheckout | null;
110
+ /** Course-runs lookup for a course selector. Empty `elements` is notFound. */
111
+ courseRunLookup?: {
112
+ pending: boolean;
113
+ notFound: boolean;
114
+ };
112
115
  }
113
116
  /**
114
117
  * Pure decision function — no hooks, no React Query/nuqs types beyond plain
@@ -30,7 +30,8 @@ import { placeAlacarteOrder, toAlacarteBillingAddress, } from '../../utils/alaca
30
30
  import { AlacartePlaceOrderError } from '../../utils/placeOrderErrors';
31
31
  import { CardValidationError } from '../../utils/stripeCard';
32
32
  import { useSubscriptionCourseKeyQuery, useViaxSessionQuery } from './useCheckoutQueries';
33
- import { lmsOriginFromSessionUrl } from '../../utils/provision';
33
+ import { lmsOriginFromSessionUrl, isCourseNotFoundError } from '../../utils/provision';
34
+ import { getCourseRunKeyFromUrl } from '../../utils/url';
34
35
  import { useOwnedProductQuery, useAlacarteCheckoutQuery, useSelectProductMutation, useProductDetailQuery, useUpdateCheckoutMutation, usePlacedOrderQuery, useOrderDatesQuery, } from './useAlacarteQueries';
35
36
  /**
36
37
  * Read the product selector from the URL: course_uid+course_run_key, or
@@ -40,13 +41,12 @@ import { useOwnedProductQuery, useAlacarteCheckoutQuery, useSelectProductMutatio
40
41
  *
41
42
  * NOTE: course_run_key values look like "course-v1:HarvardX+CS50+X" — nuqs
42
43
  * decodes query values the standards-compliant way (literal `+` -> space),
43
- * same as native URLSearchParams. This assumes whoever generates links into
44
- * this page percent-encodes `+` as %2B. Verify this in practice; see the plan
45
- * doc for the fallback if it's ever violated (drop nuqs for course_run_key
46
- * specifically).
44
+ * same as native URLSearchParams. runKey is therefore read from the raw query
45
+ * string via getCourseRunKeyFromUrl(), which preserves literal `+`.
47
46
  */
48
47
  export function useProductSelector() {
49
- const [{ courseUid, runKey, programUid }] = useQueryStates({
48
+ var _a;
49
+ const [{ courseUid, runKey: nuqsRunKey, programUid }] = useQueryStates({
50
50
  courseUid: parseAsString,
51
51
  runKey: parseAsString,
52
52
  programUid: parseAsString,
@@ -57,6 +57,7 @@ export function useProductSelector() {
57
57
  programUid: 'program_uid',
58
58
  },
59
59
  });
60
+ const runKey = nuqsRunKey ? ((_a = getCourseRunKeyFromUrl()) !== null && _a !== void 0 ? _a : nuqsRunKey) : null;
60
61
  return useMemo(() => {
61
62
  const hasCourse = !!courseUid || !!runKey;
62
63
  const hasProgram = !!programUid;
@@ -122,7 +123,7 @@ function buildLineFromOwnedProduct(product) {
122
123
  */
123
124
  export function deriveAlacartePhase(input) {
124
125
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
125
- const { selector, sessionReady, sessionIsError, sessionErrorMessage, ownedQuery, selectMutation, checkoutQuery, productDetail, couponMutation, checkoutOverride = null, urlCouponPending: urlCouponPendingProp = false, } = input;
126
+ const { selector, sessionReady, sessionIsError, sessionErrorMessage, ownedQuery, selectMutation, checkoutQuery, productDetail, couponMutation, checkoutOverride = null, urlCouponPending: urlCouponPendingProp = false, courseRunLookup = { pending: false, notFound: false }, } = input;
126
127
  const ownedProductName = (_c = (_b = (_a = ownedQuery.data) === null || _a === void 0 ? void 0 : _a.product) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : null;
127
128
  const empty = {
128
129
  selector,
@@ -158,7 +159,10 @@ export function deriveAlacartePhase(input) {
158
159
  }
159
160
  const hasSelector = selector.kind === 'course' || selector.kind === 'program';
160
161
  if (hasSelector) {
161
- if (!sessionReady || ownedQuery.isLoading) {
162
+ if (selector.kind === 'course' && courseRunLookup.notFound) {
163
+ return Object.assign(Object.assign({ phase: 'error' }, empty), { error: 'This course could not be found.' });
164
+ }
165
+ if (!sessionReady || ownedQuery.isLoading || courseRunLookup.pending) {
162
166
  return Object.assign({ phase: 'loading' }, empty);
163
167
  }
164
168
  if (ownedQuery.isError) {
@@ -254,13 +258,24 @@ export function useAlacarteCheckout(options) {
254
258
  const isOwned = ((_a = ownedQuery.data) === null || _a === void 0 ? void 0 : _a.ok) === true && ((_b = ownedQuery.data.product) === null || _b === void 0 ? void 0 : _b.status) === 'full';
255
259
  const selectMutation = useSelectProductMutation(client);
256
260
  const { isIdle: selectIsIdle, mutate: selectMutate, reset: selectReset, } = selectMutation;
261
+ const courseRunKey = selector.kind === 'course' ? selector.runKey : null;
262
+ const lmsBaseUrl = useMemo(() => lmsOriginFromSessionUrl(edxSessionUrl), [edxSessionUrl]);
263
+ const courseLookupEnabled = selector.kind === 'course' && !!lmsBaseUrl && !!courseRunKey;
264
+ const courseKeyQuery = useSubscriptionCourseKeyQuery(lmsBaseUrl, courseRunKey);
265
+ const courseKey = (_c = courseKeyQuery.data) !== null && _c !== void 0 ? _c : null;
266
+ const courseNotFound = courseLookupEnabled
267
+ && courseKeyQuery.isError
268
+ && isCourseNotFoundError(courseKeyQuery.error);
257
269
  // Mutations aren't called during render — fire once the owned-products
258
270
  // query resolves (regardless of result) so we always get checkout/line data.
271
+ // A course is not selected until the course-runs lookup returns a course.
259
272
  // Pass viewedPrice from tOwnedProducts.amountDue (ALC-159) when available.
260
273
  useEffect(() => {
261
274
  var _a, _b, _c;
262
275
  if (!hasSelector || ownedQuery.isLoading || ownedQuery.isError)
263
276
  return;
277
+ if (selector.kind === 'course' && !courseKey)
278
+ return;
264
279
  if (!selectIsIdle)
265
280
  return;
266
281
  const amountDue = (_c = (_b = (_a = ownedQuery.data) === null || _a === void 0 ? void 0 : _a.product) === null || _b === void 0 ? void 0 : _b.price) === null || _c === void 0 ? void 0 : _c.amountDue;
@@ -272,15 +287,12 @@ export function useAlacarteCheckout(options) {
272
287
  hasSelector,
273
288
  ownedQuery.isLoading,
274
289
  ownedQuery.isError,
275
- (_e = (_d = (_c = ownedQuery.data) === null || _c === void 0 ? void 0 : _c.product) === null || _d === void 0 ? void 0 : _d.price) === null || _e === void 0 ? void 0 : _e.amountDue,
290
+ (_f = (_e = (_d = ownedQuery.data) === null || _d === void 0 ? void 0 : _d.product) === null || _e === void 0 ? void 0 : _e.price) === null || _f === void 0 ? void 0 : _f.amountDue,
276
291
  selector,
292
+ courseKey,
277
293
  selectIsIdle,
278
294
  selectMutate,
279
295
  ]);
280
- const courseRunKey = selector.kind === 'course' ? selector.runKey : null;
281
- const lmsBaseUrl = useMemo(() => lmsOriginFromSessionUrl(edxSessionUrl), [edxSessionUrl]);
282
- const courseKeyQuery = useSubscriptionCourseKeyQuery(lmsBaseUrl, courseRunKey);
283
- const courseKey = (_f = courseKeyQuery.data) !== null && _f !== void 0 ? _f : null;
284
296
  const productDetailEnabled = hasSelector && sessionReady && !ownedQuery.isLoading
285
297
  && (selector.kind !== 'course' || !!courseKey);
286
298
  const productDetailQuery = useProductDetailQuery(client, productDetailEnabled, selector, courseKey);
@@ -385,6 +397,10 @@ export function useAlacarteCheckout(options) {
385
397
  data: checkoutQuery.data,
386
398
  },
387
399
  productDetail: (_j = productDetailQuery.data) !== null && _j !== void 0 ? _j : null,
400
+ courseRunLookup: {
401
+ pending: courseLookupEnabled && courseKeyQuery.isLoading,
402
+ notFound: courseNotFound,
403
+ },
388
404
  couponMutation: {
389
405
  isIdle: urlCouponMutation.isIdle,
390
406
  isPending: urlCouponMutation.isPending,
@@ -1 +1 @@
1
- {"version":3,"file":"useAlacarteCheckout.js","sourceRoot":"","sources":["../../../src/data/hooks/useAlacarteCheckout.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * data/hooks/useAlacarteCheckout.ts — page-level orchestration for the à la\n * carte checkout flow:\n *\n * 1. Read a product selector (course or program) from the URL via nuqs.\n * 2. If a product is selected: check ownership (tOwnedProducts). Already\n * owned -> 'alreadyOwned'. Otherwise select it into the checkout\n * (tCheckoutSelect) and fetch its display details in parallel.\n * 3. If no product is selected: look for an existing open checkout\n * (tCheckout). Found -> 'ready'. Not found -> 'noActiveCheckout'.\n * 4. Coupon apply/remove and payment prep via tCheckoutUpdate.\n *\n * See /alacarte-checkout-api.md and /alacarte-owned-products-api.md at the\n * repo root for the underlying API contract.\n */\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { useQueryStates, useQueryState, parseAsString } from 'nuqs';\nimport { createAlacarteCheckoutClient } from '../../utils/alacarteCheckout';\nimport { getCouponErrorMessage, getCouponRecheckMessage } from '../../utils/couponErrors';\nimport {\n placeAlacarteOrder,\n toAlacarteBillingAddress,\n} from '../../utils/alacartePayment';\nimport { AlacartePlaceOrderError } from '../../utils/placeOrderErrors';\nimport { CardValidationError } from '../../utils/stripeCard';\nimport { useSubscriptionCourseKeyQuery, useViaxSessionQuery } from './useCheckoutQueries';\nimport { lmsOriginFromSessionUrl } from '../../utils/provision';\nimport {\n useOwnedProductQuery, useAlacarteCheckoutQuery, useSelectProductMutation, useProductDetailQuery,\n useUpdateCheckoutMutation, usePlacedOrderQuery, useOrderDatesQuery,\n} from './useAlacarteQueries';\nimport type {\n AlacarteCheckout, AlacarteCheckoutResult, AlacarteLine, AlacarteMoney, AlacartePaymentDecline,\n AlacartePriceChanged, OwnedProduct, OwnedProductResult, PlacedOrder, ProductDetail, ProductSelector,\n} from '../../types/alacarte';\nimport type { BillingInfo } from '../../types';\n\nexport type AlacartePhase = 'loading' | 'alreadyOwned' | 'noActiveCheckout' | 'notPurchasable' | 'ready' | 'error';\n\nexport type AlacarteNoticeMessageId = 'alreadyOwnedCourse' | 'alreadyOwnedProgram' | 'noActiveCheckout';\n\n/** Pure phase decision output — no action callbacks. */\nexport interface AlacartePhaseState {\n phase: AlacartePhase,\n noticeMessageId?: AlacarteNoticeMessageId,\n selector: ProductSelector,\n checkout: AlacarteCheckout | null,\n line: AlacarteLine | null,\n productDetail: ProductDetail | null,\n error: string | null,\n priceChanged: AlacartePriceChanged | null,\n priceAccepted: boolean,\n /** True when the learner already owns this product. The checkout data may\n * still be populated so the UI can render the full page under an overlay. */\n isAlreadyOwned: boolean,\n /** Product name from the owned-products query — used as a fallback when the\n * checkout line (which normally carries the name) is not available. */\n ownedProductName: string | null,\n}\n\nexport interface UseAlacarteCheckoutResult extends AlacartePhaseState {\n couponError: string | null,\n couponApplying: boolean,\n applyCoupon: (code: string) => void,\n removeCoupon: () => void,\n clearCouponError: () => void,\n /** Code of the coupon just removed, set only once the removal round-trip\n * completes — kept in sync with when the discount actually leaves the line. */\n removedCouponCode: string | null,\n clearRemovedCouponCode: () => void,\n placingOrder: boolean,\n placeOrderError: string | null,\n /**\n * Accepts price (if needed) + terms, calls tCheckoutPlaceOrder with billing,\n * confirms the card via Stripe.js, then sets ?order_bi_id= to poll tPlacedOrder.\n * Fire-and-forget — errors go to placeOrderError state.\n */\n placeOrder: (opts: {\n billing: BillingInfo,\n confirmCardPayment: (clientSecret: string) => Promise<void>,\n }) => void,\n /**\n * Same as placeOrder but returns a Promise — used by ExpressCheckout\n * so the wallet sheet can await the result and call ev.complete().\n */\n placeOrderAsync: (opts: {\n billing: BillingInfo,\n confirmCardPayment: (clientSecret: string) => Promise<void>,\n }) => Promise<void>,\n clearPlaceOrderError: () => void,\n /** Decline details from the last card attempt on this checkout, if any. */\n paymentDecline: AlacartePaymentDecline | null,\n /** When ?order_bi_id= is present, the placed order (or null while polling). */\n placedOrder: PlacedOrder | null,\n awaitingPlacedOrder: boolean,\n placedOrderError: string | null,\n /** ISO timestamp the order was placed (tPlacedAt, falling back to\n * biCreatedAt); null while the order-dates query hasn't resolved yet. */\n placedOrderPlacedAt: string | null,\n}\n\n/**\n * Read the product selector from the URL: course_uid+course_run_key, or\n * program_uid, or neither. Both course params must be present together; if a\n * course param and a program param are both present, that's\n * CONFLICTING_SELECTION.\n *\n * NOTE: course_run_key values look like \"course-v1:HarvardX+CS50+X\" — nuqs\n * decodes query values the standards-compliant way (literal `+` -> space),\n * same as native URLSearchParams. This assumes whoever generates links into\n * this page percent-encodes `+` as %2B. Verify this in practice; see the plan\n * doc for the fallback if it's ever violated (drop nuqs for course_run_key\n * specifically).\n */\nexport function useProductSelector(): ProductSelector {\n const [{ courseUid, runKey, programUid }] = useQueryStates({\n courseUid: parseAsString,\n runKey: parseAsString,\n programUid: parseAsString,\n }, {\n urlKeys: {\n courseUid: 'course_uid',\n runKey: 'course_run_key',\n programUid: 'program_uid',\n },\n });\n\n return useMemo<ProductSelector>(() => {\n const hasCourse = !!courseUid || !!runKey;\n const hasProgram = !!programUid;\n if (hasCourse && hasProgram) return { kind: 'invalid' };\n if (courseUid && runKey) return { kind: 'course', courseUid, runKey };\n if (programUid) return { kind: 'program', programUid };\n return { kind: 'none' };\n }, [courseUid, runKey, programUid]);\n}\n\n/** Reads ?discount_code= — applied to the checkout right after it's created. */\nexport function useDiscountCode(): string | null {\n const [discountCode] = useQueryState('discount_code', parseAsString);\n return discountCode;\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : 'Unknown error';\n}\n\n/**\n * Build a synthetic AlacarteLine from the owned-product pricing data so the\n * checkout overlay can show subtotal / deduction / total even when the backend\n * blocks tCheckoutSelect and returns no checkout object.\n */\nfunction buildLineFromOwnedProduct(product: OwnedProduct): AlacarteLine | null {\n if (!product.price) return null;\n const { full, deduction, amountDue, currency } = product.price;\n const toMoney = (amount: number): AlacarteMoney => ({ amount, currency });\n\n if (product.kind === 'program') {\n return {\n biiId: '',\n kind: 'program',\n programId: product.productId,\n programName: product.name,\n price: toMoney(full),\n deduction: deduction ? toMoney(deduction) : null,\n ownedCourses: product.ownedCourses.map((c) => ({\n courseId: c.courseId, name: c.name, via: c.via,\n })),\n discount: null,\n amountDue: toMoney(amountDue),\n billingAddressSet: false,\n };\n }\n\n return {\n biiId: '',\n kind: 'course',\n courseName: product.name,\n courseUid: product.productId,\n courseRunKey: '',\n seatType: 'verified',\n price: toMoney(full),\n discount: null,\n amountDue: toMoney(amountDue),\n billingAddressSet: false,\n };\n}\n\ninterface QueryLikeState<T> {\n isLoading: boolean,\n isError: boolean,\n error?: unknown,\n data?: T,\n}\n\ninterface MutationLikeState<T> {\n isIdle: boolean,\n isPending: boolean,\n isError: boolean,\n error?: unknown,\n data?: T,\n}\n\nexport interface DeriveAlacartePhaseInput {\n selector: ProductSelector,\n sessionReady: boolean,\n sessionIsError: boolean,\n sessionErrorMessage?: string,\n ownedQuery: QueryLikeState<OwnedProductResult>,\n selectMutation: MutationLikeState<AlacarteCheckoutResult>,\n checkoutQuery: QueryLikeState<AlacarteCheckoutResult>,\n productDetail: ProductDetail | null,\n /** Coupon (?discount_code=) applied right after the checkout is created —\n * when it succeeds, its checkout (with the coupon's discount reflected)\n * is shown in place of the pre-coupon one from selectMutation. */\n couponMutation?: MutationLikeState<AlacarteCheckoutResult>,\n /** True when a URL discount code still needs to be applied — the phase\n * stays 'loading' until the coupon mutation resolves so the user never sees\n * the pre-discount price flash. */\n urlCouponPending?: boolean,\n /** Latest successful manual update (coupon / acceptPrice / terms). Wins over\n * select + URL coupon when present. */\n checkoutOverride?: AlacarteCheckout | null,\n}\n\n/**\n * Pure decision function — no hooks, no React Query/nuqs types beyond plain\n * data — so every branch combination can be unit-tested directly.\n */\nexport function deriveAlacartePhase(input: DeriveAlacartePhaseInput): AlacartePhaseState {\n const {\n selector, sessionReady, sessionIsError, sessionErrorMessage,\n ownedQuery, selectMutation, checkoutQuery, productDetail, couponMutation,\n checkoutOverride = null, urlCouponPending: urlCouponPendingProp = false,\n } = input;\n\n const ownedProductName = ownedQuery.data?.product?.name ?? null;\n\n const empty: Omit<AlacartePhaseState, 'phase'> = {\n selector,\n checkout: null,\n line: null,\n productDetail: null,\n error: null,\n priceChanged: null,\n priceAccepted: false,\n isAlreadyOwned: false,\n ownedProductName: null,\n };\n\n const withCheckout = (\n checkout: AlacarteCheckout | null,\n priceChanged: AlacartePriceChanged | null = null,\n isAlreadyOwned = false,\n ): AlacartePhaseState => ({\n phase: isAlreadyOwned ? 'alreadyOwned' : 'ready',\n selector,\n checkout,\n line: checkout?.line ?? null,\n productDetail,\n error: null,\n priceChanged: priceChanged ?? null,\n priceAccepted: checkout?.priceAccepted === true,\n isAlreadyOwned,\n ownedProductName: isAlreadyOwned ? ownedProductName : null,\n });\n\n if (selector.kind === 'invalid') {\n return { phase: 'error', ...empty, error: 'CONFLICTING_SELECTION' };\n }\n if (sessionIsError) {\n return { phase: 'error', ...empty, error: sessionErrorMessage ?? 'Session error' };\n }\n\n const hasSelector = selector.kind === 'course' || selector.kind === 'program';\n\n if (hasSelector) {\n if (!sessionReady || ownedQuery.isLoading) {\n return { phase: 'loading', ...empty };\n }\n if (ownedQuery.isError) {\n return { phase: 'error', ...empty, error: errorMessage(ownedQuery.error) };\n }\n\n const isOwned = ownedQuery.data?.ok === true && ownedQuery.data.product?.status === 'full';\n\n if (selectMutation.isIdle || selectMutation.isPending) {\n return { phase: 'loading', ...empty };\n }\n if (selectMutation.isError) {\n return { phase: 'error', ...empty, error: errorMessage(selectMutation.error) };\n }\n if (selectMutation.data && !selectMutation.data.ok) {\n // The backend may block ALREADY_OWNED at select time. When the\n // blocked response still includes checkout data (line, pricing), use\n // it so the overlay page shows the real totals. Fall back to the\n // standalone tCheckout query, then to an empty state.\n if (selectMutation.data.blocked?.reason === 'ALREADY_OWNED') {\n const blockedCheckout = selectMutation.data.checkout\n ?? (checkoutQuery.data?.ok ? checkoutQuery.data.checkout : null);\n if (blockedCheckout) {\n return withCheckout(blockedCheckout, selectMutation.data.priceChanged ?? null, true);\n }\n // Build a synthetic line from the owned-product pricing so the\n // overlay can show subtotal / deduction / total.\n const ownedProduct = ownedQuery.data?.product;\n const syntheticLine = ownedProduct ? buildLineFromOwnedProduct(ownedProduct) : null;\n return {\n phase: 'alreadyOwned',\n noticeMessageId: selectMutation.data.blocked.kind === 'course' ? 'alreadyOwnedCourse' : 'alreadyOwnedProgram',\n ...empty,\n line: syntheticLine,\n productDetail,\n isAlreadyOwned: true,\n ownedProductName,\n };\n }\n if (selectMutation.data.blocked?.reason === 'NOT_PURCHASABLE') {\n return {\n phase: 'notPurchasable',\n ...empty,\n productDetail,\n error: selectMutation.data.blocked.kind === 'program'\n ? 'This program is not eligible for checkout.'\n : 'This course is not eligible for checkout.',\n };\n }\n const selectError = selectMutation.data.error;\n if (selectError === 'COURSE_NOT_FOUND' || selectError === 'PRODUCT_NOT_FOUND') {\n return {\n phase: 'error',\n ...empty,\n error: 'This course could not be found.',\n };\n }\n if (selectError === 'PROGRAM_NOT_FOUND') {\n return {\n phase: 'error',\n ...empty,\n error: 'This program could not be found.',\n };\n }\n const blockedDetail = selectMutation.data.blocked?.detail;\n return {\n phase: 'error',\n ...empty,\n error: blockedDetail ?? selectError ?? 'unknown',\n };\n }\n\n // When a URL discount code still needs to be applied, stay in 'loading'\n // so the user never sees the pre-discount price flash.\n if (urlCouponPendingProp && !checkoutOverride) {\n return { phase: 'loading', ...empty };\n }\n\n // Once the coupon-apply (?discount_code=) mutation succeeds, its checkout\n // (with the discount reflected) supersedes the pre-coupon one. Manual\n // updates (override) win over both.\n const finalCheckout = checkoutOverride\n ?? (couponMutation?.data?.ok\n ? couponMutation.data.checkout\n : selectMutation.data?.checkout ?? null);\n\n // When select succeeds but the owned-products query says the learner\n // already has this product, show the full checkout under an overlay.\n return withCheckout(\n finalCheckout,\n selectMutation.data?.priceChanged\n ?? (couponMutation?.data?.ok ? couponMutation.data.priceChanged : undefined)\n ?? null,\n isOwned,\n );\n }\n\n // No selector: fall back to the learner's existing open checkout, if any.\n if (!sessionReady || checkoutQuery.isLoading) {\n return { phase: 'loading', ...empty };\n }\n if (checkoutQuery.isError) {\n return { phase: 'error', ...empty, error: errorMessage(checkoutQuery.error) };\n }\n if (checkoutOverride || checkoutQuery.data?.checkout) {\n const checkout = checkoutOverride ?? checkoutQuery.data!.checkout;\n return withCheckout(checkout, checkoutQuery.data?.priceChanged ?? null);\n }\n\n return { phase: 'noActiveCheckout', noticeMessageId: 'noActiveCheckout', ...empty, isAlreadyOwned: false, ownedProductName: null };\n}\n\nexport function useAlacarteCheckout(\n options: { apiUrl?: string, edxSessionUrl?: string },\n): UseAlacarteCheckoutResult {\n const { apiUrl, edxSessionUrl } = options;\n const selector = useProductSelector();\n const discountCode = useDiscountCode();\n const [orderBiId, setOrderBiId] = useQueryState('order_bi_id', parseAsString);\n\n const client = useMemo(\n () => (apiUrl ? createAlacarteCheckoutClient({ apiUrl }) : null),\n [apiUrl],\n );\n\n // Reuses the same query key as useCheckout's session exchange — React\n // Query dedupes the network call regardless of how many hooks read it.\n const sessionQuery = useViaxSessionQuery(edxSessionUrl ?? null);\n const sessionReady = !!sessionQuery.data;\n\n useEffect(() => {\n if (sessionQuery.data && client) {\n client.setToken(sessionQuery.data.viaxToken);\n }\n }, [sessionQuery.data, client]);\n\n const hasSelector = selector.kind === 'course' || selector.kind === 'program';\n const productId = selector.kind === 'course'\n ? selector.courseUid\n : selector.kind === 'program' ? selector.programUid : null;\n\n const ownedQuery = useOwnedProductQuery(client, sessionReady && hasSelector, productId);\n const isOwned = ownedQuery.data?.ok === true && ownedQuery.data.product?.status === 'full';\n\n const selectMutation = useSelectProductMutation(client);\n const {\n isIdle: selectIsIdle, mutate: selectMutate, reset: selectReset,\n } = selectMutation;\n\n // Mutations aren't called during render — fire once the owned-products\n // query resolves (regardless of result) so we always get checkout/line data.\n // Pass viewedPrice from tOwnedProducts.amountDue (ALC-159) when available.\n useEffect(() => {\n if (!hasSelector || ownedQuery.isLoading || ownedQuery.isError) return;\n if (!selectIsIdle) return;\n const amountDue = ownedQuery.data?.product?.price?.amountDue;\n selectMutate({\n selector,\n viewedPrice: typeof amountDue === 'number' ? amountDue : undefined,\n });\n }, [\n hasSelector,\n ownedQuery.isLoading,\n ownedQuery.isError,\n ownedQuery.data?.product?.price?.amountDue,\n selector,\n selectIsIdle,\n selectMutate,\n ]);\n\n const courseRunKey = selector.kind === 'course' ? selector.runKey : null;\n const lmsBaseUrl = useMemo(\n () => lmsOriginFromSessionUrl(edxSessionUrl),\n [edxSessionUrl],\n );\n const courseKeyQuery = useSubscriptionCourseKeyQuery(lmsBaseUrl, courseRunKey);\n const courseKey = courseKeyQuery.data ?? null;\n\n const productDetailEnabled = hasSelector && sessionReady && !ownedQuery.isLoading\n && (selector.kind !== 'course' || !!courseKey);\n const productDetailQuery = useProductDetailQuery(client, productDetailEnabled, selector, courseKey);\n\n // Run the checkout query when there's no selector (standard path) OR when\n // the product is already owned — after the select mutation is blocked with\n // ALREADY_OWNED the server may still have an open checkout with pricing data.\n const selectBlocked = !selectMutation.isIdle && !selectMutation.isPending\n && selectMutation.data && !selectMutation.data.ok;\n const checkoutQuery = useAlacarteCheckoutQuery(\n client,\n sessionReady && (!hasSelector || (isOwned && !!selectBlocked)),\n );\n\n // Apply ?discount_code= to the freshly-created checkout — fired once the\n // select mutation succeeds with a checkout that doesn't already carry it.\n const urlCouponMutation = useUpdateCheckoutMutation(client);\n const {\n isIdle: couponIsIdle, mutate: couponMutate, reset: urlCouponReset,\n } = urlCouponMutation;\n const createdCheckout = selectMutation.data?.ok ? selectMutation.data.checkout : null;\n\n useEffect(() => {\n if (!createdCheckout || !discountCode) return;\n if (createdCheckout.couponCode === discountCode) return;\n if (couponIsIdle) {\n couponMutate({ biId: createdCheckout.biId, couponCode: discountCode });\n }\n }, [createdCheckout, discountCode, couponIsIdle, couponMutate]);\n\n const [checkoutOverride, setCheckoutOverride] = useState<AlacarteCheckout | null>(null);\n const [couponError, setCouponError] = useState<string | null>(null);\n const [removedCouponCode, setRemovedCouponCode] = useState<string | null>(null);\n const [placeOrderError, setPlaceOrderError] = useState<string | null>(null);\n const [placingOrder, setPlacingOrder] = useState(false);\n // biId of a checkout that's locked (CART_PAYMENT_PENDING) from a prior\n // tCheckoutPlaceOrder call whose Stripe confirmation was rejected\n // client-side. The next attempt must skip tCheckoutUpdate (it would fail\n // with CHECKOUT_NOT_OPEN) and go straight to tCheckoutPlaceOrder again.\n const [cardRetryBiId, setCardRetryBiId] = useState<string | null>(null);\n\n // Reset local overrides and in-flight select/coupon when the product changes\n // so viewedPrice / couponRecheck run again for the new selection.\n useEffect(() => {\n setCheckoutOverride(null);\n setCouponError(null);\n setRemovedCouponCode(null);\n setPlaceOrderError(null);\n setCardRetryBiId(null);\n selectReset();\n urlCouponReset();\n }, [selector, selectReset, urlCouponReset]);\n\n // Surface couponRecheck from product switch (section 2 of the API doc).\n useEffect(() => {\n const result = selectMutation.data;\n if (!result?.ok) return;\n const message = getCouponRecheckMessage(\n result.couponRecheck,\n result.checkout?.line?.discountSource,\n );\n if (message) setCouponError(message);\n }, [selectMutation.data]);\n\n // Surface ?discount_code= apply failures (domain ok:false or transport error).\n useEffect(() => {\n if (!discountCode) return;\n if (urlCouponMutation.isIdle || urlCouponMutation.isPending) return;\n if (urlCouponMutation.isError) {\n setCouponError(errorMessage(urlCouponMutation.error));\n return;\n }\n const result = urlCouponMutation.data;\n if (result && !result.ok) {\n setCouponError(getCouponErrorMessage(result.error, discountCode));\n }\n }, [\n discountCode,\n urlCouponMutation.isIdle,\n urlCouponMutation.isPending,\n urlCouponMutation.isError,\n urlCouponMutation.error,\n urlCouponMutation.data,\n ]);\n\n const manualUpdateMutation = useUpdateCheckoutMutation(client);\n\n const placedOrderQuery = usePlacedOrderQuery(\n client,\n orderBiId,\n sessionReady && !!orderBiId,\n );\n\n const orderDatesQuery = useOrderDatesQuery(\n client,\n orderBiId,\n sessionReady && !!orderBiId,\n );\n\n const derived = deriveAlacartePhase({\n selector,\n sessionReady,\n sessionIsError: sessionQuery.isError,\n sessionErrorMessage: sessionQuery.error?.message,\n ownedQuery: {\n isLoading: ownedQuery.isLoading,\n isError: ownedQuery.isError,\n error: ownedQuery.error,\n data: ownedQuery.data,\n },\n selectMutation: {\n isIdle: selectMutation.isIdle,\n isPending: selectMutation.isPending,\n isError: selectMutation.isError,\n error: selectMutation.error,\n data: selectMutation.data,\n },\n checkoutQuery: {\n isLoading: checkoutQuery.isLoading,\n isError: checkoutQuery.isError,\n error: checkoutQuery.error,\n data: checkoutQuery.data,\n },\n productDetail: productDetailQuery.data ?? null,\n couponMutation: {\n isIdle: urlCouponMutation.isIdle,\n isPending: urlCouponMutation.isPending,\n isError: urlCouponMutation.isError,\n error: urlCouponMutation.error,\n data: urlCouponMutation.data,\n },\n checkoutOverride,\n // The URL coupon is pending only when the checkout exists, doesn't already\n // carry the code, and the mutation hasn't completed yet. When the backend\n // returns the coupon pre-applied (couponCode === discountCode) or when\n // there's no discount_code param at all, this is false from the start.\n urlCouponPending: !!discountCode\n && !!createdCheckout\n && createdCheckout.couponCode !== discountCode\n && (urlCouponMutation.isIdle || urlCouponMutation.isPending),\n });\n\n const applyCoupon = useCallback((code: string) => {\n const biId = derived.checkout?.biId;\n if (!biId || !client) return;\n const trimmed = code.trim();\n if (!trimmed) return;\n\n setCouponError(null);\n manualUpdateMutation.mutate(\n { biId, couponCode: trimmed },\n {\n onSuccess: (result) => {\n if (result.ok && result.checkout) {\n setCheckoutOverride(result.checkout);\n setCouponError(null);\n setRemovedCouponCode(null);\n } else {\n setCouponError(getCouponErrorMessage(result.error, trimmed));\n }\n },\n onError: (err) => {\n setCouponError(errorMessage(err));\n },\n },\n );\n }, [derived.checkout?.biId, client, manualUpdateMutation]);\n\n const removeCoupon = useCallback(() => {\n const currentCheckout = derived.checkout;\n if (!currentCheckout?.biId || !client) return;\n const removedCode = currentCheckout.couponCode?.trim() || null;\n\n setCouponError(null);\n manualUpdateMutation.mutate(\n { biId: currentCheckout.biId, couponCode: '' },\n {\n onSuccess: (result) => {\n if (!result.ok) {\n setCouponError(getCouponErrorMessage(result.error));\n return;\n }\n // The backend may return a checkout whose line still carries the\n // old discount/amountDue. Always patch the line to clear the\n // coupon so the cart summary reflects the removal immediately.\n const base = result.checkout ?? currentCheckout;\n const line = base.line;\n const patchedLine = line\n ? {\n ...line,\n discount: null,\n amountDue: line.price && line.kind === 'program' && 'deduction' in line && line.deduction\n ? { amount: line.price.amount - line.deduction.amount, currency: line.price.currency }\n : line.price,\n } as typeof line\n : null;\n setCheckoutOverride({\n ...base,\n couponCode: null,\n line: patchedLine,\n });\n setCouponError(null);\n if (removedCode) setRemovedCouponCode(removedCode);\n },\n onError: (err) => {\n setCouponError(errorMessage(err));\n },\n },\n );\n }, [derived.checkout, client, manualUpdateMutation]);\n\n const placeOrderCore = useCallback(async (opts: {\n billing: BillingInfo,\n confirmCardPayment: (clientSecret: string) => Promise<void>,\n }) => {\n const checkout = derived.checkout;\n if (!checkout || !client) throw new Error('Checkout not ready');\n\n setPlacingOrder(true);\n setPlaceOrderError(null);\n\n try {\n const { checkout: updated } = await placeAlacarteOrder({\n updateCheckout: (args) => client.updateCheckout(args),\n placeCheckoutOrder: (biId, billing) => client.placeCheckoutOrder(biId, billing),\n checkout,\n billing: toAlacarteBillingAddress(opts.billing),\n confirmCardPayment: opts.confirmCardPayment,\n skipPrepare: cardRetryBiId === checkout.biId,\n });\n\n setCardRetryBiId(null);\n setCheckoutOverride(updated);\n await setOrderBiId(updated.biId);\n } catch (err: unknown) {\n if (err instanceof CardValidationError) {\n // tCheckoutPlaceOrder already succeeded and locked the checkout\n // (CART_PAYMENT_PENDING); Stripe rejected the card before it ever\n // reached the backend. Next attempt must retry tCheckoutPlaceOrder\n // directly, not tCheckoutUpdate.\n setCardRetryBiId(checkout.biId);\n } else {\n setCardRetryBiId(null);\n }\n if (err instanceof AlacartePlaceOrderError && err.checkout) {\n setCheckoutOverride(err.checkout);\n }\n setPlaceOrderError(errorMessage(err));\n throw err;\n } finally {\n setPlacingOrder(false);\n }\n }, [derived.checkout, client, setOrderBiId, cardRetryBiId]);\n\n /** Fire-and-forget wrapper for card payments. */\n const placeOrder = useCallback((opts: {\n billing: BillingInfo,\n confirmCardPayment: (clientSecret: string) => Promise<void>,\n }) => {\n if (placingOrder) return;\n placeOrderCore(opts).catch(() => { /* error already in state */ });\n }, [placeOrderCore, placingOrder]);\n\n const placedOrder = placedOrderQuery.data?.ok ? placedOrderQuery.data.order : null;\n\n const dates = orderDatesQuery.data?.ok ? orderDatesQuery.data.dates : null;\n const placedOrderPlacedAt = dates?.tPlacedAt ?? dates?.biCreatedAt ?? null;\n\n const placedOrderError = (() => {\n if (!orderBiId) return null;\n if (\n placedOrderQuery.data\n && !placedOrderQuery.data.ok\n && placedOrderQuery.data.error !== 'NOT_PLACED'\n && placedOrderQuery.data.error !== 'ORDER_READ_FAILED'\n ) {\n return placedOrderQuery.data.error ?? 'ORDER_READ_FAILED';\n }\n return null;\n })();\n\n return {\n ...derived,\n couponError,\n couponApplying: manualUpdateMutation.isPending,\n applyCoupon,\n removeCoupon,\n clearCouponError: () => setCouponError(null),\n removedCouponCode,\n clearRemovedCouponCode: () => setRemovedCouponCode(null),\n placingOrder,\n placeOrderError,\n placeOrder,\n placeOrderAsync: placeOrderCore,\n clearPlaceOrderError: () => setPlaceOrderError(null),\n paymentDecline: derived.checkout?.paymentDecline ?? null,\n placedOrder,\n awaitingPlacedOrder: !!orderBiId && !placedOrder && !placedOrderError && (\n placedOrderQuery.isLoading\n || placedOrderQuery.isFetching\n || placedOrderQuery.data?.error === 'NOT_PLACED'\n || placedOrderQuery.data?.error === 'ORDER_READ_FAILED'\n || (placedOrderQuery.data?.ok === true && !placedOrderQuery.data.order)\n || !placedOrderQuery.data\n ),\n placedOrderError,\n placedOrderPlacedAt,\n };\n}\n\nexport default useAlacarteCheckout;\n"]}
1
+ {"version":3,"file":"useAlacarteCheckout.js","sourceRoot":"","sources":["../../../src/data/hooks/useAlacarteCheckout.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * data/hooks/useAlacarteCheckout.ts — page-level orchestration for the à la\n * carte checkout flow:\n *\n * 1. Read a product selector (course or program) from the URL via nuqs.\n * 2. If a product is selected: check ownership (tOwnedProducts). Already\n * owned -> 'alreadyOwned'. Otherwise select it into the checkout\n * (tCheckoutSelect) and fetch its display details in parallel.\n * 3. If no product is selected: look for an existing open checkout\n * (tCheckout). Found -> 'ready'. Not found -> 'noActiveCheckout'.\n * 4. Coupon apply/remove and payment prep via tCheckoutUpdate.\n *\n * See /alacarte-checkout-api.md and /alacarte-owned-products-api.md at the\n * repo root for the underlying API contract.\n */\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { useQueryStates, useQueryState, parseAsString } from 'nuqs';\nimport { createAlacarteCheckoutClient } from '../../utils/alacarteCheckout';\nimport { getCouponErrorMessage, getCouponRecheckMessage } from '../../utils/couponErrors';\nimport {\n placeAlacarteOrder,\n toAlacarteBillingAddress,\n} from '../../utils/alacartePayment';\nimport { AlacartePlaceOrderError } from '../../utils/placeOrderErrors';\nimport { CardValidationError } from '../../utils/stripeCard';\nimport { useSubscriptionCourseKeyQuery, useViaxSessionQuery } from './useCheckoutQueries';\nimport { lmsOriginFromSessionUrl, isCourseNotFoundError } from '../../utils/provision';\nimport { getCourseRunKeyFromUrl } from '../../utils/url';\nimport {\n useOwnedProductQuery, useAlacarteCheckoutQuery, useSelectProductMutation, useProductDetailQuery,\n useUpdateCheckoutMutation, usePlacedOrderQuery, useOrderDatesQuery,\n} from './useAlacarteQueries';\nimport type {\n AlacarteCheckout, AlacarteCheckoutResult, AlacarteLine, AlacarteMoney, AlacartePaymentDecline,\n AlacartePriceChanged, OwnedProduct, OwnedProductResult, PlacedOrder, ProductDetail, ProductSelector,\n} from '../../types/alacarte';\nimport type { BillingInfo } from '../../types';\n\nexport type AlacartePhase = 'loading' | 'alreadyOwned' | 'noActiveCheckout' | 'notPurchasable' | 'ready' | 'error';\n\nexport type AlacarteNoticeMessageId = 'alreadyOwnedCourse' | 'alreadyOwnedProgram' | 'noActiveCheckout';\n\n/** Pure phase decision output — no action callbacks. */\nexport interface AlacartePhaseState {\n phase: AlacartePhase,\n noticeMessageId?: AlacarteNoticeMessageId,\n selector: ProductSelector,\n checkout: AlacarteCheckout | null,\n line: AlacarteLine | null,\n productDetail: ProductDetail | null,\n error: string | null,\n priceChanged: AlacartePriceChanged | null,\n priceAccepted: boolean,\n /** True when the learner already owns this product. The checkout data may\n * still be populated so the UI can render the full page under an overlay. */\n isAlreadyOwned: boolean,\n /** Product name from the owned-products query — used as a fallback when the\n * checkout line (which normally carries the name) is not available. */\n ownedProductName: string | null,\n}\n\nexport interface UseAlacarteCheckoutResult extends AlacartePhaseState {\n couponError: string | null,\n couponApplying: boolean,\n applyCoupon: (code: string) => void,\n removeCoupon: () => void,\n clearCouponError: () => void,\n /** Code of the coupon just removed, set only once the removal round-trip\n * completes — kept in sync with when the discount actually leaves the line. */\n removedCouponCode: string | null,\n clearRemovedCouponCode: () => void,\n placingOrder: boolean,\n placeOrderError: string | null,\n /**\n * Accepts price (if needed) + terms, calls tCheckoutPlaceOrder with billing,\n * confirms the card via Stripe.js, then sets ?order_bi_id= to poll tPlacedOrder.\n * Fire-and-forget — errors go to placeOrderError state.\n */\n placeOrder: (opts: {\n billing: BillingInfo,\n confirmCardPayment: (clientSecret: string) => Promise<void>,\n }) => void,\n /**\n * Same as placeOrder but returns a Promise — used by ExpressCheckout\n * so the wallet sheet can await the result and call ev.complete().\n */\n placeOrderAsync: (opts: {\n billing: BillingInfo,\n confirmCardPayment: (clientSecret: string) => Promise<void>,\n }) => Promise<void>,\n clearPlaceOrderError: () => void,\n /** Decline details from the last card attempt on this checkout, if any. */\n paymentDecline: AlacartePaymentDecline | null,\n /** When ?order_bi_id= is present, the placed order (or null while polling). */\n placedOrder: PlacedOrder | null,\n awaitingPlacedOrder: boolean,\n placedOrderError: string | null,\n /** ISO timestamp the order was placed (tPlacedAt, falling back to\n * biCreatedAt); null while the order-dates query hasn't resolved yet. */\n placedOrderPlacedAt: string | null,\n}\n\n/**\n * Read the product selector from the URL: course_uid+course_run_key, or\n * program_uid, or neither. Both course params must be present together; if a\n * course param and a program param are both present, that's\n * CONFLICTING_SELECTION.\n *\n * NOTE: course_run_key values look like \"course-v1:HarvardX+CS50+X\" — nuqs\n * decodes query values the standards-compliant way (literal `+` -> space),\n * same as native URLSearchParams. runKey is therefore read from the raw query\n * string via getCourseRunKeyFromUrl(), which preserves literal `+`.\n */\nexport function useProductSelector(): ProductSelector {\n const [{ courseUid, runKey: nuqsRunKey, programUid }] = useQueryStates({\n courseUid: parseAsString,\n runKey: parseAsString,\n programUid: parseAsString,\n }, {\n urlKeys: {\n courseUid: 'course_uid',\n runKey: 'course_run_key',\n programUid: 'program_uid',\n },\n });\n const runKey = nuqsRunKey ? (getCourseRunKeyFromUrl() ?? nuqsRunKey) : null;\n\n return useMemo<ProductSelector>(() => {\n const hasCourse = !!courseUid || !!runKey;\n const hasProgram = !!programUid;\n if (hasCourse && hasProgram) return { kind: 'invalid' };\n if (courseUid && runKey) return { kind: 'course', courseUid, runKey };\n if (programUid) return { kind: 'program', programUid };\n return { kind: 'none' };\n }, [courseUid, runKey, programUid]);\n}\n\n/** Reads ?discount_code= — applied to the checkout right after it's created. */\nexport function useDiscountCode(): string | null {\n const [discountCode] = useQueryState('discount_code', parseAsString);\n return discountCode;\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : 'Unknown error';\n}\n\n/**\n * Build a synthetic AlacarteLine from the owned-product pricing data so the\n * checkout overlay can show subtotal / deduction / total even when the backend\n * blocks tCheckoutSelect and returns no checkout object.\n */\nfunction buildLineFromOwnedProduct(product: OwnedProduct): AlacarteLine | null {\n if (!product.price) return null;\n const { full, deduction, amountDue, currency } = product.price;\n const toMoney = (amount: number): AlacarteMoney => ({ amount, currency });\n\n if (product.kind === 'program') {\n return {\n biiId: '',\n kind: 'program',\n programId: product.productId,\n programName: product.name,\n price: toMoney(full),\n deduction: deduction ? toMoney(deduction) : null,\n ownedCourses: product.ownedCourses.map((c) => ({\n courseId: c.courseId, name: c.name, via: c.via,\n })),\n discount: null,\n amountDue: toMoney(amountDue),\n billingAddressSet: false,\n };\n }\n\n return {\n biiId: '',\n kind: 'course',\n courseName: product.name,\n courseUid: product.productId,\n courseRunKey: '',\n seatType: 'verified',\n price: toMoney(full),\n discount: null,\n amountDue: toMoney(amountDue),\n billingAddressSet: false,\n };\n}\n\ninterface QueryLikeState<T> {\n isLoading: boolean,\n isError: boolean,\n error?: unknown,\n data?: T,\n}\n\ninterface MutationLikeState<T> {\n isIdle: boolean,\n isPending: boolean,\n isError: boolean,\n error?: unknown,\n data?: T,\n}\n\nexport interface DeriveAlacartePhaseInput {\n selector: ProductSelector,\n sessionReady: boolean,\n sessionIsError: boolean,\n sessionErrorMessage?: string,\n ownedQuery: QueryLikeState<OwnedProductResult>,\n selectMutation: MutationLikeState<AlacarteCheckoutResult>,\n checkoutQuery: QueryLikeState<AlacarteCheckoutResult>,\n productDetail: ProductDetail | null,\n /** Coupon (?discount_code=) applied right after the checkout is created —\n * when it succeeds, its checkout (with the coupon's discount reflected)\n * is shown in place of the pre-coupon one from selectMutation. */\n couponMutation?: MutationLikeState<AlacarteCheckoutResult>,\n /** True when a URL discount code still needs to be applied — the phase\n * stays 'loading' until the coupon mutation resolves so the user never sees\n * the pre-discount price flash. */\n urlCouponPending?: boolean,\n /** Latest successful manual update (coupon / acceptPrice / terms). Wins over\n * select + URL coupon when present. */\n checkoutOverride?: AlacarteCheckout | null,\n /** Course-runs lookup for a course selector. Empty `elements` is notFound. */\n courseRunLookup?: { pending: boolean, notFound: boolean },\n}\n\n/**\n * Pure decision function — no hooks, no React Query/nuqs types beyond plain\n * data — so every branch combination can be unit-tested directly.\n */\nexport function deriveAlacartePhase(input: DeriveAlacartePhaseInput): AlacartePhaseState {\n const {\n selector, sessionReady, sessionIsError, sessionErrorMessage,\n ownedQuery, selectMutation, checkoutQuery, productDetail, couponMutation,\n checkoutOverride = null, urlCouponPending: urlCouponPendingProp = false,\n courseRunLookup = { pending: false, notFound: false },\n } = input;\n\n const ownedProductName = ownedQuery.data?.product?.name ?? null;\n\n const empty: Omit<AlacartePhaseState, 'phase'> = {\n selector,\n checkout: null,\n line: null,\n productDetail: null,\n error: null,\n priceChanged: null,\n priceAccepted: false,\n isAlreadyOwned: false,\n ownedProductName: null,\n };\n\n const withCheckout = (\n checkout: AlacarteCheckout | null,\n priceChanged: AlacartePriceChanged | null = null,\n isAlreadyOwned = false,\n ): AlacartePhaseState => ({\n phase: isAlreadyOwned ? 'alreadyOwned' : 'ready',\n selector,\n checkout,\n line: checkout?.line ?? null,\n productDetail,\n error: null,\n priceChanged: priceChanged ?? null,\n priceAccepted: checkout?.priceAccepted === true,\n isAlreadyOwned,\n ownedProductName: isAlreadyOwned ? ownedProductName : null,\n });\n\n if (selector.kind === 'invalid') {\n return { phase: 'error', ...empty, error: 'CONFLICTING_SELECTION' };\n }\n if (sessionIsError) {\n return { phase: 'error', ...empty, error: sessionErrorMessage ?? 'Session error' };\n }\n\n const hasSelector = selector.kind === 'course' || selector.kind === 'program';\n\n if (hasSelector) {\n if (selector.kind === 'course' && courseRunLookup.notFound) {\n return {\n phase: 'error',\n ...empty,\n error: 'This course could not be found.',\n };\n }\n if (!sessionReady || ownedQuery.isLoading || courseRunLookup.pending) {\n return { phase: 'loading', ...empty };\n }\n if (ownedQuery.isError) {\n return { phase: 'error', ...empty, error: errorMessage(ownedQuery.error) };\n }\n\n const isOwned = ownedQuery.data?.ok === true && ownedQuery.data.product?.status === 'full';\n\n if (selectMutation.isIdle || selectMutation.isPending) {\n return { phase: 'loading', ...empty };\n }\n if (selectMutation.isError) {\n return { phase: 'error', ...empty, error: errorMessage(selectMutation.error) };\n }\n if (selectMutation.data && !selectMutation.data.ok) {\n // The backend may block ALREADY_OWNED at select time. When the\n // blocked response still includes checkout data (line, pricing), use\n // it so the overlay page shows the real totals. Fall back to the\n // standalone tCheckout query, then to an empty state.\n if (selectMutation.data.blocked?.reason === 'ALREADY_OWNED') {\n const blockedCheckout = selectMutation.data.checkout\n ?? (checkoutQuery.data?.ok ? checkoutQuery.data.checkout : null);\n if (blockedCheckout) {\n return withCheckout(blockedCheckout, selectMutation.data.priceChanged ?? null, true);\n }\n // Build a synthetic line from the owned-product pricing so the\n // overlay can show subtotal / deduction / total.\n const ownedProduct = ownedQuery.data?.product;\n const syntheticLine = ownedProduct ? buildLineFromOwnedProduct(ownedProduct) : null;\n return {\n phase: 'alreadyOwned',\n noticeMessageId: selectMutation.data.blocked.kind === 'course' ? 'alreadyOwnedCourse' : 'alreadyOwnedProgram',\n ...empty,\n line: syntheticLine,\n productDetail,\n isAlreadyOwned: true,\n ownedProductName,\n };\n }\n if (selectMutation.data.blocked?.reason === 'NOT_PURCHASABLE') {\n return {\n phase: 'notPurchasable',\n ...empty,\n productDetail,\n error: selectMutation.data.blocked.kind === 'program'\n ? 'This program is not eligible for checkout.'\n : 'This course is not eligible for checkout.',\n };\n }\n const selectError = selectMutation.data.error;\n if (selectError === 'COURSE_NOT_FOUND' || selectError === 'PRODUCT_NOT_FOUND') {\n return {\n phase: 'error',\n ...empty,\n error: 'This course could not be found.',\n };\n }\n if (selectError === 'PROGRAM_NOT_FOUND') {\n return {\n phase: 'error',\n ...empty,\n error: 'This program could not be found.',\n };\n }\n const blockedDetail = selectMutation.data.blocked?.detail;\n return {\n phase: 'error',\n ...empty,\n error: blockedDetail ?? selectError ?? 'unknown',\n };\n }\n\n // When a URL discount code still needs to be applied, stay in 'loading'\n // so the user never sees the pre-discount price flash.\n if (urlCouponPendingProp && !checkoutOverride) {\n return { phase: 'loading', ...empty };\n }\n\n // Once the coupon-apply (?discount_code=) mutation succeeds, its checkout\n // (with the discount reflected) supersedes the pre-coupon one. Manual\n // updates (override) win over both.\n const finalCheckout = checkoutOverride\n ?? (couponMutation?.data?.ok\n ? couponMutation.data.checkout\n : selectMutation.data?.checkout ?? null);\n\n // When select succeeds but the owned-products query says the learner\n // already has this product, show the full checkout under an overlay.\n return withCheckout(\n finalCheckout,\n selectMutation.data?.priceChanged\n ?? (couponMutation?.data?.ok ? couponMutation.data.priceChanged : undefined)\n ?? null,\n isOwned,\n );\n }\n\n // No selector: fall back to the learner's existing open checkout, if any.\n if (!sessionReady || checkoutQuery.isLoading) {\n return { phase: 'loading', ...empty };\n }\n if (checkoutQuery.isError) {\n return { phase: 'error', ...empty, error: errorMessage(checkoutQuery.error) };\n }\n if (checkoutOverride || checkoutQuery.data?.checkout) {\n const checkout = checkoutOverride ?? checkoutQuery.data!.checkout;\n return withCheckout(checkout, checkoutQuery.data?.priceChanged ?? null);\n }\n\n return { phase: 'noActiveCheckout', noticeMessageId: 'noActiveCheckout', ...empty, isAlreadyOwned: false, ownedProductName: null };\n}\n\nexport function useAlacarteCheckout(\n options: { apiUrl?: string, edxSessionUrl?: string },\n): UseAlacarteCheckoutResult {\n const { apiUrl, edxSessionUrl } = options;\n const selector = useProductSelector();\n const discountCode = useDiscountCode();\n const [orderBiId, setOrderBiId] = useQueryState('order_bi_id', parseAsString);\n\n const client = useMemo(\n () => (apiUrl ? createAlacarteCheckoutClient({ apiUrl }) : null),\n [apiUrl],\n );\n\n // Reuses the same query key as useCheckout's session exchange — React\n // Query dedupes the network call regardless of how many hooks read it.\n const sessionQuery = useViaxSessionQuery(edxSessionUrl ?? null);\n const sessionReady = !!sessionQuery.data;\n\n useEffect(() => {\n if (sessionQuery.data && client) {\n client.setToken(sessionQuery.data.viaxToken);\n }\n }, [sessionQuery.data, client]);\n\n const hasSelector = selector.kind === 'course' || selector.kind === 'program';\n const productId = selector.kind === 'course'\n ? selector.courseUid\n : selector.kind === 'program' ? selector.programUid : null;\n\n const ownedQuery = useOwnedProductQuery(client, sessionReady && hasSelector, productId);\n const isOwned = ownedQuery.data?.ok === true && ownedQuery.data.product?.status === 'full';\n\n const selectMutation = useSelectProductMutation(client);\n const {\n isIdle: selectIsIdle, mutate: selectMutate, reset: selectReset,\n } = selectMutation;\n\n const courseRunKey = selector.kind === 'course' ? selector.runKey : null;\n const lmsBaseUrl = useMemo(\n () => lmsOriginFromSessionUrl(edxSessionUrl),\n [edxSessionUrl],\n );\n const courseLookupEnabled = selector.kind === 'course' && !!lmsBaseUrl && !!courseRunKey;\n const courseKeyQuery = useSubscriptionCourseKeyQuery(lmsBaseUrl, courseRunKey);\n const courseKey = courseKeyQuery.data ?? null;\n const courseNotFound = courseLookupEnabled\n && courseKeyQuery.isError\n && isCourseNotFoundError(courseKeyQuery.error);\n\n // Mutations aren't called during render — fire once the owned-products\n // query resolves (regardless of result) so we always get checkout/line data.\n // A course is not selected until the course-runs lookup returns a course.\n // Pass viewedPrice from tOwnedProducts.amountDue (ALC-159) when available.\n useEffect(() => {\n if (!hasSelector || ownedQuery.isLoading || ownedQuery.isError) return;\n if (selector.kind === 'course' && !courseKey) return;\n if (!selectIsIdle) return;\n const amountDue = ownedQuery.data?.product?.price?.amountDue;\n selectMutate({\n selector,\n viewedPrice: typeof amountDue === 'number' ? amountDue : undefined,\n });\n }, [\n hasSelector,\n ownedQuery.isLoading,\n ownedQuery.isError,\n ownedQuery.data?.product?.price?.amountDue,\n selector,\n courseKey,\n selectIsIdle,\n selectMutate,\n ]);\n\n const productDetailEnabled = hasSelector && sessionReady && !ownedQuery.isLoading\n && (selector.kind !== 'course' || !!courseKey);\n const productDetailQuery = useProductDetailQuery(client, productDetailEnabled, selector, courseKey);\n\n // Run the checkout query when there's no selector (standard path) OR when\n // the product is already owned — after the select mutation is blocked with\n // ALREADY_OWNED the server may still have an open checkout with pricing data.\n const selectBlocked = !selectMutation.isIdle && !selectMutation.isPending\n && selectMutation.data && !selectMutation.data.ok;\n const checkoutQuery = useAlacarteCheckoutQuery(\n client,\n sessionReady && (!hasSelector || (isOwned && !!selectBlocked)),\n );\n\n // Apply ?discount_code= to the freshly-created checkout — fired once the\n // select mutation succeeds with a checkout that doesn't already carry it.\n const urlCouponMutation = useUpdateCheckoutMutation(client);\n const {\n isIdle: couponIsIdle, mutate: couponMutate, reset: urlCouponReset,\n } = urlCouponMutation;\n const createdCheckout = selectMutation.data?.ok ? selectMutation.data.checkout : null;\n\n useEffect(() => {\n if (!createdCheckout || !discountCode) return;\n if (createdCheckout.couponCode === discountCode) return;\n if (couponIsIdle) {\n couponMutate({ biId: createdCheckout.biId, couponCode: discountCode });\n }\n }, [createdCheckout, discountCode, couponIsIdle, couponMutate]);\n\n const [checkoutOverride, setCheckoutOverride] = useState<AlacarteCheckout | null>(null);\n const [couponError, setCouponError] = useState<string | null>(null);\n const [removedCouponCode, setRemovedCouponCode] = useState<string | null>(null);\n const [placeOrderError, setPlaceOrderError] = useState<string | null>(null);\n const [placingOrder, setPlacingOrder] = useState(false);\n // biId of a checkout that's locked (CART_PAYMENT_PENDING) from a prior\n // tCheckoutPlaceOrder call whose Stripe confirmation was rejected\n // client-side. The next attempt must skip tCheckoutUpdate (it would fail\n // with CHECKOUT_NOT_OPEN) and go straight to tCheckoutPlaceOrder again.\n const [cardRetryBiId, setCardRetryBiId] = useState<string | null>(null);\n\n // Reset local overrides and in-flight select/coupon when the product changes\n // so viewedPrice / couponRecheck run again for the new selection.\n useEffect(() => {\n setCheckoutOverride(null);\n setCouponError(null);\n setRemovedCouponCode(null);\n setPlaceOrderError(null);\n setCardRetryBiId(null);\n selectReset();\n urlCouponReset();\n }, [selector, selectReset, urlCouponReset]);\n\n // Surface couponRecheck from product switch (section 2 of the API doc).\n useEffect(() => {\n const result = selectMutation.data;\n if (!result?.ok) return;\n const message = getCouponRecheckMessage(\n result.couponRecheck,\n result.checkout?.line?.discountSource,\n );\n if (message) setCouponError(message);\n }, [selectMutation.data]);\n\n // Surface ?discount_code= apply failures (domain ok:false or transport error).\n useEffect(() => {\n if (!discountCode) return;\n if (urlCouponMutation.isIdle || urlCouponMutation.isPending) return;\n if (urlCouponMutation.isError) {\n setCouponError(errorMessage(urlCouponMutation.error));\n return;\n }\n const result = urlCouponMutation.data;\n if (result && !result.ok) {\n setCouponError(getCouponErrorMessage(result.error, discountCode));\n }\n }, [\n discountCode,\n urlCouponMutation.isIdle,\n urlCouponMutation.isPending,\n urlCouponMutation.isError,\n urlCouponMutation.error,\n urlCouponMutation.data,\n ]);\n\n const manualUpdateMutation = useUpdateCheckoutMutation(client);\n\n const placedOrderQuery = usePlacedOrderQuery(\n client,\n orderBiId,\n sessionReady && !!orderBiId,\n );\n\n const orderDatesQuery = useOrderDatesQuery(\n client,\n orderBiId,\n sessionReady && !!orderBiId,\n );\n\n const derived = deriveAlacartePhase({\n selector,\n sessionReady,\n sessionIsError: sessionQuery.isError,\n sessionErrorMessage: sessionQuery.error?.message,\n ownedQuery: {\n isLoading: ownedQuery.isLoading,\n isError: ownedQuery.isError,\n error: ownedQuery.error,\n data: ownedQuery.data,\n },\n selectMutation: {\n isIdle: selectMutation.isIdle,\n isPending: selectMutation.isPending,\n isError: selectMutation.isError,\n error: selectMutation.error,\n data: selectMutation.data,\n },\n checkoutQuery: {\n isLoading: checkoutQuery.isLoading,\n isError: checkoutQuery.isError,\n error: checkoutQuery.error,\n data: checkoutQuery.data,\n },\n productDetail: productDetailQuery.data ?? null,\n courseRunLookup: {\n pending: courseLookupEnabled && courseKeyQuery.isLoading,\n notFound: courseNotFound,\n },\n couponMutation: {\n isIdle: urlCouponMutation.isIdle,\n isPending: urlCouponMutation.isPending,\n isError: urlCouponMutation.isError,\n error: urlCouponMutation.error,\n data: urlCouponMutation.data,\n },\n checkoutOverride,\n // The URL coupon is pending only when the checkout exists, doesn't already\n // carry the code, and the mutation hasn't completed yet. When the backend\n // returns the coupon pre-applied (couponCode === discountCode) or when\n // there's no discount_code param at all, this is false from the start.\n urlCouponPending: !!discountCode\n && !!createdCheckout\n && createdCheckout.couponCode !== discountCode\n && (urlCouponMutation.isIdle || urlCouponMutation.isPending),\n });\n\n const applyCoupon = useCallback((code: string) => {\n const biId = derived.checkout?.biId;\n if (!biId || !client) return;\n const trimmed = code.trim();\n if (!trimmed) return;\n\n setCouponError(null);\n manualUpdateMutation.mutate(\n { biId, couponCode: trimmed },\n {\n onSuccess: (result) => {\n if (result.ok && result.checkout) {\n setCheckoutOverride(result.checkout);\n setCouponError(null);\n setRemovedCouponCode(null);\n } else {\n setCouponError(getCouponErrorMessage(result.error, trimmed));\n }\n },\n onError: (err) => {\n setCouponError(errorMessage(err));\n },\n },\n );\n }, [derived.checkout?.biId, client, manualUpdateMutation]);\n\n const removeCoupon = useCallback(() => {\n const currentCheckout = derived.checkout;\n if (!currentCheckout?.biId || !client) return;\n const removedCode = currentCheckout.couponCode?.trim() || null;\n\n setCouponError(null);\n manualUpdateMutation.mutate(\n { biId: currentCheckout.biId, couponCode: '' },\n {\n onSuccess: (result) => {\n if (!result.ok) {\n setCouponError(getCouponErrorMessage(result.error));\n return;\n }\n // The backend may return a checkout whose line still carries the\n // old discount/amountDue. Always patch the line to clear the\n // coupon so the cart summary reflects the removal immediately.\n const base = result.checkout ?? currentCheckout;\n const line = base.line;\n const patchedLine = line\n ? {\n ...line,\n discount: null,\n amountDue: line.price && line.kind === 'program' && 'deduction' in line && line.deduction\n ? { amount: line.price.amount - line.deduction.amount, currency: line.price.currency }\n : line.price,\n } as typeof line\n : null;\n setCheckoutOverride({\n ...base,\n couponCode: null,\n line: patchedLine,\n });\n setCouponError(null);\n if (removedCode) setRemovedCouponCode(removedCode);\n },\n onError: (err) => {\n setCouponError(errorMessage(err));\n },\n },\n );\n }, [derived.checkout, client, manualUpdateMutation]);\n\n const placeOrderCore = useCallback(async (opts: {\n billing: BillingInfo,\n confirmCardPayment: (clientSecret: string) => Promise<void>,\n }) => {\n const checkout = derived.checkout;\n if (!checkout || !client) throw new Error('Checkout not ready');\n\n setPlacingOrder(true);\n setPlaceOrderError(null);\n\n try {\n const { checkout: updated } = await placeAlacarteOrder({\n updateCheckout: (args) => client.updateCheckout(args),\n placeCheckoutOrder: (biId, billing) => client.placeCheckoutOrder(biId, billing),\n checkout,\n billing: toAlacarteBillingAddress(opts.billing),\n confirmCardPayment: opts.confirmCardPayment,\n skipPrepare: cardRetryBiId === checkout.biId,\n });\n\n setCardRetryBiId(null);\n setCheckoutOverride(updated);\n await setOrderBiId(updated.biId);\n } catch (err: unknown) {\n if (err instanceof CardValidationError) {\n // tCheckoutPlaceOrder already succeeded and locked the checkout\n // (CART_PAYMENT_PENDING); Stripe rejected the card before it ever\n // reached the backend. Next attempt must retry tCheckoutPlaceOrder\n // directly, not tCheckoutUpdate.\n setCardRetryBiId(checkout.biId);\n } else {\n setCardRetryBiId(null);\n }\n if (err instanceof AlacartePlaceOrderError && err.checkout) {\n setCheckoutOverride(err.checkout);\n }\n setPlaceOrderError(errorMessage(err));\n throw err;\n } finally {\n setPlacingOrder(false);\n }\n }, [derived.checkout, client, setOrderBiId, cardRetryBiId]);\n\n /** Fire-and-forget wrapper for card payments. */\n const placeOrder = useCallback((opts: {\n billing: BillingInfo,\n confirmCardPayment: (clientSecret: string) => Promise<void>,\n }) => {\n if (placingOrder) return;\n placeOrderCore(opts).catch(() => { /* error already in state */ });\n }, [placeOrderCore, placingOrder]);\n\n const placedOrder = placedOrderQuery.data?.ok ? placedOrderQuery.data.order : null;\n\n const dates = orderDatesQuery.data?.ok ? orderDatesQuery.data.dates : null;\n const placedOrderPlacedAt = dates?.tPlacedAt ?? dates?.biCreatedAt ?? null;\n\n const placedOrderError = (() => {\n if (!orderBiId) return null;\n if (\n placedOrderQuery.data\n && !placedOrderQuery.data.ok\n && placedOrderQuery.data.error !== 'NOT_PLACED'\n && placedOrderQuery.data.error !== 'ORDER_READ_FAILED'\n ) {\n return placedOrderQuery.data.error ?? 'ORDER_READ_FAILED';\n }\n return null;\n })();\n\n return {\n ...derived,\n couponError,\n couponApplying: manualUpdateMutation.isPending,\n applyCoupon,\n removeCoupon,\n clearCouponError: () => setCouponError(null),\n removedCouponCode,\n clearRemovedCouponCode: () => setRemovedCouponCode(null),\n placingOrder,\n placeOrderError,\n placeOrder,\n placeOrderAsync: placeOrderCore,\n clearPlaceOrderError: () => setPlaceOrderError(null),\n paymentDecline: derived.checkout?.paymentDecline ?? null,\n placedOrder,\n awaitingPlacedOrder: !!orderBiId && !placedOrder && !placedOrderError && (\n placedOrderQuery.isLoading\n || placedOrderQuery.isFetching\n || placedOrderQuery.data?.error === 'NOT_PLACED'\n || placedOrderQuery.data?.error === 'ORDER_READ_FAILED'\n || (placedOrderQuery.data?.ok === true && !placedOrderQuery.data.order)\n || !placedOrderQuery.data\n ),\n placedOrderError,\n placedOrderPlacedAt,\n };\n}\n\nexport default useAlacarteCheckout;\n"]}
@@ -18,9 +18,9 @@ export declare function useUpdateCheckoutMutation(client: AlacarteCheckoutClient
18
18
  acceptPrice?: boolean;
19
19
  }, unknown>;
20
20
  /** Fetches display details for the selected product.
21
- * A course is looked up in Viax by the course key resolved from the
22
- * subscription course-run API (not the URL course_run_key). A program uses
23
- * filterTwouProgram by uid. */
21
+ * A course is looked up in Viax by elements[0].course from the
22
+ * subscription course-run API (not the course-run key or the URL param).
23
+ * A program uses filterTwouProgram by uid. */
24
24
  export declare function useProductDetailQuery(client: AlacarteCheckoutClient | null, enabled: boolean, selector: ProductSelector, courseKey?: string | null): import("@tanstack/react-query").UseQueryResult<ProductDetail | null, Error>;
25
25
  /** Fetches a placed order for the confirmation page. Polls while the order
26
26
  * is not yet placed (Stripe confirms to the backend asynchronously). */
@@ -54,9 +54,9 @@ export function useUpdateCheckoutMutation(client) {
54
54
  });
55
55
  }
56
56
  /** Fetches display details for the selected product.
57
- * A course is looked up in Viax by the course key resolved from the
58
- * subscription course-run API (not the URL course_run_key). A program uses
59
- * filterTwouProgram by uid. */
57
+ * A course is looked up in Viax by elements[0].course from the
58
+ * subscription course-run API (not the course-run key or the URL param).
59
+ * A program uses filterTwouProgram by uid. */
60
60
  export function useProductDetailQuery(client, enabled, selector, courseKey = null) {
61
61
  const productKey = selector.kind === 'course'
62
62
  ? (courseKey !== null && courseKey !== void 0 ? courseKey : 'none')
@@ -1 +1 @@
1
- {"version":3,"file":"useAlacarteQueries.js","sourceRoot":"","sources":["../../../src/data/hooks/useAlacarteQueries.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * data/hooks/useAlacarteQueries.ts — read/write-side TanStack Query hooks for\n * the à la carte checkout flow. Mirrors useCheckoutQueries.ts's conventions.\n */\nimport { useQuery, useMutation } from '@tanstack/react-query';\nimport { alacarteKeys } from './keys';\nimport type {\n AlacarteCheckoutClient, AlacarteCheckoutResult, OwnedProductResult, ProductSelector, ProductDetail,\n PlacedOrderResult, OrderDatesResult,\n} from '../../types/alacarte';\n\n/** Checks ownership of the product identified by the query params. */\nexport function useOwnedProductQuery(\n client: AlacarteCheckoutClient | null,\n enabled: boolean,\n productId: string | null,\n) {\n return useQuery({\n queryKey: alacarteKeys.ownedProduct(productId ?? 'none'),\n enabled: enabled && !!client && !!productId,\n queryFn: (): Promise<OwnedProductResult> => client!.getOwnedProduct(productId!),\n staleTime: Infinity,\n retry: 1,\n });\n}\n\n/** Reads the learner's existing open checkout (used when there's no product selector). */\nexport function useAlacarteCheckoutQuery(client: AlacarteCheckoutClient | null, enabled: boolean) {\n return useQuery({\n queryKey: alacarteKeys.checkout(),\n enabled: enabled && !!client,\n queryFn: (): Promise<AlacarteCheckoutResult> => client!.getCheckout(),\n staleTime: 0,\n retry: 1,\n });\n}\n\n/** Selects a course or program into the learner's checkout — fired once ownership is confirmed not-full.\n * `viewedPrice` is `tOwnedProducts.price.amountDue` (USD, before any coupon) for ALC-159. */\nexport function useSelectProductMutation(client: AlacarteCheckoutClient | null) {\n return useMutation({\n mutationFn: (args: {\n selector: ProductSelector,\n viewedPrice?: number,\n }): Promise<AlacarteCheckoutResult> => {\n if (!client) return Promise.reject(new Error('Alacarte client not ready.'));\n const { selector, viewedPrice } = args;\n if (selector.kind === 'course') {\n return client.selectCourse(selector.courseUid, selector.runKey, viewedPrice);\n }\n if (selector.kind === 'program') {\n return client.selectProgram(selector.programUid, viewedPrice);\n }\n return Promise.reject(new Error('selectMutation called with no product selector.'));\n },\n });\n}\n\n/** Updates the learner's checkout — used here to apply ?discount_code= right\n * after the checkout is created. */\nexport function useUpdateCheckoutMutation(client: AlacarteCheckoutClient | null) {\n return useMutation({\n mutationFn: (args: {\n biId?: string, couponCode?: string, termsAccepted?: boolean, acceptPrice?: boolean,\n }): Promise<AlacarteCheckoutResult> => {\n if (!client) return Promise.reject(new Error('Alacarte client not ready.'));\n return client.updateCheckout(args);\n },\n });\n}\n\n/** Fetches display details for the selected product.\n * A course is looked up in Viax by the course key resolved from the\n * subscription course-run API (not the URL course_run_key). A program uses\n * filterTwouProgram by uid. */\nexport function useProductDetailQuery(\n client: AlacarteCheckoutClient | null,\n enabled: boolean,\n selector: ProductSelector,\n courseKey: string | null = null,\n) {\n const productKey = selector.kind === 'course'\n ? (courseKey ?? 'none')\n : selector.kind === 'program' ? selector.programUid : 'none';\n\n return useQuery({\n queryKey: alacarteKeys.productDetail(`${selector.kind}:${productKey}`),\n enabled: enabled && !!client && (\n selector.kind === 'program' || (selector.kind === 'course' && !!courseKey)\n ),\n queryFn: (): Promise<ProductDetail | null> => {\n if (selector.kind === 'course') return client!.getCourseDetail(courseKey!);\n if (selector.kind === 'program') return client!.getProgramDetail(selector.programUid);\n return Promise.resolve(null);\n },\n staleTime: Infinity,\n retry: 1,\n });\n}\n\n/** Fetches a placed order for the confirmation page. Polls while the order\n * is not yet placed (Stripe confirms to the backend asynchronously). */\nexport function usePlacedOrderQuery(\n client: AlacarteCheckoutClient | null,\n biId: string | null,\n enabled: boolean,\n) {\n return useQuery({\n queryKey: alacarteKeys.placedOrder(biId ?? 'none'),\n enabled: enabled && !!client && !!biId,\n queryFn: (): Promise<PlacedOrderResult> => client!.getPlacedOrder(biId!),\n staleTime: 0,\n retry: 1,\n refetchInterval: (query) => {\n const result = query.state.data;\n // Keep polling while payment is still settling on the backend.\n if (!result) return 2000;\n if (result.ok && result.order) return false;\n if (result.error === 'NOT_PLACED' || result.error === 'ORDER_READ_FAILED') return 2000;\n return false;\n },\n });\n}\n\n/** Fetches the order's placement/creation timestamps — used for the\n * confirmation page's purchase date and refund-window deadline. */\nexport function useOrderDatesQuery(\n client: AlacarteCheckoutClient | null,\n biId: string | null,\n enabled: boolean,\n) {\n return useQuery({\n queryKey: alacarteKeys.orderDates(biId ?? 'none'),\n enabled: enabled && !!client && !!biId,\n queryFn: (): Promise<OrderDatesResult> => client!.getOrderDates(biId!),\n staleTime: Infinity,\n retry: 1,\n });\n}\n"]}
1
+ {"version":3,"file":"useAlacarteQueries.js","sourceRoot":"","sources":["../../../src/data/hooks/useAlacarteQueries.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * data/hooks/useAlacarteQueries.ts — read/write-side TanStack Query hooks for\n * the à la carte checkout flow. Mirrors useCheckoutQueries.ts's conventions.\n */\nimport { useQuery, useMutation } from '@tanstack/react-query';\nimport { alacarteKeys } from './keys';\nimport type {\n AlacarteCheckoutClient, AlacarteCheckoutResult, OwnedProductResult, ProductSelector, ProductDetail,\n PlacedOrderResult, OrderDatesResult,\n} from '../../types/alacarte';\n\n/** Checks ownership of the product identified by the query params. */\nexport function useOwnedProductQuery(\n client: AlacarteCheckoutClient | null,\n enabled: boolean,\n productId: string | null,\n) {\n return useQuery({\n queryKey: alacarteKeys.ownedProduct(productId ?? 'none'),\n enabled: enabled && !!client && !!productId,\n queryFn: (): Promise<OwnedProductResult> => client!.getOwnedProduct(productId!),\n staleTime: Infinity,\n retry: 1,\n });\n}\n\n/** Reads the learner's existing open checkout (used when there's no product selector). */\nexport function useAlacarteCheckoutQuery(client: AlacarteCheckoutClient | null, enabled: boolean) {\n return useQuery({\n queryKey: alacarteKeys.checkout(),\n enabled: enabled && !!client,\n queryFn: (): Promise<AlacarteCheckoutResult> => client!.getCheckout(),\n staleTime: 0,\n retry: 1,\n });\n}\n\n/** Selects a course or program into the learner's checkout — fired once ownership is confirmed not-full.\n * `viewedPrice` is `tOwnedProducts.price.amountDue` (USD, before any coupon) for ALC-159. */\nexport function useSelectProductMutation(client: AlacarteCheckoutClient | null) {\n return useMutation({\n mutationFn: (args: {\n selector: ProductSelector,\n viewedPrice?: number,\n }): Promise<AlacarteCheckoutResult> => {\n if (!client) return Promise.reject(new Error('Alacarte client not ready.'));\n const { selector, viewedPrice } = args;\n if (selector.kind === 'course') {\n return client.selectCourse(selector.courseUid, selector.runKey, viewedPrice);\n }\n if (selector.kind === 'program') {\n return client.selectProgram(selector.programUid, viewedPrice);\n }\n return Promise.reject(new Error('selectMutation called with no product selector.'));\n },\n });\n}\n\n/** Updates the learner's checkout — used here to apply ?discount_code= right\n * after the checkout is created. */\nexport function useUpdateCheckoutMutation(client: AlacarteCheckoutClient | null) {\n return useMutation({\n mutationFn: (args: {\n biId?: string, couponCode?: string, termsAccepted?: boolean, acceptPrice?: boolean,\n }): Promise<AlacarteCheckoutResult> => {\n if (!client) return Promise.reject(new Error('Alacarte client not ready.'));\n return client.updateCheckout(args);\n },\n });\n}\n\n/** Fetches display details for the selected product.\n * A course is looked up in Viax by elements[0].course from the\n * subscription course-run API (not the course-run key or the URL param).\n * A program uses filterTwouProgram by uid. */\nexport function useProductDetailQuery(\n client: AlacarteCheckoutClient | null,\n enabled: boolean,\n selector: ProductSelector,\n courseKey: string | null = null,\n) {\n const productKey = selector.kind === 'course'\n ? (courseKey ?? 'none')\n : selector.kind === 'program' ? selector.programUid : 'none';\n\n return useQuery({\n queryKey: alacarteKeys.productDetail(`${selector.kind}:${productKey}`),\n enabled: enabled && !!client && (\n selector.kind === 'program' || (selector.kind === 'course' && !!courseKey)\n ),\n queryFn: (): Promise<ProductDetail | null> => {\n if (selector.kind === 'course') return client!.getCourseDetail(courseKey!);\n if (selector.kind === 'program') return client!.getProgramDetail(selector.programUid);\n return Promise.resolve(null);\n },\n staleTime: Infinity,\n retry: 1,\n });\n}\n\n/** Fetches a placed order for the confirmation page. Polls while the order\n * is not yet placed (Stripe confirms to the backend asynchronously). */\nexport function usePlacedOrderQuery(\n client: AlacarteCheckoutClient | null,\n biId: string | null,\n enabled: boolean,\n) {\n return useQuery({\n queryKey: alacarteKeys.placedOrder(biId ?? 'none'),\n enabled: enabled && !!client && !!biId,\n queryFn: (): Promise<PlacedOrderResult> => client!.getPlacedOrder(biId!),\n staleTime: 0,\n retry: 1,\n refetchInterval: (query) => {\n const result = query.state.data;\n // Keep polling while payment is still settling on the backend.\n if (!result) return 2000;\n if (result.ok && result.order) return false;\n if (result.error === 'NOT_PLACED' || result.error === 'ORDER_READ_FAILED') return 2000;\n return false;\n },\n });\n}\n\n/** Fetches the order's placement/creation timestamps — used for the\n * confirmation page's purchase date and refund-window deadline. */\nexport function useOrderDatesQuery(\n client: AlacarteCheckoutClient | null,\n biId: string | null,\n enabled: boolean,\n) {\n return useQuery({\n queryKey: alacarteKeys.orderDates(biId ?? 'none'),\n enabled: enabled && !!client && !!biId,\n queryFn: (): Promise<OrderDatesResult> => client!.getOrderDates(biId!),\n staleTime: Infinity,\n retry: 1,\n });\n}\n"]}