import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import {
useIntl, FormattedDate, FormattedMessage, injectIntl,
} from '@edx/frontend-platform/i18n';
import { sendTrackEvent, sendTrackingLogEvent } from '@edx/frontend-platform/analytics';
import { Button, Icon, IconButton } from '@openedx/paragon';
import { Close } from '@openedx/paragon/icons';
import { setLocalStorage } from '../../data/localStorage';
import { UpgradeButton } from '../upgrade-button';
import {
VerifiedCertBullet,
UnlockGradedBullet,
FullAccessBullet,
SupportMissionBullet,
} from '../upsell-bullets/UpsellBullets';
import messages from '../messages';
const UpsellNoFBECardContent = () => (
);
const UpsellFBEFarAwayCardContent = () => (
);
const UpsellFBESoonCardContent = ({ accessExpirationDate, timezoneFormatArgs }) => {
const includingAnyProgress = (
);
const date = (
);
const benefitsOfUpgrading = (
);
return (
);
};
UpsellFBESoonCardContent.propTypes = {
accessExpirationDate: PropTypes.PropTypes.instanceOf(Date).isRequired,
timezoneFormatArgs: PropTypes.shape({
timeZone: PropTypes.string,
}),
};
UpsellFBESoonCardContent.defaultProps = {
timezoneFormatArgs: {},
};
const PastExpirationCardContent = () => (
);
const ExpirationCountdown = ({
courseId, hoursToExpiration, setupgradeNotificationCurrentState, type,
}) => {
let expirationText;
if (hoursToExpiration >= 24) { // More than 1 day left
// setupgradeNotificationCurrentState is available in NotificationTray (not course home)
if (setupgradeNotificationCurrentState) {
if (type === 'access') {
setupgradeNotificationCurrentState('accessDaysLeft');
setLocalStorage(`upgradeNotificationCurrentState.${courseId}`, 'accessDaysLeft');
}
if (type === 'offer') {
setupgradeNotificationCurrentState('FPDdaysLeft');
setLocalStorage(`upgradeNotificationCurrentState.${courseId}`, 'FPDdaysLeft');
}
}
expirationText = (
);
} else if (hoursToExpiration >= 1) { // More than 1 hour left
// setupgradeNotificationCurrentState is available in NotificationTray (not course home)
if (setupgradeNotificationCurrentState) {
if (type === 'access') {
setupgradeNotificationCurrentState('accessHoursLeft');
setLocalStorage(`upgradeNotificationCurrentState.${courseId}`, 'accessHoursLeft');
}
if (type === 'offer') {
setupgradeNotificationCurrentState('FPDHoursLeft');
setLocalStorage(`upgradeNotificationCurrentState.${courseId}`, 'FPDHoursLeft');
}
}
expirationText = (
);
} else { // Less than 1 hour
// setupgradeNotificationCurrentState is available in NotificationTray (not course home)
if (setupgradeNotificationCurrentState) {
if (type === 'access') {
setupgradeNotificationCurrentState('accessLastHour');
setLocalStorage(`upgradeNotificationCurrentState.${courseId}`, 'accessLastHour');
}
if (type === 'offer') {
setupgradeNotificationCurrentState('FPDLastHour');
setLocalStorage(`upgradeNotificationCurrentState.${courseId}`, 'FPDLastHour');
}
}
expirationText = (
);
}
return ({expirationText}
);
};
ExpirationCountdown.propTypes = {
courseId: PropTypes.string.isRequired,
hoursToExpiration: PropTypes.number.isRequired,
setupgradeNotificationCurrentState: PropTypes.func,
type: PropTypes.string,
};
ExpirationCountdown.defaultProps = {
setupgradeNotificationCurrentState: null,
type: null,
};
const AccessExpirationDateBanner = ({
courseId, accessExpirationDate, timezoneFormatArgs, setupgradeNotificationCurrentState,
}) => {
if (setupgradeNotificationCurrentState) {
setupgradeNotificationCurrentState('accessDateView');
setLocalStorage(`upgradeNotificationCurrentState.${courseId}`, 'accessDateView');
}
return (
),
}}
/>
);
};
AccessExpirationDateBanner.propTypes = {
courseId: PropTypes.string.isRequired,
accessExpirationDate: PropTypes.PropTypes.instanceOf(Date).isRequired,
timezoneFormatArgs: PropTypes.shape({
timeZone: PropTypes.string,
}),
setupgradeNotificationCurrentState: PropTypes.func,
};
AccessExpirationDateBanner.defaultProps = {
timezoneFormatArgs: {},
setupgradeNotificationCurrentState: null,
};
const PastExpirationDateBanner = ({
courseId, accessExpirationDate, timezoneFormatArgs, setupgradeNotificationCurrentState,
}) => {
if (setupgradeNotificationCurrentState) {
setupgradeNotificationCurrentState('PastExpirationDate');
setLocalStorage(`upgradeNotificationCurrentState.${courseId}`, 'PastExpirationDate');
}
return (
),
}}
/>
);
};
PastExpirationDateBanner.propTypes = {
courseId: PropTypes.string.isRequired,
accessExpirationDate: PropTypes.PropTypes.instanceOf(Date).isRequired,
timezoneFormatArgs: PropTypes.shape({
timeZone: PropTypes.string,
}),
setupgradeNotificationCurrentState: PropTypes.func,
};
PastExpirationDateBanner.defaultProps = {
timezoneFormatArgs: {},
setupgradeNotificationCurrentState: null,
};
const UpgradeNotification = ({
accessExpiration,
contentTypeGatingEnabled,
marketingUrl,
courseId,
offer,
org,
setupgradeNotificationCurrentState,
shouldDisplayBorder,
timeOffsetMillis,
upsellPageName,
userTimezone,
verifiedMode,
toggleSidebar,
}) => {
const intl = useIntl();
const dateNow = Date.now();
const timezoneFormatArgs = userTimezone ? { timeZone: userTimezone } : {};
const correctedTime = new Date(dateNow + timeOffsetMillis);
const accessExpirationDate = accessExpiration ? new Date(accessExpiration.expirationDate) : null;
const pastExpirationDeadline = accessExpiration ? new Date(dateNow) > accessExpirationDate : false;
const eventProperties = {
org_key: org,
courserun_key: courseId,
};
const promotionEventProperties = {
creative: 'sidebarupsell',
name: 'In-Course Verification Prompt',
position: 'sidebar-message',
promotion_id: 'courseware_verified_certificate_upsell',
...eventProperties,
};
useEffect(() => {
sendTrackingLogEvent('edx.bi.course.upgrade.sidebarupsell.displayed', eventProperties);
sendTrackEvent('Promotion Viewed', promotionEventProperties);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
if (!verifiedMode) {
return null;
}
const logClick = () => {
sendTrackingLogEvent('edx.bi.course.upgrade.sidebarupsell.clicked', eventProperties);
sendTrackingLogEvent('edx.course.enrollment.upgrade.clicked', {
...eventProperties,
location: 'sidebar-message',
});
sendTrackEvent('Promotion Clicked', promotionEventProperties);
sendTrackEvent('edx.bi.ecommerce.upsell_links_clicked', {
...eventProperties,
linkCategory: 'green_upgrade',
linkName: `${upsellPageName}_green`,
linkType: 'button',
pageName: upsellPageName,
});
};
const logClickPastExpiration = () => {
sendTrackEvent('edx.bi.ecommerce.upgrade_notification.past_expiration.button_clicked', {
...eventProperties,
linkCategory: 'upgrade_notification',
linkName: `${upsellPageName}_course_details`,
linkType: 'button',
pageName: upsellPageName,
});
};
/*
There are 5 parts that change in the upgrade card:
upgradeNotificationHeaderText
expirationBanner
upsellMessage
callToActionButton
offerCode
*/
let upgradeNotificationHeaderText;
let expirationBanner;
let upsellMessage;
let callToActionButton;
let offerCode;
if (!!accessExpiration && !!contentTypeGatingEnabled) {
const hoursToAccessExpiration = Math.floor((accessExpirationDate - correctedTime) / 1000 / 60 / 60);
if (hoursToAccessExpiration >= (7 * 24)) {
if (offer) { // countdown to the first purchase discount if there is one
const hoursToDiscountExpiration = Math.floor((new Date(offer.expirationDate) - correctedTime) / 1000 / 60 / 60);
upgradeNotificationHeaderText = (
);
expirationBanner = (
);
} else {
upgradeNotificationHeaderText = (
);
expirationBanner = (
);
}
upsellMessage = ;
} else if (hoursToAccessExpiration < (7 * 24) && hoursToAccessExpiration >= 0) {
// more urgent messaging if there's less than 7 days left to access expiration
upgradeNotificationHeaderText = (
);
expirationBanner = (
);
upsellMessage = (
);
} else { // access expiration deadline has passed
upgradeNotificationHeaderText = (
);
expirationBanner = (
);
upsellMessage = (
);
}
} else { // FBE is turned off
upgradeNotificationHeaderText = (
);
upsellMessage = ();
}
if (pastExpirationDeadline) {
callToActionButton = (
);
} else {
callToActionButton = (
);
}
if (offer) { // if there's a first purchase discount, message the code at the bottom
offerCode = (
{offer.code}),
}}
/>
);
}
return (
{expirationBanner}
{upsellMessage}
{callToActionButton}
{offerCode}
);
};
UpgradeNotification.propTypes = {
courseId: PropTypes.string.isRequired,
org: PropTypes.string.isRequired,
accessExpiration: PropTypes.shape({
expirationDate: PropTypes.string,
}),
contentTypeGatingEnabled: PropTypes.bool,
marketingUrl: PropTypes.string,
offer: PropTypes.shape({
expirationDate: PropTypes.string,
percentage: PropTypes.number,
code: PropTypes.string,
}),
toggleSidebar: PropTypes.func,
shouldDisplayBorder: PropTypes.bool,
setupgradeNotificationCurrentState: PropTypes.func,
timeOffsetMillis: PropTypes.number,
upsellPageName: PropTypes.string.isRequired,
userTimezone: PropTypes.string,
verifiedMode: PropTypes.shape({
currencySymbol: PropTypes.string.isRequired,
price: PropTypes.number.isRequired,
upgradeUrl: PropTypes.string.isRequired,
}),
};
UpgradeNotification.defaultProps = {
accessExpiration: null,
contentTypeGatingEnabled: false,
marketingUrl: null,
offer: null,
setupgradeNotificationCurrentState: null,
shouldDisplayBorder: null,
timeOffsetMillis: 0,
userTimezone: null,
verifiedMode: null,
toggleSidebar: null,
};
export default injectIntl(UpgradeNotification);