import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { sendTrackEvent, sendTrackingLogEvent } from '@edx/frontend-platform/analytics';
import { FormattedDate, FormattedMessage, injectIntl } from '@edx/frontend-platform/i18n';
import { setLocalStorage } from '../../data/localStorage';
import { UpgradeButton } from '../upgrade-button';
import {
VerifiedCertBullet,
UnlockGradedBullet,
FullAccessBullet,
SupportMissionBullet,
} from '../upsell-bullets/UpsellBullets';
function UpsellNoFBECardContent() {
return (
);
}
function UpsellFBEFarAwayCardContent() {
return (
);
}
function 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: {},
};
function ExpirationCountdown({ hoursToExpiration, setupgradeNotificationCurrentState, type }) {
let expirationText;
if (hoursToExpiration >= 24) {
// setupgradeNotificationCurrentState is available in NotificationTray (not course home)
if (setupgradeNotificationCurrentState) {
if (type === 'access') {
setupgradeNotificationCurrentState('accessDaysLeft');
setLocalStorage('upgradeNotificationCurrentState', 'accessDaysLeft');
}
if (type === 'offer') {
setupgradeNotificationCurrentState('FPDdaysLeft');
setLocalStorage('upgradeNotificationCurrentState', 'FPDdaysLeft');
}
}
expirationText = (
);
} else if (hoursToExpiration >= 1) {
// setupgradeNotificationCurrentState is available in NotificationTray (not course home)
if (setupgradeNotificationCurrentState) {
if (type === 'access') {
setupgradeNotificationCurrentState('accessHoursLeft');
setLocalStorage('upgradeNotificationCurrentState', 'accessHoursLeft');
}
if (type === 'offer') {
setupgradeNotificationCurrentState('FPDHoursLeft');
setLocalStorage('upgradeNotificationCurrentState', 'FPDHoursLeft');
}
}
expirationText = (
);
} else {
// setupgradeNotificationCurrentState is available in NotificationTray (not course home)
if (setupgradeNotificationCurrentState) {
if (type === 'access') {
setupgradeNotificationCurrentState('accessLastHour');
setLocalStorage('upgradeNotificationCurrentState', 'accessLastHour');
}
if (type === 'offer') {
setupgradeNotificationCurrentState('FPDLastHour');
setLocalStorage('upgradeNotificationCurrentState', 'FPDLastHour');
}
}
expirationText = (
);
}
return ({expirationText}
);
}
ExpirationCountdown.propTypes = {
hoursToExpiration: PropTypes.number.isRequired,
setupgradeNotificationCurrentState: PropTypes.func,
type: PropTypes.string,
};
ExpirationCountdown.defaultProps = {
setupgradeNotificationCurrentState: null,
type: null,
};
function AccessExpirationDateBanner({ accessExpirationDate, timezoneFormatArgs, setupgradeNotificationCurrentState }) {
if (setupgradeNotificationCurrentState) {
setupgradeNotificationCurrentState('accessDateView');
setLocalStorage('upgradeNotificationCurrentState', 'accessDateView');
}
return (
),
}}
/>
);
}
AccessExpirationDateBanner.propTypes = {
accessExpirationDate: PropTypes.PropTypes.instanceOf(Date).isRequired,
timezoneFormatArgs: PropTypes.shape({
timeZone: PropTypes.string,
}),
setupgradeNotificationCurrentState: PropTypes.func,
};
AccessExpirationDateBanner.defaultProps = {
timezoneFormatArgs: {},
setupgradeNotificationCurrentState: null,
};
function UpgradeNotification({
accessExpiration,
contentTypeGatingEnabled,
courseId,
offer,
org,
setupgradeNotificationCurrentState,
shouldDisplayBorder,
timeOffsetMillis,
upsellPageName,
userTimezone,
verifiedMode,
}) {
const timezoneFormatArgs = userTimezone ? { timeZone: userTimezone } : {};
const correctedTime = new Date(Date.now() + timeOffsetMillis);
if (!verifiedMode) {
return null;
}
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);
}, []);
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,
});
};
/*
There are 4 parts that change in the upgrade card:
upgradeNotificationHeaderText
expirationBanner
upsellMessage
offerCode
*/
let upgradeNotificationHeaderText;
let expirationBanner;
let upsellMessage;
let offerCode;
if (!!accessExpiration && !!contentTypeGatingEnabled) {
const accessExpirationDate = new Date(accessExpiration.expirationDate);
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 { // more urgent messaging if there's less than 7 days left to access expiration
upgradeNotificationHeaderText = (
);
expirationBanner = (
);
upsellMessage = (
);
}
} else { // FBE is turned off
upgradeNotificationHeaderText = (
);
upsellMessage = ();
}
if (offer) { // if there's a first purchase discount, message the code at the bottom
offerCode = (
{offer.code}),
}}
/>
);
}
return (
{expirationBanner}
{upsellMessage}
{offerCode}
);
}
UpgradeNotification.propTypes = {
courseId: PropTypes.string.isRequired,
org: PropTypes.string.isRequired,
accessExpiration: PropTypes.shape({
expirationDate: PropTypes.string,
}),
contentTypeGatingEnabled: PropTypes.bool,
offer: PropTypes.shape({
expirationDate: PropTypes.string,
percentage: PropTypes.number,
code: PropTypes.string,
}),
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,
offer: null,
setupgradeNotificationCurrentState: null,
shouldDisplayBorder: null,
timeOffsetMillis: 0,
userTimezone: null,
verifiedMode: null,
};
export default injectIntl(UpgradeNotification);