@edx/frontend-app-subscription-learner-dashboard 1.24.0 → 1.25.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.
- package/dist/containers/Dashboard/index.js +5 -5
- package/dist/containers/Dashboard/index.js.map +1 -1
- package/dist/containers/SubscriptionBanner/components/SubscriptionBanner.d.ts +2 -1
- package/dist/containers/SubscriptionBanner/components/SubscriptionBanner.js +65 -63
- package/dist/containers/SubscriptionBanner/components/SubscriptionBanner.js.map +1 -1
- package/dist/containers/SubscriptionBanner/messages.js +4 -4
- package/dist/containers/SubscriptionBanner/messages.js.map +1 -1
- package/package.json +1 -1
|
@@ -13,22 +13,22 @@ import DashboardLayout from './DashboardLayout';
|
|
|
13
13
|
import hooks from './hooks';
|
|
14
14
|
import './index.scss';
|
|
15
15
|
import { SubscriptionBanner } from '../SubscriptionBanner';
|
|
16
|
-
import { DashboardTitle } from './DashboardTitle';
|
|
17
16
|
import { useInitializeSubsDashboard } from '../../data/hooks';
|
|
18
17
|
import DashboardHeroSlot from '../../slots/DashboardHeroSlot';
|
|
19
18
|
export const Dashboard = () => {
|
|
20
|
-
var _a, _b
|
|
19
|
+
var _a, _b;
|
|
21
20
|
const { data, isPending } = useInitializeSubsCourseDashboard();
|
|
22
21
|
const { data: learnerData } = useInitializeSubsDashboard();
|
|
23
22
|
const { pageTitle } = hooks.useDashboardMessages();
|
|
24
23
|
const { selectSessionModal } = useSelectSessionModal();
|
|
25
24
|
const showSelectSessionModal = selectSessionModal.cardId !== null;
|
|
26
|
-
const
|
|
25
|
+
const learnerSubscriptionData = (learnerData === null || learnerData === void 0 ? void 0 : learnerData.userSubscription) || {};
|
|
26
|
+
const userSubscriptionStartDate = (learnerSubscriptionData === null || learnerSubscriptionData === void 0 ? void 0 : learnerSubscriptionData.subscriptionStartDate) || '';
|
|
27
27
|
const hasCourses = useMemo(() => { var _a; return ((_a = data === null || data === void 0 ? void 0 : data.subscriptionCourses) === null || _a === void 0 ? void 0 : _a.length) > 0; }, [data]);
|
|
28
|
-
const hasCourseHistory = ((
|
|
28
|
+
const hasCourseHistory = ((_b = (_a = data === null || data === void 0 ? void 0 : data.nonUpgradeableCourses) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0;
|
|
29
29
|
return (_jsx("div", { id: "learnerdashboardroot", children: _jsx("main", { children: _jsxs("div", { id: "dashboard-container", className: "d-flex flex-column p-2 pt-0", children: [_jsx("h1", { className: "sr-only", children: pageTitle }), !isPending && (_jsxs(_Fragment, { children: [_jsx(DashboardModalSlot, {}), (hasCourses && showSelectSessionModal) && _jsx(SelectSessionModal, {})] })), _jsx("div", { id: "dashboard-content", "data-testid": "dashboard-content", children: isPending
|
|
30
30
|
? (_jsx(LoadingView, {}))
|
|
31
|
-
: (_jsxs(DashboardLayout, { children: [_jsx(DashboardHeader, { startDate: userSubscriptionStartDate }), _jsx(SubscriptionBanner, {
|
|
31
|
+
: (_jsxs(DashboardLayout, { children: [_jsx(DashboardHeader, { startDate: userSubscriptionStartDate }), _jsx(SubscriptionBanner, { learnerSubscriptionData: learnerSubscriptionData }), _jsx(DashboardHeroSlot, {}), _jsx(DashboardContent, { hasCourseHistory: hasCourseHistory }), _jsx(PopularCoursePanel, {}), _jsx(PopularProgramsPanel, {})] })) })] }) }) }));
|
|
32
32
|
};
|
|
33
33
|
export default Dashboard;
|
|
34
34
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/containers/Dashboard/index.jsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,gCAAgC,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,kBAAkB,MAAM,qCAAqC,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,kBAAkB,MAAM,gCAAgC,CAAC;AAChE,OAAO,kBAAkB,MAAM,uBAAuB,CAAC;AACvD,OAAO,oBAAoB,MAAM,yBAAyB,CAAC;AAE3D,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,eAAe,MAAM,mBAAmB,CAAC;AAEhD,OAAO,KAAK,MAAM,SAAS,CAAC;AAC5B,OAAO,cAAc,CAAC;AACtB,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/containers/Dashboard/index.jsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,gCAAgC,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,kBAAkB,MAAM,qCAAqC,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,kBAAkB,MAAM,gCAAgC,CAAC;AAChE,OAAO,kBAAkB,MAAM,uBAAuB,CAAC;AACvD,OAAO,oBAAoB,MAAM,yBAAyB,CAAC;AAE3D,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,eAAe,MAAM,mBAAmB,CAAC;AAEhD,OAAO,KAAK,MAAM,SAAS,CAAC;AAC5B,OAAO,cAAc,CAAC;AACtB,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,iBAAiB,MAAM,8BAA8B,CAAC;AAG7D,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,EAAE;;IAC5B,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,gCAAgC,EAAE,CAAC;IAC/D,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,0BAA0B,EAAE,CAAC;IAC3D,MAAM,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC,oBAAoB,EAAE,CAAC;IACnD,MAAM,EAAE,kBAAkB,EAAE,GAAG,qBAAqB,EAAE,CAAC;IACvD,MAAM,sBAAsB,GAAG,kBAAkB,CAAC,MAAM,KAAK,IAAI,CAAC;IAClE,MAAM,uBAAuB,GAAG,CAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,gBAAgB,KAAI,EAAE,CAAC;IACpE,MAAM,yBAAyB,GAAG,CAAA,uBAAuB,aAAvB,uBAAuB,uBAAvB,uBAAuB,CAAE,qBAAqB,KAAI,EAAE,CAAC;IAEvF,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE,WAAC,OAAA,CAAA,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,mBAAmB,0CAAE,MAAM,IAAG,CAAC,CAAA,EAAA,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAChF,MAAM,gBAAgB,GAAG,CAAC,MAAA,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,qBAAqB,0CAAE,MAAM,mCAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAExE,OAAO,CACL,cAAK,EAAE,EAAC,sBAAsB,YAC5B,yBACE,eAAK,EAAE,EAAC,qBAAqB,EAAC,SAAS,EAAC,6BAA6B,aACnE,aAAI,SAAS,EAAC,SAAS,YAAE,SAAS,GAAM,EACvC,CAAC,SAAS,IAAI,CACb,8BACE,KAAC,kBAAkB,KAAG,EACrB,CAAC,UAAU,IAAI,sBAAsB,CAAC,IAAI,KAAC,kBAAkB,KAAG,IAChE,CACJ,EACD,cAAK,EAAE,EAAC,mBAAmB,iBAAa,mBAAmB,YACxD,SAAS;4BACR,CAAC,CAAC,CAAC,KAAC,WAAW,KAAG,CAAC;4BACnB,CAAC,CAAC,CACA,MAAC,eAAe,eACd,KAAC,eAAe,IAAC,SAAS,EAAE,yBAAyB,GAAI,EACzD,KAAC,kBAAkB,IAAC,uBAAuB,EAAE,uBAAuB,GAAI,EACxE,KAAC,iBAAiB,KAAG,EACrB,KAAC,gBAAgB,IAAC,gBAAgB,EAAE,gBAAgB,GAAI,EACxD,KAAC,kBAAkB,KAAG,EACtB,KAAC,oBAAoB,KAAG,IACR,CACnB,GACC,IACF,GACD,GACH,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,SAAS,CAAC","sourcesContent":["import { useMemo } from 'react';\nimport { DashboardHeader } from './DashboardHeader';\n\nimport { useSelectSessionModal } from '@src/data/context';\nimport { useInitializeSubsCourseDashboard } from '@src/data/hooks';\nimport SelectSessionModal from '../../containers/SelectSessionModal';\nimport { DashboardContent } from './DashboardContent';\nimport DashboardModalSlot from '../../slots/DashboardModalSlot';\nimport PopularCoursePanel from '../PopularCoursePanel';\nimport PopularProgramsPanel from '../PopularProgramsPanel';\n\nimport LoadingView from './LoadingView';\nimport DashboardLayout from './DashboardLayout';\n\nimport hooks from './hooks';\nimport './index.scss';\nimport { SubscriptionBanner } from '../SubscriptionBanner';\nimport { useInitializeSubsDashboard } from '@src/data/hooks';\nimport DashboardHeroSlot from '@src/slots/DashboardHeroSlot';\n\n\nexport const Dashboard = () => {\n const { data, isPending } = useInitializeSubsCourseDashboard();\n const { data: learnerData } = useInitializeSubsDashboard();\n const { pageTitle } = hooks.useDashboardMessages();\n const { selectSessionModal } = useSelectSessionModal();\n const showSelectSessionModal = selectSessionModal.cardId !== null;\n const learnerSubscriptionData = learnerData?.userSubscription || {};\n const userSubscriptionStartDate = learnerSubscriptionData?.subscriptionStartDate || '';\n\n const hasCourses = useMemo(() => data?.subscriptionCourses?.length > 0, [data]);\n const hasCourseHistory = (data?.nonUpgradeableCourses?.length ?? 0) > 0;\n\n return (\n <div id=\"learnerdashboardroot\">\n <main>\n <div id=\"dashboard-container\" className=\"d-flex flex-column p-2 pt-0\">\n <h1 className=\"sr-only\">{pageTitle}</h1>\n {!isPending && (\n <>\n <DashboardModalSlot />\n {(hasCourses && showSelectSessionModal) && <SelectSessionModal />}\n </>\n )}\n <div id=\"dashboard-content\" data-testid=\"dashboard-content\">\n {isPending\n ? (<LoadingView />)\n : (\n <DashboardLayout>\n <DashboardHeader startDate={userSubscriptionStartDate} />\n <SubscriptionBanner learnerSubscriptionData={learnerSubscriptionData} />\n <DashboardHeroSlot />\n <DashboardContent hasCourseHistory={hasCourseHistory} />\n <PopularCoursePanel />\n <PopularProgramsPanel />\n </DashboardLayout>\n )}\n </div>\n </div>\n </main>\n </div>\n );\n};\n\nexport default Dashboard;\n"]}
|
|
@@ -8,84 +8,82 @@ import { utilHooks } from '../../../hooks';
|
|
|
8
8
|
import messages from '../messages';
|
|
9
9
|
import { subscriptionRenewalURL, checkoutPageURL } from '../../../data/constants/app';
|
|
10
10
|
import { Link } from 'react-router-dom';
|
|
11
|
-
|
|
12
|
-
// For now, we can use this hardcoded data to test the SubscriptionBanner component.
|
|
13
|
-
// Refer to https://2u-internal.atlassian.net/browse/SUBS-442 for more details on the API integration.
|
|
14
|
-
// And https://github.com/edx/frontend-app-subscription-learner-dashboard/pull/2#discussion_r3139442324 for the implementation details of the API integration.
|
|
15
|
-
// Test cases for the trial case are already written in the SubscriptionBanner.test.tsx file. We can update the test cases to use the actual API data once we have the API ready.
|
|
16
|
-
const subscriptionBannerData = {
|
|
17
|
-
isSubscribed: true,
|
|
18
|
-
status: 'trial', // can be 'active', 'cancelled', 'renewalFailed'
|
|
19
|
-
subscriptionStartDate: '2026-05-22',
|
|
20
|
-
subscriptionEndDate: '2026-07-22',
|
|
21
|
-
subscriptionRenewalDate: '2026-07-22',
|
|
22
|
-
subscriptionRenewalPrice: '$36',
|
|
23
|
-
};
|
|
24
|
-
export const SubscriptionBanner = () => {
|
|
25
|
-
var _a;
|
|
11
|
+
export const SubscriptionBanner = ({ learnerSubscriptionData }) => {
|
|
26
12
|
const { formatMessage } = useIntl();
|
|
27
13
|
const [showPageBanner, setShowPageBanner] = useState(true);
|
|
28
14
|
const [bannerBody, setBannerBody] = useState('');
|
|
29
15
|
const [bannerTitle, setBannerTitle] = useState('');
|
|
30
16
|
const [bannerVariant, setBannerVariant] = useState(undefined);
|
|
31
17
|
const formatDate = utilHooks.useFormatDate();
|
|
18
|
+
const { status, subscriptionEndDate, subscriptionRenewalDate, subscriptionStartDate } = learnerSubscriptionData;
|
|
32
19
|
useEffect(() => {
|
|
33
|
-
const trialEndDate = moment(
|
|
20
|
+
const trialEndDate = moment(subscriptionEndDate).startOf('day');
|
|
34
21
|
const today = moment().startOf('day');
|
|
35
22
|
const trialDaysLeft = trialEndDate.isValid()
|
|
36
23
|
? Math.max(0, trialEndDate.diff(today, 'days'))
|
|
37
24
|
: 0;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
25
|
+
if (status !== undefined && status !== null) {
|
|
26
|
+
switch (status) {
|
|
27
|
+
case 'ACTIVE':
|
|
28
|
+
/**
|
|
29
|
+
* TODO : Since we do not have screen for ACTIVE case, we are hiding the banner
|
|
30
|
+
*/
|
|
31
|
+
setShowPageBanner(false);
|
|
32
|
+
break;
|
|
33
|
+
case 'TRIAL_ACTIVE':
|
|
34
|
+
setBannerVariant('success');
|
|
35
|
+
if (trialDaysLeft === 0) {
|
|
36
|
+
setBannerTitle(formatMessage(messages.activeTrialSubscriptionTitleToday));
|
|
37
|
+
}
|
|
38
|
+
else if (trialDaysLeft === 1) {
|
|
39
|
+
setBannerTitle(formatMessage(messages.activeTrialSubscriptionTitleTomorrow));
|
|
40
|
+
}
|
|
41
|
+
else if (moment(subscriptionStartDate).isValid() && moment(subscriptionStartDate).isSame(moment(), 'day')) {
|
|
42
|
+
setBannerTitle(formatMessage(messages.activeSubscriptionTitle));
|
|
43
|
+
setBannerBody(formatMessage(messages.activeSubscriptionBody, {
|
|
44
|
+
subscriptionRenewalDate: formatDate(subscriptionRenewalDate),
|
|
45
|
+
}));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
setBannerTitle(formatMessage(messages.activeTrialSubscriptionTitle, {
|
|
50
|
+
daysLeft: trialDaysLeft,
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
setBannerBody(formatMessage(messages.activeTrialSubscriptionBody, {
|
|
54
|
+
subscriptionEndDate: formatDate(subscriptionEndDate),
|
|
55
|
+
}));
|
|
56
|
+
break;
|
|
57
|
+
case 'CANCELLED':
|
|
58
|
+
setBannerVariant('light');
|
|
59
|
+
setBannerTitle(formatMessage(messages.cancelledSubscriptionTitle));
|
|
60
|
+
setBannerBody(formatMessage(messages.cancelledSubscriptionBody, {
|
|
61
|
+
subscriptionEndDate: formatDate(subscriptionEndDate),
|
|
62
|
+
}));
|
|
63
|
+
break;
|
|
64
|
+
case 'RENEWAL_FAILED': // also known as 'Payment Error' in figma designs
|
|
65
|
+
setBannerVariant('light');
|
|
66
|
+
setBannerTitle(formatMessage(messages.renewalFailedTitle));
|
|
67
|
+
setBannerBody(formatMessage(messages.renewalFailedBody, {
|
|
68
|
+
subscriptionRenewalDate: formatDate(subscriptionRenewalDate),
|
|
57
69
|
}));
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
setBannerBody(formatMessage(messages.cancelledSubscriptionBody, {
|
|
67
|
-
subscriptionEndDate: formatDate(subscriptionBannerData.subscriptionEndDate),
|
|
68
|
-
}));
|
|
69
|
-
break;
|
|
70
|
-
case 'renewalFailed': // also known as 'Payment Error' in figma designs
|
|
71
|
-
setBannerVariant('light');
|
|
72
|
-
setBannerTitle(formatMessage(messages.renewalFailedTitle));
|
|
73
|
-
setBannerBody(formatMessage(messages.renewalFailedBody, {
|
|
74
|
-
subscriptionRenewalDate: formatDate(subscriptionBannerData.subscriptionRenewalDate),
|
|
75
|
-
}));
|
|
76
|
-
break;
|
|
77
|
-
default:
|
|
78
|
-
setShowPageBanner(false);
|
|
79
|
-
break;
|
|
70
|
+
break;
|
|
71
|
+
default:
|
|
72
|
+
setShowPageBanner(false);
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
setShowPageBanner(false);
|
|
80
78
|
}
|
|
81
|
-
}, [formatDate, formatMessage]);
|
|
79
|
+
}, [formatDate, formatMessage, status, subscriptionEndDate, subscriptionRenewalDate, subscriptionStartDate]);
|
|
82
80
|
const getSubscriptionAction = useMemo(() => {
|
|
83
|
-
if (
|
|
81
|
+
if (status === 'CANCELLED') {
|
|
84
82
|
return ([
|
|
85
83
|
_jsx(Button, { "data-testid": "renew-button", className: "renew-button", variant: "primary", href: subscriptionRenewalURL, target: "_blank", rel: "noopener noreferrer", role: "link", children: formatMessage(messages.renewSubscriptionButton) }, "renew-subscription"),
|
|
86
84
|
]);
|
|
87
85
|
}
|
|
88
|
-
else if (
|
|
86
|
+
else if (status === 'RENEWAL_FAILED') {
|
|
89
87
|
return ([
|
|
90
88
|
_jsx(Button, { "data-testid": "renew-failed-button", className: "renew-failed-button", variant: "primary", to: checkoutPageURL, target: "_blank", rel: "noopener noreferrer", role: "link", as: Link, children: formatMessage(messages.renewalFailedButton) }, "renew-failed-subscription"),
|
|
91
89
|
]);
|
|
@@ -93,11 +91,15 @@ export const SubscriptionBanner = () => {
|
|
|
93
91
|
else {
|
|
94
92
|
return [];
|
|
95
93
|
}
|
|
96
|
-
}, [formatMessage]);
|
|
94
|
+
}, [formatMessage, status]);
|
|
97
95
|
const subscriptionStatusIcons = {
|
|
98
|
-
|
|
96
|
+
TRIAL_ACTIVE: CheckCircle,
|
|
99
97
|
};
|
|
100
|
-
const bannerIcon = (
|
|
98
|
+
const bannerIcon = (subscriptionStatusIcons[status]
|
|
99
|
+
&& moment(subscriptionStartDate).isValid()
|
|
100
|
+
&& moment(subscriptionStartDate).isSame(moment(), 'day'))
|
|
101
|
+
? subscriptionStatusIcons[status]
|
|
102
|
+
: undefined;
|
|
101
103
|
return (_jsx("div", { className: "mt-4.5 mb-4.5", children: _jsxs(Alert, { variant: bannerVariant, icon: bannerIcon, dismissible: true, closeLabel: "Dismiss", show: showPageBanner, onClose: () => setShowPageBanner(false), actions: getSubscriptionAction, children: [_jsx(Alert.Heading, { children: bannerTitle }), _jsx("p", { children: bannerBody })] }) }));
|
|
102
104
|
};
|
|
103
105
|
//# sourceMappingURL=SubscriptionBanner.js.map
|
|
@@ -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 { subscriptionRenewalURL, checkoutPageURL } from '@src/data/constants/app';\nimport { Link } from 'react-router-dom';\n\n// TODO: We can replace the below hardcoded subscriptionBannerData with the actual data from the API once we have the API ready.\n// For now, we can use this hardcoded data to test the SubscriptionBanner component.\n// Refer to https://2u-internal.atlassian.net/browse/SUBS-442 for more details on the API integration.\n// And https://github.com/edx/frontend-app-subscription-learner-dashboard/pull/2#discussion_r3139442324 for the implementation details of the API integration.\n// Test cases for the trial case are already written in the SubscriptionBanner.test.tsx file. We can update the test cases to use the actual API data once we have the API ready.\nconst subscriptionBannerData = {\n isSubscribed: true,\n status: 'trial', // can be 'active', 'cancelled', 'renewalFailed'\n subscriptionStartDate: '2026-05-22',\n subscriptionEndDate: '2026-07-22',\n subscriptionRenewalDate: '2026-07-22',\n subscriptionRenewalPrice: '$36',\n};\n\nexport const SubscriptionBanner: FC = () => {\n const { formatMessage } = useIntl();\n const [showPageBanner, setShowPageBanner] = useState<boolean>(true);\n const [bannerBody, setBannerBody] = useState('');\n const [bannerTitle, setBannerTitle] = useState('');\n const [bannerVariant, setBannerVariant] = useState<Variant | undefined>(undefined);\n const formatDate = utilHooks.useFormatDate();\n\n useEffect(() => {\n const trialEndDate = moment(subscriptionBannerData.subscriptionEndDate).startOf('day');\n const today = moment().startOf('day');\n const trialDaysLeft = trialEndDate.isValid()\n ? Math.max(0, trialEndDate.diff(today, 'days'))\n : 0;\n\n switch (subscriptionBannerData.status) {\n case 'active':\n setBannerVariant('success');\n setBannerTitle(formatMessage(messages.activeSubscriptionTitle));\n setBannerBody(formatMessage(messages.activeSubscriptionBody, {\n subscriptionRenewalDate: formatDate(subscriptionBannerData.subscriptionRenewalDate),\n }));\n break;\n case 'trial':\n setBannerVariant('success');\n if (trialDaysLeft === 0) {\n setBannerTitle(formatMessage(messages.activeTrialSubscriptionTitleToday));\n } else if (trialDaysLeft === 1) {\n setBannerTitle(formatMessage(messages.activeTrialSubscriptionTitleTomorrow));\n } else {\n setBannerTitle(formatMessage(messages.activeTrialSubscriptionTitle, {\n daysLeft: trialDaysLeft,\n }));\n }\n setBannerBody(formatMessage(messages.activeTrialSubscriptionBody, {\n subscriptionEndDate: formatDate(subscriptionBannerData.subscriptionEndDate),\n }));\n break;\n case 'cancelled':\n setBannerVariant('light');\n setBannerTitle(formatMessage(messages.cancelledSubscriptionTitle));\n setBannerBody(formatMessage(messages.cancelledSubscriptionBody, {\n subscriptionEndDate: formatDate(subscriptionBannerData.subscriptionEndDate),\n }));\n break;\n case 'renewalFailed': // also known as 'Payment Error' in figma designs\n setBannerVariant('light');\n setBannerTitle(formatMessage(messages.renewalFailedTitle));\n setBannerBody(formatMessage(messages.renewalFailedBody, {\n subscriptionRenewalDate: formatDate(subscriptionBannerData.subscriptionRenewalDate),\n }));\n break;\n default:\n setShowPageBanner(false);\n break;\n }\n }, [formatDate, formatMessage]);\n\n const getSubscriptionAction = useMemo(() => {\n if (subscriptionBannerData.status === 'cancelled') {\n return (\n [\n <Button\n key=\"renew-subscription\"\n data-testid=\"renew-button\"\n className=\"renew-button\"\n variant=\"primary\"\n href={subscriptionRenewalURL}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n role=\"link\"\n >\n {formatMessage(messages.renewSubscriptionButton)}\n </Button>,\n ]\n );\n } else if (subscriptionBannerData.status === 'renewalFailed') {\n return (\n [\n <Button\n key=\"renew-failed-subscription\"\n data-testid=\"renew-failed-button\"\n className=\"renew-failed-button\"\n variant=\"primary\"\n to={checkoutPageURL}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n role=\"link\"\n as={Link}\n >\n {formatMessage(messages.renewalFailedButton)}\n </Button>,\n ]\n );\n } else {\n return [];\n }\n }, [formatMessage]);\n\n const subscriptionStatusIcons: Record<string, typeof Info | undefined> = {\n active: CheckCircle,\n };\n\n const bannerIcon = subscriptionStatusIcons[subscriptionBannerData.status] ?? undefined;\n\n return (\n <div className=\"mt-4.5 mb-4.5\">\n <Alert\n variant={bannerVariant}\n icon={bannerIcon}\n dismissible\n closeLabel=\"Dismiss\"\n show={showPageBanner}\n onClose={() => setShowPageBanner(false)}\n actions={getSubscriptionAction}\n >\n <Alert.Heading>{bannerTitle}</Alert.Heading>\n <p>\n {bannerBody}\n </p>\n </Alert>\n </div>\n );\n};\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 { subscriptionRenewalURL, checkoutPageURL } from '@src/data/constants/app';\nimport { Link } from 'react-router-dom';\nimport { BannerItem } from '../types';\n\nexport const SubscriptionBanner: FC<BannerItem> = ({ learnerSubscriptionData }) => {\n const { formatMessage } = useIntl();\n const [showPageBanner, setShowPageBanner] = useState<boolean>(true);\n const [bannerBody, setBannerBody] = useState('');\n const [bannerTitle, setBannerTitle] = useState('');\n const [bannerVariant, setBannerVariant] = useState<Variant | undefined>(undefined);\n const formatDate = utilHooks.useFormatDate();\n const { status, subscriptionEndDate, subscriptionRenewalDate, subscriptionStartDate } = learnerSubscriptionData;\n\n useEffect(() => {\n const trialEndDate = moment(subscriptionEndDate).startOf('day');\n const today = moment().startOf('day');\n const trialDaysLeft = trialEndDate.isValid()\n ? Math.max(0, trialEndDate.diff(today, 'days'))\n : 0;\n\n if (status !== undefined && status !== null) {\n switch (status) {\n case 'ACTIVE':\n /**\n * TODO : Since we do not have screen for ACTIVE case, we are hiding the banner\n */\n setShowPageBanner(false);\n break;\n case 'TRIAL_ACTIVE':\n setBannerVariant('success');\n if (trialDaysLeft === 0) {\n setBannerTitle(formatMessage(messages.activeTrialSubscriptionTitleToday));\n } else if (trialDaysLeft === 1) {\n setBannerTitle(formatMessage(messages.activeTrialSubscriptionTitleTomorrow));\n } else if (moment(subscriptionStartDate).isValid() && moment(subscriptionStartDate).isSame(moment(), 'day')) {\n setBannerTitle(formatMessage(messages.activeSubscriptionTitle));\n setBannerBody(formatMessage(messages.activeSubscriptionBody, {\n subscriptionRenewalDate: formatDate(subscriptionRenewalDate),\n }));\n return;\n } else {\n setBannerTitle(formatMessage(messages.activeTrialSubscriptionTitle, {\n daysLeft: trialDaysLeft,\n }));\n }\n setBannerBody(formatMessage(messages.activeTrialSubscriptionBody, {\n subscriptionEndDate: formatDate(subscriptionEndDate),\n }));\n break;\n case 'CANCELLED':\n setBannerVariant('light');\n setBannerTitle(formatMessage(messages.cancelledSubscriptionTitle));\n setBannerBody(formatMessage(messages.cancelledSubscriptionBody, {\n subscriptionEndDate: formatDate(subscriptionEndDate),\n }));\n break;\n case 'RENEWAL_FAILED': // also known as 'Payment Error' in figma designs\n setBannerVariant('light');\n setBannerTitle(formatMessage(messages.renewalFailedTitle));\n setBannerBody(formatMessage(messages.renewalFailedBody, {\n subscriptionRenewalDate: formatDate(subscriptionRenewalDate),\n }));\n break;\n default:\n setShowPageBanner(false);\n break;\n }\n } else {\n setShowPageBanner(false);\n }\n }, [formatDate, formatMessage, status, subscriptionEndDate, subscriptionRenewalDate, subscriptionStartDate]);\n\n const getSubscriptionAction = useMemo(() => {\n if (status === 'CANCELLED') {\n return (\n [\n <Button\n key=\"renew-subscription\"\n data-testid=\"renew-button\"\n className=\"renew-button\"\n variant=\"primary\"\n href={subscriptionRenewalURL}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n role=\"link\"\n >\n {formatMessage(messages.renewSubscriptionButton)}\n </Button>,\n ]\n );\n } else if (status === 'RENEWAL_FAILED') {\n return (\n [\n <Button\n key=\"renew-failed-subscription\"\n data-testid=\"renew-failed-button\"\n className=\"renew-failed-button\"\n variant=\"primary\"\n to={checkoutPageURL}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n role=\"link\"\n as={Link}\n >\n {formatMessage(messages.renewalFailedButton)}\n </Button>,\n ]\n );\n } else {\n return [];\n }\n }, [formatMessage, status]);\n\n const subscriptionStatusIcons: Record<string, typeof Info | undefined> = {\n TRIAL_ACTIVE: 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 return (\n <div className=\"mt-4.5 mb-4.5\">\n <Alert\n variant={bannerVariant}\n icon={bannerIcon}\n dismissible\n closeLabel=\"Dismiss\"\n show={showPageBanner}\n onClose={() => setShowPageBanner(false)}\n actions={getSubscriptionAction}\n >\n <Alert.Heading>{bannerTitle}</Alert.Heading>\n <p>\n {bannerBody}\n </p>\n </Alert>\n </div>\n );\n};\n"]}
|
|
@@ -4,7 +4,7 @@ const messages = defineMessages({
|
|
|
4
4
|
activeSubscriptionTitle: {
|
|
5
5
|
id: 'learner-dash.subscriptionBanner.banners.activeSubscriptionTitle',
|
|
6
6
|
description: 'Message to learners with an active subscription',
|
|
7
|
-
defaultMessage: 'Congrats! Your edX
|
|
7
|
+
defaultMessage: 'Congrats! Your edX Plus trial is active.',
|
|
8
8
|
},
|
|
9
9
|
activeSubscriptionBody: {
|
|
10
10
|
id: 'learner-dash.subscriptionBanner.banners.activeSubscriptionBody',
|
|
@@ -14,17 +14,17 @@ const messages = defineMessages({
|
|
|
14
14
|
activeTrialSubscriptionTitle: {
|
|
15
15
|
id: 'learner-dash.subscriptionBanner.banners.activeTrialSubscriptionTitle',
|
|
16
16
|
description: 'Message to learners with an active trial subscription',
|
|
17
|
-
defaultMessage: 'Your edX
|
|
17
|
+
defaultMessage: 'Your edX Plus trial expires in {daysLeft} days.',
|
|
18
18
|
},
|
|
19
19
|
activeTrialSubscriptionTitleToday: {
|
|
20
20
|
id: 'learner-dash.subscriptionBanner.banners.activeTrialSubscriptionTitleToday',
|
|
21
21
|
description: 'Message to learners with a trial subscription expiring today',
|
|
22
|
-
defaultMessage: 'Your edX
|
|
22
|
+
defaultMessage: 'Your edX Plus trial expires today.',
|
|
23
23
|
},
|
|
24
24
|
activeTrialSubscriptionTitleTomorrow: {
|
|
25
25
|
id: 'learner-dash.subscriptionBanner.banners.activeTrialSubscriptionTitleTomorrow',
|
|
26
26
|
description: 'Message to learners with a trial subscription expiring tomorrow',
|
|
27
|
-
defaultMessage: 'Your edX
|
|
27
|
+
defaultMessage: 'Your edX Plus trial expires tomorrow.',
|
|
28
28
|
},
|
|
29
29
|
activeTrialSubscriptionBody: {
|
|
30
30
|
id: 'learner-dash.subscriptionBanner.banners.activeTrialSubscriptionBody',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../../src/containers/SubscriptionBanner/messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,yHAAyH;AACzH,MAAM,QAAQ,GAAG,cAAc,CAAC;IAC9B,uBAAuB,EAAE;QACvB,EAAE,EAAE,iEAAiE;QACrE,WAAW,EAAE,iDAAiD;QAC9D,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../../src/containers/SubscriptionBanner/messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,yHAAyH;AACzH,MAAM,QAAQ,GAAG,cAAc,CAAC;IAC9B,uBAAuB,EAAE;QACvB,EAAE,EAAE,iEAAiE;QACrE,WAAW,EAAE,iDAAiD;QAC9D,cAAc,EAAE,0CAA0C;KAC3D;IACD,sBAAsB,EAAE;QACtB,EAAE,EAAE,gEAAgE;QACpE,WAAW,EAAE,iDAAiD;QAC9D,cAAc,EAAE,4DAA4D;KAC7E;IACD,4BAA4B,EAAE;QAC5B,EAAE,EAAE,sEAAsE;QAC1E,WAAW,EAAE,uDAAuD;QACpE,cAAc,EAAE,iDAAiD;KAClE;IACD,iCAAiC,EAAE;QACjC,EAAE,EAAE,2EAA2E;QAC/E,WAAW,EAAE,8DAA8D;QAC3E,cAAc,EAAE,oCAAoC;KACrD;IACD,oCAAoC,EAAE;QACpC,EAAE,EAAE,8EAA8E;QAClF,WAAW,EAAE,iEAAiE;QAC9E,cAAc,EAAE,uCAAuC;KACxD;IACD,2BAA2B,EAAE;QAC3B,EAAE,EAAE,qEAAqE;QACzE,WAAW,EAAE,uDAAuD;QACpE,cAAc,EAAE,wDAAwD;KACzE;IACD,0BAA0B,EAAE;QAC1B,EAAE,EAAE,oEAAoE;QACxE,WAAW,EAAE,mDAAmD;QAChE,cAAc,EAAE,sCAAsC;KACvD;IACD,yBAAyB,EAAE;QACzB,EAAE,EAAE,mEAAmE;QACvE,WAAW,EAAE,mDAAmD;QAChE,cAAc,EAAE,6GAA6G;KAC9H;IACD,uBAAuB,EAAE;QACvB,EAAE,EAAE,iEAAiE;QACrE,WAAW,EAAE,oBAAoB;QACjC,cAAc,EAAE,oBAAoB;KACrC;IACD,kBAAkB,EAAE;QAClB,EAAE,EAAE,4DAA4D;QAChE,WAAW,EAAE,wDAAwD;QACrE,cAAc,EAAE,4DAA4D;KAC7E;IACD,iBAAiB,EAAE;QACjB,EAAE,EAAE,2DAA2D;QAC/D,WAAW,EAAE,wDAAwD;QACrE,cAAc,EAAE,qJAAqJ;KACtK;IACD,mBAAmB,EAAE;QACnB,EAAE,EAAE,6DAA6D;QACjE,WAAW,EAAE,uBAAuB;QACpC,cAAc,EAAE,uBAAuB;KACxC;CACF,CAAC,CAAC;AAEH,eAAe,QAAQ,CAAC","sourcesContent":["import { defineMessages } from '@openedx/frontend-base';\n\n// TODO: Update the messages as per new designs once we have the designs ready for subscription types other than 'trial'.\nconst messages = defineMessages({\n activeSubscriptionTitle: {\n id: 'learner-dash.subscriptionBanner.banners.activeSubscriptionTitle',\n description: 'Message to learners with an active subscription',\n defaultMessage: 'Congrats! Your edX Plus trial is active.',\n },\n activeSubscriptionBody: {\n id: 'learner-dash.subscriptionBanner.banners.activeSubscriptionBody',\n description: 'Message to learners with an active subscription',\n defaultMessage: 'Your subscription will renew on {subscriptionRenewalDate}.',\n },\n activeTrialSubscriptionTitle: {\n id: 'learner-dash.subscriptionBanner.banners.activeTrialSubscriptionTitle',\n description: 'Message to learners with an active trial subscription',\n defaultMessage: 'Your edX Plus trial expires in {daysLeft} days.',\n },\n activeTrialSubscriptionTitleToday: {\n id: 'learner-dash.subscriptionBanner.banners.activeTrialSubscriptionTitleToday',\n description: 'Message to learners with a trial subscription expiring today',\n defaultMessage: 'Your edX Plus trial expires today.',\n },\n activeTrialSubscriptionTitleTomorrow: {\n id: 'learner-dash.subscriptionBanner.banners.activeTrialSubscriptionTitleTomorrow',\n description: 'Message to learners with a trial subscription expiring tomorrow',\n defaultMessage: 'Your edX Plus trial expires tomorrow.',\n },\n activeTrialSubscriptionBody: {\n id: 'learner-dash.subscriptionBanner.banners.activeTrialSubscriptionBody',\n description: 'Message to learners with an active trial subscription',\n defaultMessage: 'Your subscription will renew on {subscriptionEndDate}.',\n },\n cancelledSubscriptionTitle: {\n id: 'learner-dash.subscriptionBanner.banners.cancelledSubscriptionTitle',\n description: 'Message to learners with a cancelled subscription',\n defaultMessage: 'Your subscription expires in # days.',\n },\n cancelledSubscriptionBody: {\n id: 'learner-dash.subscriptionBanner.banners.cancelledSubscriptionBody',\n description: 'Message to learners with a cancelled subscription',\n defaultMessage: 'You canceled your subscription on {subscriptionEndDate}. Renew your subscription to maintain course access.',\n },\n renewSubscriptionButton: {\n id: 'learner-dash.subscriptionBanner.banners.renewSubscriptionButton',\n description: 'Renew Subscription',\n defaultMessage: 'Renew Subscription',\n },\n renewalFailedTitle: {\n id: 'learner-dash.subscriptionBanner.banners.renewalFailedTitle',\n description: 'Message to learners with a failed renewal subscription',\n defaultMessage: 'Update your payment card to keep your subscription active.',\n },\n renewalFailedBody: {\n id: 'learner-dash.subscriptionBanner.banners.renewalFailedBody',\n description: 'Message to learners with a failed renewal subscription',\n defaultMessage: 'We were unable to process your subscription payment. Update your card on file by {subscriptionRenewalDate} or your subscription access will expire.',\n },\n renewalFailedButton: {\n id: 'learner-dash.subscriptionBanner.banners.renewalFailedButton',\n description: 'Update payment method',\n defaultMessage: 'Update payment method',\n },\n});\n\nexport default messages;\n"]}
|