@edx/frontend-app-subscription-learner-dashboard 1.67.1 → 1.67.3
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.
- package/dist/containers/PopularProgramsPanel/PopularPrograms/index.d.ts +0 -2
- package/dist/containers/PopularProgramsPanel/PopularPrograms/index.js +1 -21
- package/dist/containers/PopularProgramsPanel/PopularPrograms/index.js.map +1 -1
- package/dist/containers/ProductCard/index.js +25 -16
- package/dist/containers/ProductCard/index.js.map +1 -1
- package/dist/containers/ProductCard/index.scss +73 -13
- package/dist/containers/SubscriptionBanner/components/SubscriptionBanner.js +4 -2
- package/dist/containers/SubscriptionBanner/components/SubscriptionBanner.js.map +1 -1
- package/dist/containers/SubscriptionInformation/components/SubscriptionInformation.js +4 -2
- package/dist/containers/SubscriptionInformation/components/SubscriptionInformation.js.map +1 -1
- package/dist/hooks/usePopularCoursesAndPrograms.d.ts +2 -0
- package/dist/hooks/usePopularCoursesAndPrograms.js +26 -1
- package/dist/hooks/usePopularCoursesAndPrograms.js.map +1 -1
- package/dist/tracking/trackingContext.d.ts +1 -0
- package/dist/tracking/trackingContext.js +2 -1
- package/dist/tracking/trackingContext.js.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/isRenewEligible.d.ts +1 -0
- package/dist/utils/isRenewEligible.js +20 -0
- package/dist/utils/isRenewEligible.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { FC } from 'react';
|
|
2
2
|
import { PopularProgramsProps } from './data/types';
|
|
3
|
-
export declare const getProductSlugFromMarketingUrl: (marketingUrl: string | null | undefined) => string | null;
|
|
4
|
-
export declare const buildEnrollPath: (marketingUrl: string | null | undefined) => string;
|
|
5
3
|
export declare const PopularPrograms: FC<PopularProgramsProps>;
|
|
6
4
|
export default PopularPrograms;
|
|
@@ -1,27 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { ProductCard } from '../../ProductCard';
|
|
3
|
-
export const getProductSlugFromMarketingUrl = (marketingUrl) => {
|
|
4
|
-
if (!marketingUrl) {
|
|
5
|
-
return null;
|
|
6
|
-
}
|
|
7
|
-
try {
|
|
8
|
-
const pathname = new URL(marketingUrl).pathname;
|
|
9
|
-
const slug = pathname.split('/').filter(Boolean).at(-1);
|
|
10
|
-
return slug !== null && slug !== void 0 ? slug : null;
|
|
11
|
-
}
|
|
12
|
-
catch (_a) {
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
export const buildEnrollPath = (marketingUrl) => {
|
|
17
|
-
const slug = getProductSlugFromMarketingUrl(marketingUrl);
|
|
18
|
-
if (!slug) {
|
|
19
|
-
return '';
|
|
20
|
-
}
|
|
21
|
-
return `/program/${encodeURIComponent(slug)}`;
|
|
22
|
-
};
|
|
23
3
|
export const PopularPrograms = ({ items }) => {
|
|
24
|
-
return (_jsx("div", { "data-testid": "popular-programs-items", children: _jsx("div", { className: "row g-3 flex-nowrap flex-md-wrap overflow-auto", children: items.map((item) => (_jsx("div", { className: "col-12 col-md-6 col-xl-3 d-flex mb-2", children: _jsx(ProductCard, { item:
|
|
4
|
+
return (_jsx("div", { "data-testid": "popular-programs-items", children: _jsx("div", { className: "row g-3 flex-nowrap flex-md-wrap overflow-auto", children: items.map((item) => (_jsx("div", { className: "col-12 col-md-6 col-xl-3 d-flex mb-2", children: _jsx(ProductCard, { item: item }) }, item.objectID))) }) }));
|
|
25
5
|
};
|
|
26
6
|
export default PopularPrograms;
|
|
27
7
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/containers/PopularProgramsPanel/PopularPrograms/index.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,MAAM,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/containers/PopularProgramsPanel/PopularPrograms/index.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,MAAM,CAAC,MAAM,eAAe,GAA6B,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;IACrE,OAAO,CACL,6BAAiB,wBAAwB,YACvC,cAAK,SAAS,EAAC,gDAAgD,YAC5D,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACnB,cAAyB,SAAS,EAAC,sCAAsC,YACvE,KAAC,WAAW,IACV,IAAI,EAAE,IAAI,GACV,IAHM,IAAI,CAAC,QAAQ,CAIjB,CACP,CAAC,GACE,GACF,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,eAAe,CAAC","sourcesContent":["import { FC } from 'react';\n\nimport { ProductCard } from '../../ProductCard';\nimport { PopularProgramsProps } from './data/types';\n\nexport const PopularPrograms: FC<PopularProgramsProps> = ({ items }) => {\n return (\n <div data-testid=\"popular-programs-items\">\n <div className=\"row g-3 flex-nowrap flex-md-wrap overflow-auto\">\n {items.map((item) => (\n <div key={item.objectID} className=\"col-12 col-md-6 col-xl-3 d-flex mb-2\">\n <ProductCard\n item={item}\n />\n </div>\n ))}\n </div>\n </div>\n );\n};\n\nexport default PopularPrograms;\n"]}
|
|
@@ -1,30 +1,39 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useIntl } from '@openedx/frontend-base';
|
|
3
|
-
import { Card,
|
|
4
|
-
import {
|
|
3
|
+
import { Card, Icon } from '@openedx/paragon';
|
|
4
|
+
import { Speed, FormatListNumbered, Timer } from '@openedx/paragon/icons';
|
|
5
5
|
import './index.scss';
|
|
6
6
|
import cardFallbackImg from '@openedx/brand-openedx/paragon/images/card-imagecap-fallback.png';
|
|
7
7
|
import messages from './messages';
|
|
8
8
|
import { eventNames, trackSubscriptionEvent } from '../../tracking/trackers/subscription';
|
|
9
|
-
const getIdentifyingUrlPath = (marketingUrl) => {
|
|
10
|
-
if (!marketingUrl) {
|
|
11
|
-
return null;
|
|
12
|
-
}
|
|
13
|
-
try {
|
|
14
|
-
const path = new URL(marketingUrl, window.location.origin).pathname.replace(/^\//, '');
|
|
15
|
-
return path || null;
|
|
16
|
-
}
|
|
17
|
-
catch (_a) {
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
9
|
export const ProductCard = ({ item, isLoading }) => {
|
|
22
10
|
const { formatMessage } = useIntl();
|
|
23
|
-
const identifyingUrlPath = getIdentifyingUrlPath(item.marketing_url);
|
|
24
11
|
const totalProgramCourses = item.product === 'program' && item.subject && item.subject.length ? item.subject.length : 0;
|
|
12
|
+
const durationWeeks = item.weeks_to_complete != null && typeof item.weeks_to_complete === 'number' ? item.weeks_to_complete : '';
|
|
13
|
+
const level = item.level || '';
|
|
14
|
+
const linkProps = item.marketing_url
|
|
15
|
+
? { as: 'a', href: item.marketing_url }
|
|
16
|
+
: {};
|
|
25
17
|
const handleClick = () => {
|
|
26
18
|
trackSubscriptionEvent(eventNames.cardTileSelected, {});
|
|
27
19
|
};
|
|
28
|
-
|
|
20
|
+
const metadataItems = [
|
|
21
|
+
totalProgramCourses > 0 && {
|
|
22
|
+
key: 'course-count',
|
|
23
|
+
icon: FormatListNumbered,
|
|
24
|
+
label: formatMessage(messages.courses, { count: totalProgramCourses }),
|
|
25
|
+
},
|
|
26
|
+
durationWeeks && {
|
|
27
|
+
key: 'duration',
|
|
28
|
+
icon: Timer,
|
|
29
|
+
label: formatMessage(messages.weeksToComplete, { count: item.weeks_to_complete }),
|
|
30
|
+
},
|
|
31
|
+
level && {
|
|
32
|
+
key: 'level',
|
|
33
|
+
icon: Speed,
|
|
34
|
+
label: formatMessage(messages.level, { level }),
|
|
35
|
+
},
|
|
36
|
+
].filter(Boolean);
|
|
37
|
+
return (_jsxs(Card, Object.assign({ isClickable: Boolean(item.marketing_url), className: "product-card course-card h-100 d-flex flex-column overflow-hidden", variant: "light", "data-testid": "product-card", isLoading: isLoading, onClick: handleClick }, linkProps, { children: [_jsx(Card.Header, { className: "product-card__header", size: "sm", title: (_jsx("span", { className: "product-card__header-label", children: item.product === 'program' ? `${item.content_type}` : 'Course' })) }), _jsx(Card.ImageCap, { src: item.url || cardFallbackImg, srcAlt: `${item.title} main-image`, "data-testid": "product-card-image", logoSrc: item.thumbnail || '', logoAlt: `${item.title} thumbnail-image`, fallbackLogoSrc: cardFallbackImg }), _jsxs(Card.Section, { className: "pt-4\\.5 flex-grow-1", children: [item.title && (_jsx("h4", { className: "h6 m-0 product-card__title", children: item.title })), item.partner && (_jsx("p", { className: "mt-1 mb-0 product-card__institution", children: item.partner }))] }), _jsx(Card.Section, { className: "product-card__metadata pt-0 mt-auto", children: metadataItems.map((mitem) => (_jsxs("div", { className: "product-card__metadata-item", children: [_jsx(Icon, { src: mitem.icon, size: "sm", className: "product-card__metadata-icon" }), _jsx("span", { children: mitem.label })] }, mitem.key))) })] })));
|
|
29
38
|
};
|
|
30
39
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/containers/ProductCard/index.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/containers/ProductCard/index.tsx"],"names":[],"mappings":"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","sourcesContent":["import { FC } from 'react';\nimport { useIntl } from '@openedx/frontend-base';\nimport { Card, Icon } from '@openedx/paragon';\nimport { Speed, FormatListNumbered, Timer } from '@openedx/paragon/icons';\nimport './index.scss';\nimport cardFallbackImg from '@openedx/brand-openedx/paragon/images/card-imagecap-fallback.png';\nimport { ProductCardProps } from './data/types';\nimport messages from './messages';\nimport { eventNames, trackSubscriptionEvent } from '@src/tracking/trackers/subscription';\n\nexport const ProductCard: FC<ProductCardProps> = ({ item, isLoading }) => {\n const { formatMessage } = useIntl();\n const totalProgramCourses = item.product === 'program' && item.subject && item.subject.length ? item.subject.length : 0;\n const durationWeeks = item.weeks_to_complete != null && typeof item.weeks_to_complete === 'number' ? item.weeks_to_complete : '';\n const level = item.level || '';\n const linkProps = item.marketing_url\n ? { as: 'a' as const, href: item.marketing_url }\n : {};\n\n const handleClick = () => {\n trackSubscriptionEvent(eventNames.cardTileSelected, {});\n };\n\n const metadataItems = [\n totalProgramCourses > 0 && {\n key: 'course-count',\n icon: FormatListNumbered,\n label: formatMessage(messages.courses, { count: totalProgramCourses }),\n },\n durationWeeks && {\n key: 'duration',\n icon: Timer,\n label: formatMessage(messages.weeksToComplete, { count: item.weeks_to_complete }),\n },\n level && {\n key: 'level',\n icon: Speed,\n label: formatMessage(messages.level, { level }),\n },\n ].filter(Boolean) as {\n key: string,\n icon: React.ComponentType,\n label: string,\n }[];\n\n return (\n <Card\n isClickable={Boolean(item.marketing_url)}\n className=\"product-card course-card h-100 d-flex flex-column overflow-hidden\"\n variant=\"light\"\n data-testid=\"product-card\"\n isLoading={isLoading}\n onClick={handleClick}\n {...linkProps}\n >\n <Card.Header\n className=\"product-card__header\"\n size=\"sm\"\n title={(\n <span className=\"product-card__header-label\">\n {item.product === 'program' ? `${item.content_type}` : 'Course'}\n </span>\n )}\n />\n\n <Card.ImageCap\n src={item.url || cardFallbackImg}\n srcAlt={`${item.title} main-image`}\n data-testid=\"product-card-image\"\n logoSrc={item.thumbnail || ''}\n logoAlt={`${item.title} thumbnail-image`}\n fallbackLogoSrc={cardFallbackImg}\n />\n\n <Card.Section className=\"pt-4\\.5 flex-grow-1\">\n {item.title && (\n <h4 className=\"h6 m-0 product-card__title\">\n {item.title}\n </h4>\n )}\n {item.partner && (\n <p className=\"mt-1 mb-0 product-card__institution\">\n {item.partner}\n </p>\n )}\n </Card.Section>\n\n <Card.Section className=\"product-card__metadata pt-0 mt-auto\">\n {metadataItems.map((mitem) => (\n <div key={mitem.key} className=\"product-card__metadata-item\">\n <Icon\n src={mitem.icon}\n size=\"sm\"\n className=\"product-card__metadata-icon\"\n />\n <span>{mitem.label}</span>\n </div>\n ))}\n </Card.Section>\n\n </Card>\n );\n};\n"]}
|
|
@@ -1,17 +1,77 @@
|
|
|
1
|
-
.product-card
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
.product-card {
|
|
2
|
+
overflow: hidden;
|
|
3
|
+
text-decoration: none;
|
|
4
|
+
color: inherit;
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
&:hover,
|
|
7
|
+
&:focus {
|
|
8
|
+
text-decoration: none;
|
|
9
|
+
color: inherit;
|
|
10
|
+
}
|
|
8
11
|
|
|
9
|
-
.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
.product-card__header.pgn__card-header {
|
|
13
|
+
background-color: var(--pgn-color-light-500);
|
|
14
|
+
|
|
15
|
+
.pgn__card-header-content {
|
|
16
|
+
margin: 0;
|
|
17
|
+
overflow: hidden;
|
|
18
|
+
padding: 0.6875rem 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.product-card__header-label {
|
|
22
|
+
color: var(--pgn-color-primary-base);
|
|
23
|
+
font-size: 0.875rem;
|
|
24
|
+
font-weight: 700;
|
|
25
|
+
display: block;
|
|
26
|
+
line-height: 1;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.pgn__card-wrapper-image-cap.vertical {
|
|
31
|
+
background-color: var(--pgn-color-gray-200);
|
|
32
|
+
height: 6.5rem;
|
|
33
|
+
max-height: 6.5rem;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.pgn__card-image-cap {
|
|
37
|
+
border-top-left-radius: 0;
|
|
38
|
+
border-top-right-radius: 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.pgn__card-logo-cap.show {
|
|
42
|
+
bottom: 50%;
|
|
43
|
+
transform: translateY(50%);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.product-card__title {
|
|
47
|
+
color: var(--pgn-color-gray-900);
|
|
48
|
+
display: -webkit-box;
|
|
49
|
+
-webkit-box-orient: vertical;
|
|
50
|
+
-webkit-line-clamp: 2;
|
|
51
|
+
overflow: hidden;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.product-card__institution {
|
|
55
|
+
color: var(--pgn-color-gray-500);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.product-card__metadata {
|
|
59
|
+
.product-card__metadata-item {
|
|
60
|
+
align-items: center;
|
|
61
|
+
color: var(--pgn-color-gray-500);
|
|
62
|
+
display: flex;
|
|
63
|
+
font-size: 0.875rem;
|
|
64
|
+
gap: 0.5rem;
|
|
65
|
+
line-height: 1.25rem;
|
|
66
|
+
|
|
67
|
+
&:not(:last-child) {
|
|
68
|
+
margin-bottom: 0.5rem;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
14
71
|
|
|
15
|
-
.
|
|
16
|
-
|
|
72
|
+
.product-card__metadata-icon {
|
|
73
|
+
color: var(--pgn-color-gray-500);
|
|
74
|
+
flex-shrink: 0;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
17
77
|
}
|
|
@@ -9,12 +9,14 @@ import messages from '../messages';
|
|
|
9
9
|
import { manageSubscriptionURL } from '../../../data/constants/app';
|
|
10
10
|
import { Link } from 'react-router-dom';
|
|
11
11
|
import { eventNames, trackSubscriptionEvent } from '../../../tracking/trackers/subscription';
|
|
12
|
+
import { isRenewEligible } from '../../../utils';
|
|
12
13
|
export const SubscriptionBanner = ({ learnerSubscriptionData }) => {
|
|
13
14
|
const { formatMessage } = useIntl();
|
|
14
15
|
const [isDismissed, setIsDismissed] = useState(false);
|
|
15
16
|
const [bannerBody, setBannerBody] = useState('');
|
|
16
17
|
const [bannerTitle, setBannerTitle] = useState('');
|
|
17
18
|
const [bannerVariant, setBannerVariant] = useState(undefined);
|
|
19
|
+
const showRenewButton = isRenewEligible();
|
|
18
20
|
const formatDate = utilHooks.useFormatDate();
|
|
19
21
|
const { status, subscriptionEndDate, subscriptionStartDate, currentPeriodEnd, trialEndDate, } = learnerSubscriptionData;
|
|
20
22
|
useEffect(() => {
|
|
@@ -107,7 +109,7 @@ export const SubscriptionBanner = ({ learnerSubscriptionData }) => {
|
|
|
107
109
|
setIsDismissed(false);
|
|
108
110
|
}, [status]);
|
|
109
111
|
const getSubscriptionAction = useMemo(() => {
|
|
110
|
-
if (
|
|
112
|
+
if (showRenewButton) {
|
|
111
113
|
return [
|
|
112
114
|
_jsx(Button, { "data-testid": "renew-button", className: "renew-button", variant: "primary", href: manageSubscriptionURL, onClick: () => trackSubscriptionEvent(eventNames.subscriptionBannerActionClicked, {
|
|
113
115
|
subscription_status: status,
|
|
@@ -124,7 +126,7 @@ export const SubscriptionBanner = ({ learnerSubscriptionData }) => {
|
|
|
124
126
|
];
|
|
125
127
|
}
|
|
126
128
|
return [];
|
|
127
|
-
}, [formatMessage, status]);
|
|
129
|
+
}, [formatMessage, status, showRenewButton]);
|
|
128
130
|
const subscriptionStatusIcons = {
|
|
129
131
|
TRIAL_ACTIVE: CheckCircle,
|
|
130
132
|
RENEWAL_PENDING: CheckCircle,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubscriptionBanner.js","sourceRoot":"","sources":["../../../../src/containers/SubscriptionBanner/components/SubscriptionBanner.tsx"],"names":[],"mappings":"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","sourcesContent":["import { FC, useEffect, useState, useMemo } from 'react';\nimport { Alert, Button, Variant } from '@openedx/paragon';\nimport { CheckCircle, Info } from '@openedx/paragon/icons';\nimport { useIntl } from '@openedx/frontend-base';\nimport moment from 'moment';\nimport { utilHooks } from '@src/hooks';\nimport messages from '../messages';\nimport { manageSubscriptionURL } from '@src/data/constants/app';\nimport { Link } from 'react-router-dom';\nimport { BannerItem } from '../types';\nimport { eventNames, trackSubscriptionEvent } from '@src/tracking/trackers/subscription';\n\nexport const SubscriptionBanner: FC<BannerItem> = ({ learnerSubscriptionData }) => {\n const { formatMessage } = useIntl();\n\n const [isDismissed, setIsDismissed] = useState(false);\n const [bannerBody, setBannerBody] = useState('');\n const [bannerTitle, setBannerTitle] = useState('');\n const [bannerVariant, setBannerVariant] = useState<Variant | undefined>(undefined);\n\n const formatDate = utilHooks.useFormatDate();\n\n const {\n status,\n subscriptionEndDate,\n subscriptionStartDate,\n currentPeriodEnd,\n trialEndDate,\n } = learnerSubscriptionData;\n\n useEffect(() => {\n if (!status) {\n setBannerTitle('');\n setBannerBody('');\n setBannerVariant(undefined);\n return;\n }\n\n const trialEndDateMoment = moment(trialEndDate).startOf('day');\n const today = moment().startOf('day');\n\n const trialDaysLeft = trialEndDateMoment.isValid()\n ? Math.max(0, trialEndDateMoment.diff(today, 'days'))\n : 0;\n\n const daysLeftAfterCancellation = moment(currentPeriodEnd).isValid()\n ? Math.max(0, moment(currentPeriodEnd).diff(today, 'days'))\n : 0;\n\n switch (status) {\n case 'RENEWAL_PENDING':\n setBannerVariant('success');\n setBannerTitle(formatMessage(messages.renewalPendingTitle));\n setBannerBody(\n formatMessage(messages.renewalPendingBody, {\n subscriptionRenewalDate: formatDate(\n currentPeriodEnd\n ),\n }),\n );\n break;\n\n case 'TRIAL_ACTIVE':\n setBannerVariant('success');\n\n if (trialDaysLeft === 0) {\n setBannerTitle(\n formatMessage(messages.activeTrialSubscriptionTitleToday),\n );\n } else if (trialDaysLeft === 1) {\n setBannerTitle(\n formatMessage(messages.activeTrialSubscriptionTitleTomorrow),\n );\n } else if (\n moment(subscriptionStartDate).isValid()\n && moment(subscriptionStartDate).isSame(moment(), 'day')\n ) {\n setBannerTitle(\n formatMessage(messages.activeSubscriptionTitle),\n );\n\n setBannerBody(\n formatMessage(messages.activeSubscriptionBody, {\n subscriptionRenewalDate: formatDate(\n currentPeriodEnd\n ),\n }),\n );\n\n return;\n } else {\n setBannerTitle(\n formatMessage(messages.activeTrialSubscriptionTitle, {\n daysLeft: trialDaysLeft,\n }),\n );\n }\n\n setBannerBody(\n formatMessage(messages.activeTrialSubscriptionBody, {\n trialEndDate: formatDate(trialEndDate),\n }),\n );\n break;\n\n case 'CANCEL_PENDING':\n setBannerVariant('light');\n setBannerTitle(\n formatMessage(messages.cancelledSubscriptionTitle, {\n daysLeft: daysLeftAfterCancellation,\n }),\n );\n setBannerBody(\n formatMessage(messages.cancelledSubscriptionBody, {\n subscriptionRenewalEndDate: formatDate(currentPeriodEnd),\n }),\n );\n break;\n\n case 'CANCELLED':\n setBannerVariant('light');\n setBannerTitle(\n formatMessage(messages.cancelledSubscriptionTitle, {\n daysLeft: daysLeftAfterCancellation,\n }),\n );\n setBannerBody(\n formatMessage(messages.cancelledSubscriptionBody, {\n subscriptionRenewalEndDate: formatDate(currentPeriodEnd),\n }),\n );\n break;\n\n case 'RENEWAL_FAILED':\n setBannerVariant('light');\n setBannerTitle(\n formatMessage(messages.renewalFailedTitle),\n );\n setBannerBody(\n formatMessage(messages.renewalFailedBody, {\n subscriptionRenewalDate: formatDate(\n currentPeriodEnd\n ),\n }),\n );\n break;\n\n default:\n break;\n }\n }, [\n status,\n formatDate,\n formatMessage,\n subscriptionEndDate,\n subscriptionStartDate,\n currentPeriodEnd,\n trialEndDate,\n ]);\n\n // Reset dismissal when the subscription status changes.\n useEffect(() => {\n setIsDismissed(false);\n }, [status]);\n\n const getSubscriptionAction = useMemo(() => {\n if (status === 'CANCELLED' || status === 'CANCEL_PENDING') {\n return [\n <Button\n key=\"renew-subscription\"\n data-testid=\"renew-button\"\n className=\"renew-button\"\n variant=\"primary\"\n href={manageSubscriptionURL}\n onClick={() => trackSubscriptionEvent(eventNames.subscriptionBannerActionClicked, {\n subscription_status: status,\n action: 'renew',\n })}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n role=\"link\"\n >\n {formatMessage(messages.renewSubscriptionButton)}\n </Button>,\n ];\n }\n\n if (status === 'RENEWAL_FAILED') {\n return [\n <Button\n key=\"renew-failed-subscription\"\n data-testid=\"renew-failed-button\"\n className=\"renew-failed-button\"\n variant=\"primary\"\n to={manageSubscriptionURL}\n onClick={() => trackSubscriptionEvent(eventNames.subscriptionBannerActionClicked, {\n subscription_status: status,\n action: 'renewal_failed',\n })}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n role=\"link\"\n as={Link}\n >\n {formatMessage(messages.renewalFailedButton)}\n </Button>,\n ];\n }\n\n return [];\n }, [formatMessage, status]);\n\n const subscriptionStatusIcons: Record<\n string,\n typeof Info | undefined\n > = {\n TRIAL_ACTIVE: CheckCircle,\n RENEWAL_PENDING: CheckCircle,\n };\n\n const bannerIcon = (subscriptionStatusIcons[status]\n && moment(subscriptionStartDate).isValid()\n && moment(subscriptionStartDate).isSame(moment(), 'day'))\n ? subscriptionStatusIcons[status]\n : undefined;\n\n const shouldShowBanner = Boolean(\n status\n && bannerTitle\n && bannerBody\n && !isDismissed\n && bannerVariant\n );\n\n useEffect(() => {\n if (shouldShowBanner) {\n trackSubscriptionEvent(eventNames.subscriptionBannerViewed, { subscription_status: status });\n }\n }, [shouldShowBanner, status]);\n\n const handleDismiss = () => {\n trackSubscriptionEvent(eventNames.subscriptionBannerDismissed, { subscription_status: status });\n setIsDismissed(true);\n };\n\n return (\n <div className=\"mt-4.5 mb-4.5\">\n {shouldShowBanner && (\n <Alert\n variant={bannerVariant}\n icon={bannerIcon}\n dismissible\n closeLabel=\"Dismiss\"\n onClose={handleDismiss}\n actions={getSubscriptionAction}\n >\n <Alert.Heading>{bannerTitle}</Alert.Heading>\n <p>{bannerBody}</p>\n </Alert>\n )}\n </div>\n );\n};\n\nexport default SubscriptionBanner;\n"]}
|
|
1
|
+
{"version":3,"file":"SubscriptionBanner.js","sourceRoot":"","sources":["../../../../src/containers/SubscriptionBanner/components/SubscriptionBanner.tsx"],"names":[],"mappings":"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","sourcesContent":["import { FC, useEffect, useState, useMemo } from 'react';\nimport { Alert, Button, Variant } from '@openedx/paragon';\nimport { CheckCircle, Info } from '@openedx/paragon/icons';\nimport { useIntl } from '@openedx/frontend-base';\nimport moment from 'moment';\nimport { utilHooks } from '@src/hooks';\nimport messages from '../messages';\nimport { manageSubscriptionURL } from '@src/data/constants/app';\nimport { Link } from 'react-router-dom';\nimport { BannerItem } from '../types';\nimport { eventNames, trackSubscriptionEvent } from '@src/tracking/trackers/subscription';\nimport { isRenewEligible } from '@src/utils';\n\nexport const SubscriptionBanner: FC<BannerItem> = ({ learnerSubscriptionData }) => {\n const { formatMessage } = useIntl();\n\n const [isDismissed, setIsDismissed] = useState(false);\n const [bannerBody, setBannerBody] = useState('');\n const [bannerTitle, setBannerTitle] = useState('');\n const [bannerVariant, setBannerVariant] = useState<Variant | undefined>(undefined);\n const showRenewButton = isRenewEligible();\n\n const formatDate = utilHooks.useFormatDate();\n\n const {\n status,\n subscriptionEndDate,\n subscriptionStartDate,\n currentPeriodEnd,\n trialEndDate,\n } = learnerSubscriptionData;\n\n useEffect(() => {\n if (!status) {\n setBannerTitle('');\n setBannerBody('');\n setBannerVariant(undefined);\n return;\n }\n\n const trialEndDateMoment = moment(trialEndDate).startOf('day');\n const today = moment().startOf('day');\n\n const trialDaysLeft = trialEndDateMoment.isValid()\n ? Math.max(0, trialEndDateMoment.diff(today, 'days'))\n : 0;\n\n const daysLeftAfterCancellation = moment(currentPeriodEnd).isValid()\n ? Math.max(0, moment(currentPeriodEnd).diff(today, 'days'))\n : 0;\n\n switch (status) {\n case 'RENEWAL_PENDING':\n setBannerVariant('success');\n setBannerTitle(formatMessage(messages.renewalPendingTitle));\n setBannerBody(\n formatMessage(messages.renewalPendingBody, {\n subscriptionRenewalDate: formatDate(\n currentPeriodEnd\n ),\n }),\n );\n break;\n\n case 'TRIAL_ACTIVE':\n setBannerVariant('success');\n\n if (trialDaysLeft === 0) {\n setBannerTitle(\n formatMessage(messages.activeTrialSubscriptionTitleToday),\n );\n } else if (trialDaysLeft === 1) {\n setBannerTitle(\n formatMessage(messages.activeTrialSubscriptionTitleTomorrow),\n );\n } else if (\n moment(subscriptionStartDate).isValid()\n && moment(subscriptionStartDate).isSame(moment(), 'day')\n ) {\n setBannerTitle(\n formatMessage(messages.activeSubscriptionTitle),\n );\n\n setBannerBody(\n formatMessage(messages.activeSubscriptionBody, {\n subscriptionRenewalDate: formatDate(\n currentPeriodEnd\n ),\n }),\n );\n\n return;\n } else {\n setBannerTitle(\n formatMessage(messages.activeTrialSubscriptionTitle, {\n daysLeft: trialDaysLeft,\n }),\n );\n }\n\n setBannerBody(\n formatMessage(messages.activeTrialSubscriptionBody, {\n trialEndDate: formatDate(trialEndDate),\n }),\n );\n break;\n\n case 'CANCEL_PENDING':\n setBannerVariant('light');\n setBannerTitle(\n formatMessage(messages.cancelledSubscriptionTitle, {\n daysLeft: daysLeftAfterCancellation,\n }),\n );\n setBannerBody(\n formatMessage(messages.cancelledSubscriptionBody, {\n subscriptionRenewalEndDate: formatDate(currentPeriodEnd),\n }),\n );\n break;\n\n case 'CANCELLED':\n setBannerVariant('light');\n setBannerTitle(\n formatMessage(messages.cancelledSubscriptionTitle, {\n daysLeft: daysLeftAfterCancellation,\n }),\n );\n setBannerBody(\n formatMessage(messages.cancelledSubscriptionBody, {\n subscriptionRenewalEndDate: formatDate(currentPeriodEnd),\n }),\n );\n break;\n\n case 'RENEWAL_FAILED':\n setBannerVariant('light');\n setBannerTitle(\n formatMessage(messages.renewalFailedTitle),\n );\n setBannerBody(\n formatMessage(messages.renewalFailedBody, {\n subscriptionRenewalDate: formatDate(\n currentPeriodEnd\n ),\n }),\n );\n break;\n\n default:\n break;\n }\n }, [\n status,\n formatDate,\n formatMessage,\n subscriptionEndDate,\n subscriptionStartDate,\n currentPeriodEnd,\n trialEndDate,\n ]);\n\n // Reset dismissal when the subscription status changes.\n useEffect(() => {\n setIsDismissed(false);\n }, [status]);\n\n const getSubscriptionAction = useMemo(() => {\n if (showRenewButton) {\n return [\n <Button\n key=\"renew-subscription\"\n data-testid=\"renew-button\"\n className=\"renew-button\"\n variant=\"primary\"\n href={manageSubscriptionURL}\n onClick={() => trackSubscriptionEvent(eventNames.subscriptionBannerActionClicked, {\n subscription_status: status,\n action: 'renew',\n })}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n role=\"link\"\n >\n {formatMessage(messages.renewSubscriptionButton)}\n </Button>,\n ];\n }\n\n if (status === 'RENEWAL_FAILED') {\n return [\n <Button\n key=\"renew-failed-subscription\"\n data-testid=\"renew-failed-button\"\n className=\"renew-failed-button\"\n variant=\"primary\"\n to={manageSubscriptionURL}\n onClick={() => trackSubscriptionEvent(eventNames.subscriptionBannerActionClicked, {\n subscription_status: status,\n action: 'renewal_failed',\n })}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n role=\"link\"\n as={Link}\n >\n {formatMessage(messages.renewalFailedButton)}\n </Button>,\n ];\n }\n\n return [];\n }, [formatMessage, status, showRenewButton]);\n\n const subscriptionStatusIcons: Record<\n string,\n typeof Info | undefined\n > = {\n TRIAL_ACTIVE: CheckCircle,\n RENEWAL_PENDING: CheckCircle,\n };\n\n const bannerIcon = (subscriptionStatusIcons[status]\n && moment(subscriptionStartDate).isValid()\n && moment(subscriptionStartDate).isSame(moment(), 'day'))\n ? subscriptionStatusIcons[status]\n : undefined;\n\n const shouldShowBanner = Boolean(\n status\n && bannerTitle\n && bannerBody\n && !isDismissed\n && bannerVariant\n );\n\n useEffect(() => {\n if (shouldShowBanner) {\n trackSubscriptionEvent(eventNames.subscriptionBannerViewed, { subscription_status: status });\n }\n }, [shouldShowBanner, status]);\n\n const handleDismiss = () => {\n trackSubscriptionEvent(eventNames.subscriptionBannerDismissed, { subscription_status: status });\n setIsDismissed(true);\n };\n\n return (\n <div className=\"mt-4.5 mb-4.5\">\n {shouldShowBanner && (\n <Alert\n variant={bannerVariant}\n icon={bannerIcon}\n dismissible\n closeLabel=\"Dismiss\"\n onClose={handleDismiss}\n actions={getSubscriptionAction}\n >\n <Alert.Heading>{bannerTitle}</Alert.Heading>\n <p>{bannerBody}</p>\n </Alert>\n )}\n </div>\n );\n};\n\nexport default SubscriptionBanner;\n"]}
|
|
@@ -10,6 +10,7 @@ import '../index.scss';
|
|
|
10
10
|
import { Cached, WarningFilled, Cancel } from '@openedx/paragon/icons';
|
|
11
11
|
import { subscriptionRenewalURL } from '../../../data/constants/app';
|
|
12
12
|
import { eventNames, trackSubscriptionEvent } from '../../../tracking/trackers/subscription';
|
|
13
|
+
import { isRenewEligible } from '../../../utils';
|
|
13
14
|
export const SubscriptionInformation = () => {
|
|
14
15
|
var _a, _b, _c, _d, _e;
|
|
15
16
|
const { data: subsData } = useInitializeSubsDashboard();
|
|
@@ -18,6 +19,7 @@ export const SubscriptionInformation = () => {
|
|
|
18
19
|
const [infoBody, setInfoBody] = useState('');
|
|
19
20
|
const [infoTitle, setInfoTitle] = useState('');
|
|
20
21
|
const status = (_a = subsData === null || subsData === void 0 ? void 0 : subsData.userSubscription) === null || _a === void 0 ? void 0 : _a.status;
|
|
22
|
+
const showRenewButton = isRenewEligible();
|
|
21
23
|
useEffect(() => {
|
|
22
24
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
23
25
|
if (!status) {
|
|
@@ -64,7 +66,7 @@ export const SubscriptionInformation = () => {
|
|
|
64
66
|
}
|
|
65
67
|
}, [formatDate, formatMessage, status, (_b = subsData === null || subsData === void 0 ? void 0 : subsData.userSubscription) === null || _b === void 0 ? void 0 : _b.planName, (_c = subsData === null || subsData === void 0 ? void 0 : subsData.userSubscription) === null || _c === void 0 ? void 0 : _c.currentPeriodEnd]);
|
|
66
68
|
const getSubscriptionAction = useMemo(() => {
|
|
67
|
-
if (
|
|
69
|
+
if (showRenewButton) {
|
|
68
70
|
return ([
|
|
69
71
|
_jsx(Button, { "data-testid": "renew-button", className: "renew-button", variant: "tertiary", href: subscriptionRenewalURL, onClick: () => {
|
|
70
72
|
var _a;
|
|
@@ -85,7 +87,7 @@ export const SubscriptionInformation = () => {
|
|
|
85
87
|
});
|
|
86
88
|
}, target: "_blank", rel: "noopener noreferrer", role: "link", children: formatMessage(messages.manageSubscriptionMessage) }, "manage-subscription"),
|
|
87
89
|
]);
|
|
88
|
-
}, [formatMessage, status, (_d = subsData === null || subsData === void 0 ? void 0 : subsData.userSubscription) === null || _d === void 0 ? void 0 : _d.planName]);
|
|
90
|
+
}, [formatMessage, status, (_d = subsData === null || subsData === void 0 ? void 0 : subsData.userSubscription) === null || _d === void 0 ? void 0 : _d.planName, showRenewButton]);
|
|
89
91
|
const subscriptionStatusIcons = {
|
|
90
92
|
ACTIVE: Cached,
|
|
91
93
|
TRIAL_ACTIVE: Cached,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubscriptionInformation.js","sourceRoot":"","sources":["../../../../src/containers/SubscriptionInformation/components/SubscriptionInformation.tsx"],"names":[],"mappings":"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","sourcesContent":["import { FC, useEffect, useMemo, useState } from 'react';\nimport { Alert, Button, Icon } from '@openedx/paragon';\nimport { useIntl } from '@openedx/frontend-base';\nimport { utilHooks } from '@src/hooks';\nimport { useInitializeSubsDashboard } from '@src/data/hooks';\nimport messages from '../messages';\nimport { manageSubscriptionURL } from '@src/data/constants/app';\nimport '../index.scss';\nimport { Cached, WarningFilled, Cancel, Info } from '@openedx/paragon/icons';\nimport { subscriptionRenewalURL } from '@src/data/constants/app';\nimport { eventNames, trackSubscriptionEvent } from '@src/tracking/trackers/subscription';\n\nexport const SubscriptionInformation: FC = () => {\n const { data: subsData } = useInitializeSubsDashboard();\n const { formatMessage } = useIntl();\n const formatDate = utilHooks.useFormatDate();\n const [infoBody, setInfoBody] = useState('');\n const [infoTitle, setInfoTitle] = useState('');\n const status = subsData?.userSubscription?.status;\n\n useEffect(() => {\n if (!status) {\n setInfoTitle('');\n setInfoBody('');\n return;\n }\n\n switch (status) {\n case 'ACTIVE':\n case 'TRIAL_ACTIVE':\n case 'RENEWAL_PENDING':\n setInfoTitle(formatMessage(messages.activeSubscriptionTitle, {\n subscriptionStatus: status.split('_').map(part => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join(' '),\n planName: subsData?.userSubscription?.planName,\n }));\n setInfoBody(formatMessage(messages.renewalMessage, {\n subscriptionRenewalDate: formatDate(subsData?.userSubscription?.currentPeriodEnd),\n }));\n break;\n case 'CANCEL_PENDING':\n setInfoTitle(formatMessage(messages.cancelledSubscriptionTitle, {\n subscriptionStatus: status.split('_').map(part => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join(' '),\n planName: subsData?.userSubscription?.planName,\n }));\n setInfoBody(formatMessage(messages.cancelledSubscriptionBody, {\n subscriptionRenewalEndDate: formatDate(subsData?.userSubscription?.currentPeriodEnd),\n }));\n break;\n case 'CANCELLED':\n setInfoTitle(formatMessage(messages.cancelledSubscriptionTitle, {\n subscriptionStatus: status.charAt(0).toUpperCase() + status.slice(1).toLowerCase(),\n planName: subsData?.userSubscription?.planName,\n }));\n setInfoBody(formatMessage(messages.cancelledSubscriptionBody, {\n subscriptionRenewalEndDate: formatDate(subsData?.userSubscription?.currentPeriodEnd),\n }));\n break;\n case 'RENEWAL_FAILED': // also known as 'Payment Error' in figma designs\n setInfoTitle(formatMessage(messages.renewalFailedTitle));\n setInfoBody(formatMessage(messages.renewalFailedBody, {\n subscriptionRenewalDate: formatDate(subsData?.userSubscription?.currentPeriodEnd),\n }));\n break;\n }\n }, [formatDate, formatMessage, status, subsData?.userSubscription?.planName, subsData?.userSubscription?.currentPeriodEnd]);\n\n const getSubscriptionAction = useMemo(() => {\n if (status === 'CANCELLED' || status === 'CANCEL_PENDING') {\n return (\n [\n <Button\n key=\"renew-subscription\"\n data-testid=\"renew-button\"\n className=\"renew-button\"\n variant=\"tertiary\"\n href={subscriptionRenewalURL}\n onClick={() => trackSubscriptionEvent(eventNames.renewSubscriptionClicked, {\n subscription_status: status,\n plan_name: subsData?.userSubscription?.planName,\n })}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n role=\"link\"\n >\n {formatMessage(messages.renewSubscriptionButton)}\n </Button>,\n ]\n );\n } else\n return (\n [\n <Button\n key=\"manage-subscription\"\n variant=\"tertiary\"\n data-testid=\"manage-button\"\n href={manageSubscriptionURL}\n onClick={() => trackSubscriptionEvent(eventNames.manageSubscriptionClicked, {\n subscription_status: status,\n plan_name: subsData?.userSubscription?.planName,\n })}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n role=\"link\"\n >\n {formatMessage(messages.manageSubscriptionMessage)}\n </Button>,\n ]\n );\n }, [formatMessage, status, subsData?.userSubscription?.planName]);\n\n const subscriptionStatusIcons: Record<string, typeof Info | undefined> = {\n ACTIVE: Cached,\n TRIAL_ACTIVE: Cached,\n CANCELLED: Cancel,\n RENEWAL_FAILED: WarningFilled,\n RENEWAL_PENDING: Cached,\n CANCEL_PENDING: Cancel,\n };\n\n const bannerIcon = subscriptionStatusIcons[status] ?? undefined;\n\n return (\n <div className=\"container subscription-information py-5 px-4\">\n <h2 className=\"mb-4 my-subscription-heading\">{formatMessage(messages.mySubscriptionHeading)}</h2>\n <Alert\n dismissible={false}\n show={true}\n actions={getSubscriptionAction}\n className=\"subscription-status-alert bg-white\"\n >\n <Alert.Heading as=\"h6\">\n <Icon src={bannerIcon} className={`icon mr-1 ${bannerIcon === WarningFilled ? 'warning-icon text-warning-500' : ''}`} data-testid=\"subscription-status-icon\" />\n {infoTitle}\n </Alert.Heading>\n <p>\n {infoBody}\n </p>\n </Alert>\n </div>\n );\n};\n"]}
|
|
1
|
+
{"version":3,"file":"SubscriptionInformation.js","sourceRoot":"","sources":["../../../../src/containers/SubscriptionInformation/components/SubscriptionInformation.tsx"],"names":[],"mappings":"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","sourcesContent":["import { FC, useEffect, useMemo, useState } from 'react';\nimport { Alert, Button, Icon } from '@openedx/paragon';\nimport { useIntl } from '@openedx/frontend-base';\nimport { utilHooks } from '@src/hooks';\nimport { useInitializeSubsDashboard } from '@src/data/hooks';\nimport messages from '../messages';\nimport { manageSubscriptionURL } from '@src/data/constants/app';\nimport '../index.scss';\nimport { Cached, WarningFilled, Cancel, Info } from '@openedx/paragon/icons';\nimport { subscriptionRenewalURL } from '@src/data/constants/app';\nimport { eventNames, trackSubscriptionEvent } from '@src/tracking/trackers/subscription';\nimport { isRenewEligible } from '@src/utils';\n\nexport const SubscriptionInformation: FC = () => {\n const { data: subsData } = useInitializeSubsDashboard();\n const { formatMessage } = useIntl();\n const formatDate = utilHooks.useFormatDate();\n const [infoBody, setInfoBody] = useState('');\n const [infoTitle, setInfoTitle] = useState('');\n const status = subsData?.userSubscription?.status;\n const showRenewButton = isRenewEligible();\n\n useEffect(() => {\n if (!status) {\n setInfoTitle('');\n setInfoBody('');\n return;\n }\n\n switch (status) {\n case 'ACTIVE':\n case 'TRIAL_ACTIVE':\n case 'RENEWAL_PENDING':\n setInfoTitle(formatMessage(messages.activeSubscriptionTitle, {\n subscriptionStatus: status.split('_').map(part => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join(' '),\n planName: subsData?.userSubscription?.planName,\n }));\n setInfoBody(formatMessage(messages.renewalMessage, {\n subscriptionRenewalDate: formatDate(subsData?.userSubscription?.currentPeriodEnd),\n }));\n break;\n case 'CANCEL_PENDING':\n setInfoTitle(formatMessage(messages.cancelledSubscriptionTitle, {\n subscriptionStatus: status.split('_').map(part => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join(' '),\n planName: subsData?.userSubscription?.planName,\n }));\n setInfoBody(formatMessage(messages.cancelledSubscriptionBody, {\n subscriptionRenewalEndDate: formatDate(subsData?.userSubscription?.currentPeriodEnd),\n }));\n break;\n case 'CANCELLED':\n setInfoTitle(formatMessage(messages.cancelledSubscriptionTitle, {\n subscriptionStatus: status.charAt(0).toUpperCase() + status.slice(1).toLowerCase(),\n planName: subsData?.userSubscription?.planName,\n }));\n setInfoBody(formatMessage(messages.cancelledSubscriptionBody, {\n subscriptionRenewalEndDate: formatDate(subsData?.userSubscription?.currentPeriodEnd),\n }));\n break;\n case 'RENEWAL_FAILED': // also known as 'Payment Error' in figma designs\n setInfoTitle(formatMessage(messages.renewalFailedTitle));\n setInfoBody(formatMessage(messages.renewalFailedBody, {\n subscriptionRenewalDate: formatDate(subsData?.userSubscription?.currentPeriodEnd),\n }));\n break;\n }\n }, [formatDate, formatMessage, status, subsData?.userSubscription?.planName, subsData?.userSubscription?.currentPeriodEnd]);\n\n const getSubscriptionAction = useMemo(() => {\n if (showRenewButton) {\n return (\n [\n <Button\n key=\"renew-subscription\"\n data-testid=\"renew-button\"\n className=\"renew-button\"\n variant=\"tertiary\"\n href={subscriptionRenewalURL}\n onClick={() => trackSubscriptionEvent(eventNames.renewSubscriptionClicked, {\n subscription_status: status,\n plan_name: subsData?.userSubscription?.planName,\n })}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n role=\"link\"\n >\n {formatMessage(messages.renewSubscriptionButton)}\n </Button>,\n ]\n );\n } else\n return (\n [\n <Button\n key=\"manage-subscription\"\n variant=\"tertiary\"\n data-testid=\"manage-button\"\n href={manageSubscriptionURL}\n onClick={() => trackSubscriptionEvent(eventNames.manageSubscriptionClicked, {\n subscription_status: status,\n plan_name: subsData?.userSubscription?.planName,\n })}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n role=\"link\"\n >\n {formatMessage(messages.manageSubscriptionMessage)}\n </Button>,\n ]\n );\n }, [formatMessage, status, subsData?.userSubscription?.planName, showRenewButton]);\n\n const subscriptionStatusIcons: Record<string, typeof Info | undefined> = {\n ACTIVE: Cached,\n TRIAL_ACTIVE: Cached,\n CANCELLED: Cancel,\n RENEWAL_FAILED: WarningFilled,\n RENEWAL_PENDING: Cached,\n CANCEL_PENDING: Cancel,\n };\n\n const bannerIcon = subscriptionStatusIcons[status] ?? undefined;\n\n return (\n <div className=\"container subscription-information py-5 px-4\">\n <h2 className=\"mb-4 my-subscription-heading\">{formatMessage(messages.mySubscriptionHeading)}</h2>\n <Alert\n dismissible={false}\n show={true}\n actions={getSubscriptionAction}\n className=\"subscription-status-alert bg-white\"\n >\n <Alert.Heading as=\"h6\">\n <Icon src={bannerIcon} className={`icon mr-1 ${bannerIcon === WarningFilled ? 'warning-icon text-warning-500' : ''}`} data-testid=\"subscription-status-icon\" />\n {infoTitle}\n </Alert.Heading>\n <p>\n {infoBody}\n </p>\n </Alert>\n </div>\n );\n};\n"]}
|
|
@@ -8,4 +8,6 @@ export declare const searchKeys: {
|
|
|
8
8
|
courses: (query: string, tags: string[], page: number) => readonly ["search", "courses", string, string[], number];
|
|
9
9
|
popular: (productType: ProductType, limit: number, skill?: Skill) => readonly ["search", "popular", ProductType, number, string | null];
|
|
10
10
|
};
|
|
11
|
+
export declare const getProductSlugFromMarketingUrl: (marketingUrl: string | null | undefined) => string | null;
|
|
12
|
+
export declare const buildEnrollPdpPath: (productType: string | null | undefined, marketingUrl: string | null | undefined) => string | null;
|
|
11
13
|
export declare const usePopularCoursesAndProgramsData: (searchClient: SearchClient | null, enabled: boolean, productType?: ProductType, skill?: Skill) => UseQueryResult<ProductCardItem[]>;
|
|
@@ -23,6 +23,31 @@ const hitPartner = (hit) => {
|
|
|
23
23
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
24
24
|
return (Array.isArray(hit.partner) ? hit.partner[0] : (_l = (_k = (_g = (_d = (_a = hit.partner) !== null && _a !== void 0 ? _a : (_c = (_b = hit.owners) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.name) !== null && _d !== void 0 ? _d : (_f = (_e = hit.authoring_organizations) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.name) !== null && _g !== void 0 ? _g : (_j = (_h = hit.partners) === null || _h === void 0 ? void 0 : _h[0]) === null || _j === void 0 ? void 0 : _j.name) !== null && _k !== void 0 ? _k : hit.institution) !== null && _l !== void 0 ? _l : '');
|
|
25
25
|
};
|
|
26
|
+
export const getProductSlugFromMarketingUrl = (marketingUrl) => {
|
|
27
|
+
var _a, _b;
|
|
28
|
+
if (!marketingUrl) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
const pathname = new URL(marketingUrl).pathname;
|
|
33
|
+
const parts = pathname.split('/').filter(Boolean);
|
|
34
|
+
return (_a = parts[parts.length - 1]) !== null && _a !== void 0 ? _a : null;
|
|
35
|
+
}
|
|
36
|
+
catch (_c) {
|
|
37
|
+
const parts = marketingUrl.split('/').filter(Boolean);
|
|
38
|
+
return (_b = parts[parts.length - 1]) !== null && _b !== void 0 ? _b : null;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
export const buildEnrollPdpPath = (productType, marketingUrl) => {
|
|
42
|
+
const slug = getProductSlugFromMarketingUrl(marketingUrl);
|
|
43
|
+
if (!slug) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const kind = (productType !== null && productType !== void 0 ? productType : '').toLowerCase() === 'program'
|
|
47
|
+
? 'program'
|
|
48
|
+
: 'course';
|
|
49
|
+
return `/subscription-enroll/${kind}/${encodeURIComponent(slug)}`;
|
|
50
|
+
};
|
|
26
51
|
export const usePopularCoursesAndProgramsData = (searchClient, enabled, productType = PRODUCT_TYPE_COURSE, skill) => useQuery({
|
|
27
52
|
queryKey: searchKeys.popular(productType, 4, skill),
|
|
28
53
|
queryFn: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -35,7 +60,7 @@ export const usePopularCoursesAndProgramsData = (searchClient, enabled, productT
|
|
|
35
60
|
title: (_b = (_a = hit.title) !== null && _a !== void 0 ? _a : hit.name) !== null && _b !== void 0 ? _b : 'Untitled',
|
|
36
61
|
primary_description: (_e = (_d = (_c = hitDetails.primary_description) !== null && _c !== void 0 ? _c : hitDetails.short_description) !== null && _d !== void 0 ? _d : hitDetails.description) !== null && _e !== void 0 ? _e : '',
|
|
37
62
|
url: (_g = (_f = hitDetails.card_image_url) !== null && _f !== void 0 ? _f : hitDetails.image_url) !== null && _g !== void 0 ? _g : '',
|
|
38
|
-
marketing_url: (_h = hitDetails.
|
|
63
|
+
marketing_url: buildEnrollPdpPath((_h = hitDetails.product) !== null && _h !== void 0 ? _h : 'Course', hitDetails.marketing_url) || '',
|
|
39
64
|
thumbnail: (_p = (_o = (_m = (_l = (_k = (_j = hitDetails.owners) === null || _j === void 0 ? void 0 : _j[0]) === null || _k === void 0 ? void 0 : _k.logoImageUrl) !== null && _l !== void 0 ? _l : hitDetails.organization_logo_override) !== null && _m !== void 0 ? _m : hitDetails.organization_logo_url) !== null && _o !== void 0 ? _o : hitDetails.partner_logo_url) !== null && _p !== void 0 ? _p : '',
|
|
40
65
|
content_type: (_r = (_q = hitDetails.program_type) !== null && _q !== void 0 ? _q : hitDetails.product) !== null && _r !== void 0 ? _r : 'Course',
|
|
41
66
|
product: productType,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePopularCoursesAndPrograms.js","sourceRoot":"","sources":["../../src/hooks/usePopularCoursesAndPrograms.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,QAAQ,EAAkB,MAAM,uBAAuB,CAAC;AAGjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,iFAAiF;AACjF,oDAAoD;AAEpD,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,GAAG,EAAE,CAAC,QAAQ,CAAU;IACxB,QAAQ,EAAE,CAAC,KAAa,EAAE,IAAc,EAAE,EAAE,CAC1C,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,CAAU;IACvD,OAAO,EAAE,CAAC,KAAa,EAAE,IAAc,EAAE,IAAY,EAAE,EAAE,CACvD,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAU;IAC5D,OAAO,EAAE,CAAC,WAAwB,EAAE,KAAa,EAAE,KAAa,EAAE,EAAE,CAClE,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,IAAI,CAAU;CAC7E,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,GAAQ,EAAU,EAAE;;IAAC,OAAA,CACvC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAA,MAAA,MAAA,MAAA,MAAA,GAAG,CAAC,OAAO,mCACpD,MAAA,MAAA,GAAG,CAAC,MAAM,0CAAG,CAAC,CAAC,0CAAE,IAAI,mCACrB,MAAA,MAAA,GAAG,CAAC,uBAAuB,0CAAG,CAAC,CAAC,0CAAE,IAAI,mCACtC,MAAA,MAAA,GAAG,CAAC,QAAQ,0CAAG,CAAC,CAAC,0CAAE,IAAI,mCACvB,GAAG,CAAC,WAAW,mCACf,EAAE,CACR,CAAA;CAAA,CAAC;AAEF,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAC9C,YAAiC,EACjC,OAAgB,EAChB,cAA2B,mBAAmB,EAC9C,KAAa,EACsB,EAAE,CACrC,QAAQ,CAAC;IACP,QAAQ,EAAE,UAAU,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,EAAE,KAAK,CAAC;IACnD,OAAO,EAAE,GAAS,EAAE;QAClB,MAAM,IAAI,GAAG,MAAM,oBAAoB,CAAC,YAAa,EAAE,WAAW,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QAC9E,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAmB,EAAE;;YACvC,MAAM,UAAU,GAAG,GAuBlB,CAAC;YAEF,OAAO;gBACL,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,KAAK,EAAE,MAAA,MAAA,GAAG,CAAC,KAAK,mCAAI,GAAG,CAAC,IAAI,mCAAI,UAAU;gBAC1C,mBAAmB,EAAE,MAAA,MAAA,MAAA,UAAU,CAAC,mBAAmB,mCAAI,UAAU,CAAC,iBAAiB,mCAAI,UAAU,CAAC,WAAW,mCAAI,EAAE;gBACnH,GAAG,EAAE,MAAA,MAAA,UAAU,CAAC,cAAc,mCAAI,UAAU,CAAC,SAAS,mCAAI,EAAE;gBAC5D,aAAa,EAAE,MAAA,UAAU,CAAC,
|
|
1
|
+
{"version":3,"file":"usePopularCoursesAndPrograms.js","sourceRoot":"","sources":["../../src/hooks/usePopularCoursesAndPrograms.ts"],"names":[],"mappings":"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","sourcesContent":["import { useQuery, UseQueryResult } from '@tanstack/react-query';\nimport { SearchClient } from 'algoliasearch';\nimport { ProductType, Skill } from '@src/types/types';\nimport { PRODUCT_TYPE_COURSE } from '@src/constants';\nimport { fetchPopularProducts } from '@src/utils/algoliaUtils';\nimport { ProductCardItem } from '@src/containers/ProductCard/data/types';\nimport { firstOf } from './utils';\n\n// ─── Query key factories ──────────────────────────────────────────────────────\n// Centralised so cache invalidation is never a typo\n\nexport const searchKeys = {\n all: ['search'] as const,\n programs: (query: string, tags: string[]) =>\n [...searchKeys.all, 'programs', query, tags] as const,\n courses: (query: string, tags: string[], page: number) =>\n [...searchKeys.all, 'courses', query, tags, page] as const,\n popular: (productType: ProductType, limit: number, skill?: Skill) =>\n [...searchKeys.all, 'popular', productType, limit, skill ?? null] as const,\n};\n\nconst hitPartner = (hit: any): string => (\n Array.isArray(hit.partner) ? hit.partner[0] : hit.partner\n ?? hit.owners?.[0]?.name\n ?? hit.authoring_organizations?.[0]?.name\n ?? hit.partners?.[0]?.name\n ?? hit.institution\n ?? ''\n);\n\nexport const getProductSlugFromMarketingUrl = (\n marketingUrl: string | null | undefined,\n): string | null => {\n if (!marketingUrl) {\n return null;\n }\n\n try {\n const pathname = new URL(marketingUrl).pathname;\n const parts = pathname.split('/').filter(Boolean);\n return parts[parts.length - 1] ?? null;\n } catch {\n const parts = marketingUrl.split('/').filter(Boolean);\n return parts[parts.length - 1] ?? null;\n }\n};\n\nexport const buildEnrollPdpPath = (\n productType: string | null | undefined,\n marketingUrl: string | null | undefined,\n): string | null => {\n const slug = getProductSlugFromMarketingUrl(marketingUrl);\n if (!slug) {\n return null;\n }\n\n const kind = (productType ?? '').toLowerCase() === 'program'\n ? 'program'\n : 'course';\n\n return `/subscription-enroll/${kind}/${encodeURIComponent(slug)}`;\n};\n\nexport const usePopularCoursesAndProgramsData = (\n searchClient: SearchClient | null,\n enabled: boolean,\n productType: ProductType = PRODUCT_TYPE_COURSE,\n skill?: Skill,\n): UseQueryResult<ProductCardItem[]> =>\n useQuery({\n queryKey: searchKeys.popular(productType, 4, skill),\n queryFn: async () => {\n const hits = await fetchPopularProducts(searchClient!, productType, 4, skill);\n return hits.map((hit): ProductCardItem => {\n const hitDetails = hit as {\n short_description?: string,\n primary_description?: string,\n description?: string,\n marketing_url?: string,\n image_url?: string,\n card_image_url?: string,\n organization_logo_override?: string,\n content_type?: string,\n program_type?: string,\n product?: string,\n partner?: string,\n weeks_to_complete?: number,\n level?: string,\n subject?: string[],\n owners?: { logoImageUrl?: string }[],\n organization_logo_url?: string,\n partner_logo_url?: string,\n level_type?: string,\n authoring_organizations?: [],\n partners?: [],\n institution?: string,\n course_titles?: string[],\n };\n\n return {\n objectID: hit.objectID,\n title: hit.title ?? hit.name ?? 'Untitled',\n primary_description: hitDetails.primary_description ?? hitDetails.short_description ?? hitDetails.description ?? '',\n url: hitDetails.card_image_url ?? hitDetails.image_url ?? '',\n marketing_url: buildEnrollPdpPath(hitDetails.product ?? 'Course', hitDetails.marketing_url) || '',\n thumbnail: hitDetails.owners?.[0]?.logoImageUrl ?? hitDetails.organization_logo_override ?? hitDetails.organization_logo_url ?? hitDetails.partner_logo_url ?? '',\n content_type: hitDetails.program_type ?? hitDetails.product ?? 'Course',\n product: productType,\n partner: hitPartner(hit) ?? '',\n weeks_to_complete: hitDetails.weeks_to_complete ?? undefined,\n level: firstOf(hitDetails.level) ?? hitDetails.level_type ?? null,\n subject: hitDetails?.course_titles ? hitDetails?.course_titles : undefined,\n };\n });\n },\n enabled: !!searchClient && enabled,\n staleTime: 1000 * 60 * 10,\n });\n"]}
|
|
@@ -13,6 +13,7 @@ export interface CommonTrackingProps {
|
|
|
13
13
|
trial_end_date?: string | null;
|
|
14
14
|
isSubscriber?: boolean;
|
|
15
15
|
opt_in?: boolean | null;
|
|
16
|
+
isUserSuspended?: boolean | null | undefined;
|
|
16
17
|
}
|
|
17
18
|
export declare const setCommonTrackingProps: (props: CommonTrackingProps) => void;
|
|
18
19
|
export declare const getCommonTrackingProps: () => CommonTrackingProps;
|
|
@@ -6,7 +6,7 @@ export const setCommonTrackingProps = (props) => {
|
|
|
6
6
|
export const getCommonTrackingProps = () => commonProps;
|
|
7
7
|
// Single place that maps the subs/init API response -> tracking props
|
|
8
8
|
export const mapSubsInitToTrackingProps = (data) => {
|
|
9
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
9
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
10
10
|
return ({
|
|
11
11
|
free_trial_status: (_a = data === null || data === void 0 ? void 0 : data.userSubscription) === null || _a === void 0 ? void 0 : _a.trialActive,
|
|
12
12
|
subscription_status: (_b = data === null || data === void 0 ? void 0 : data.userSubscription) === null || _b === void 0 ? void 0 : _b.status,
|
|
@@ -22,6 +22,7 @@ export const mapSubsInitToTrackingProps = (data) => {
|
|
|
22
22
|
experimentation: '',
|
|
23
23
|
device_type: '',
|
|
24
24
|
isSubscriber: (_k = data === null || data === void 0 ? void 0 : data.userSubscription) === null || _k === void 0 ? void 0 : _k.isSubscriber,
|
|
25
|
+
isUserSuspended: (_m = (_l = data === null || data === void 0 ? void 0 : data.userSubscription) === null || _l === void 0 ? void 0 : _l.tIsUserSuspended) !== null && _m !== void 0 ? _m : null
|
|
25
26
|
});
|
|
26
27
|
};
|
|
27
28
|
//# sourceMappingURL=trackingContext.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trackingContext.js","sourceRoot":"","sources":["../../src/tracking/trackingContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"trackingContext.js","sourceRoot":"","sources":["../../src/tracking/trackingContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAoB9D,IAAI,WAAW,GAAwB,EAAE,CAAC;AAE1C,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,KAA0B,EAAE,EAAE;IACnE,WAAW,mCAAQ,WAAW,GAAK,KAAK,CAAE,CAAC;AAC7C,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAwB,EAAE,CAAC,WAAW,CAAC;AAE7E,sEAAsE;AACtE,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,IAAS,EAAuB,EAAE;;IAAC,OAAA,CAAC;QAC7E,iBAAiB,EAAE,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,gBAAgB,0CAAE,WAAW;QACtD,mBAAmB,EAAE,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,gBAAgB,0CAAE,MAAM;QACnD,iBAAiB,EAAE,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,gBAAgB,0CAAE,gBAAgB;QAC3D,uBAAuB,EAAE,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,gBAAgB,0CAAE,qBAAqB;QACtE,qBAAqB,EAAE,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,gBAAgB,0CAAE,mBAAmB;QAClE,kBAAkB,EAAE,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,gBAAgB,0CAAE,gBAAgB;QAC5D,cAAc,EAAE,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,gBAAgB,0CAAE,YAAY;QACpD,UAAU,EAAE,MAAA,oBAAoB,EAAE,0CAAE,KAAK;QACzC,cAAc,EAAE,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,gBAAgB,0CAAE,aAAa;QACrD,MAAM,EAAE,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,MAAM;QACpB,UAAU,EAAE,EAAE;QACd,eAAe,EAAE,EAAE;QACnB,WAAW,EAAE,EAAE;QACf,YAAY,EAAE,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,gBAAgB,0CAAE,YAAY;QAClD,eAAe,EAAE,MAAA,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,gBAAgB,0CAAE,gBAAgB,mCAAI,IAAI;KAClE,CAAC,CAAA;CAAA,CAAC","sourcesContent":["import { getAuthenticatedUser } from '@openedx/frontend-base';\n\nexport interface CommonTrackingProps {\n free_trial_status?: string,\n subscription_status?: string,\n subscription_tier?: string,\n payment_method?: string | null,\n user_email?: string | null,\n session_id?: string | null,\n experimentation?: string | null,\n device_type?: string | null,\n subscription_start_date?: string | null,\n subscription_end_date?: string | null,\n current_period_end?: string | null,\n trial_end_date?: string | null,\n isSubscriber?: boolean,\n opt_in?: boolean | null,\n isUserSuspended?: boolean | null | undefined,\n}\n\nlet commonProps: CommonTrackingProps = {};\n\nexport const setCommonTrackingProps = (props: CommonTrackingProps) => {\n commonProps = { ...commonProps, ...props };\n};\n\nexport const getCommonTrackingProps = (): CommonTrackingProps => commonProps;\n\n// Single place that maps the subs/init API response -> tracking props\nexport const mapSubsInitToTrackingProps = (data: any): CommonTrackingProps => ({\n free_trial_status: data?.userSubscription?.trialActive,\n subscription_status: data?.userSubscription?.status,\n subscription_tier: data?.userSubscription?.billingFrequency,\n subscription_start_date: data?.userSubscription?.subscriptionStartDate,\n subscription_end_date: data?.userSubscription?.subscriptionEndDate,\n current_period_end: data?.userSubscription?.currentPeriodEnd,\n trial_end_date: data?.userSubscription?.trialEndDate,\n user_email: getAuthenticatedUser()?.email,\n payment_method: data?.userSubscription?.paymentMethod,\n opt_in: data?.opt_in,\n session_id: '',\n experimentation: '',\n device_type: '',\n isSubscriber: data?.userSubscription?.isSubscriber,\n isUserSuspended: data?.userSubscription?.tIsUserSuspended ?? null\n});\n"]}
|
package/dist/utils/index.d.ts
CHANGED
package/dist/utils/index.js
CHANGED
|
@@ -3,4 +3,5 @@ export { default as StrictDict } from './StrictDict';
|
|
|
3
3
|
export { default as keyStore } from './keyStore';
|
|
4
4
|
export { default as dateFormatter } from './dateFormatter';
|
|
5
5
|
export { useViewport } from './responsiveUtils';
|
|
6
|
+
export { isRenewEligible } from './isRenewEligible';
|
|
6
7
|
//# sourceMappingURL=index.js.map
|
package/dist/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.js"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AAErC,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC","sourcesContent":["export const nullMethod = () => ({});\n\nexport { default as StrictDict } from './StrictDict';\nexport { default as keyStore } from './keyStore';\nexport { default as dateFormatter } from './dateFormatter';\nexport { useViewport } from './responsiveUtils';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.js"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AAErC,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC","sourcesContent":["export const nullMethod = () => ({});\n\nexport { default as StrictDict } from './StrictDict';\nexport { default as keyStore } from './keyStore';\nexport { default as dateFormatter } from './dateFormatter';\nexport { useViewport } from './responsiveUtils';\nexport { isRenewEligible } from './isRenewEligible';\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const isRenewEligible: () => boolean;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { getCommonTrackingProps } from '../tracking/trackingContext';
|
|
2
|
+
export const isRenewEligible = () => {
|
|
3
|
+
const { payment_method, subscription_status, isUserSuspended } = getCommonTrackingProps();
|
|
4
|
+
switch (payment_method === null || payment_method === void 0 ? void 0 : payment_method.toLowerCase()) {
|
|
5
|
+
case 'stripe':
|
|
6
|
+
return (subscription_status === 'RENEWAL_FAILED'
|
|
7
|
+
|| subscription_status === 'CANCEL_PENDING');
|
|
8
|
+
case 'paypal':
|
|
9
|
+
// User paused subscription or 3 renewal failures
|
|
10
|
+
if (isUserSuspended)
|
|
11
|
+
return true;
|
|
12
|
+
// First renewal failure, grace period applies
|
|
13
|
+
if (subscription_status === 'RENEWAL_FAILED')
|
|
14
|
+
return false;
|
|
15
|
+
return false;
|
|
16
|
+
default:
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=isRenewEligible.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isRenewEligible.js","sourceRoot":"","sources":["../../src/utils/isRenewEligible.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAEvE,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,EAAE;IAClC,MAAM,EAAE,cAAc,EAAE,mBAAmB,EAAE,eAAe,EAAE,GAAG,sBAAsB,EAAE,CAAC;IAC1F,QAAQ,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAE,WAAW,EAAE,EAAE,CAAC;QACtC,KAAK,QAAQ;YACX,OAAO,CACL,mBAAmB,KAAK,gBAAgB;mBACrC,mBAAmB,KAAK,gBAAgB,CAC5C,CAAC;QAEJ,KAAK,QAAQ;YACX,iDAAiD;YACjD,IAAI,eAAe;gBACjB,OAAO,IAAI,CAAC;YAEd,8CAA8C;YAC9C,IAAI,mBAAmB,KAAK,gBAAgB;gBAC1C,OAAO,KAAK,CAAC;YAEf,OAAO,KAAK,CAAC;QAEf;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC,CAAC","sourcesContent":["import { getCommonTrackingProps } from '@src/tracking/trackingContext';\n\nexport const isRenewEligible = () => {\n const { payment_method, subscription_status, isUserSuspended } = getCommonTrackingProps();\n switch (payment_method?.toLowerCase()) {\n case 'stripe':\n return (\n subscription_status === 'RENEWAL_FAILED'\n || subscription_status === 'CANCEL_PENDING'\n );\n\n case 'paypal':\n // User paused subscription or 3 renewal failures\n if (isUserSuspended)\n return true;\n\n // First renewal failure, grace period applies\n if (subscription_status === 'RENEWAL_FAILED')\n return false;\n\n return false;\n\n default:\n return false;\n }\n};\n"]}
|