import React, { useEffect } from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faLinkedinIn } from '@fortawesome/free-brands-svg-icons'; import { FormattedDate, FormattedMessage, useIntl } from '@edx/frontend-platform/i18n'; import { Helmet } from 'react-helmet'; import { useDispatch, useSelector } from 'react-redux'; import { Alert, breakpoints, Button, Hyperlink, useWindowSize, } from '@openedx/paragon'; import { CheckCircle } from '@openedx/paragon/icons'; import { getConfig } from '@edx/frontend-platform'; import { getAuthenticatedUser } from '@edx/frontend-platform/auth'; import CelebrationMobile from './assets/celebration_456x328.gif'; import CelebrationDesktop from './assets/celebration_750x540.gif'; import certificate from '../../../generic/assets/openedx_certificate.png'; import certificateLocked from '../../../generic/assets/openedx_locked_certificate.png'; import { FormattedPricing } from '../../../generic/upgrade-button'; import messages from './messages'; import { useModel } from '../../../generic/model-store'; import { requestCert } from '../../../course-home/data/thunks'; import ProgramCompletion from './ProgramCompletion'; import UpgradeFootnote from './UpgradeFootnote'; import SocialIcons from '../../social-share/SocialIcons'; import { logClick, logVisit } from './utils'; import { DashboardLink, IdVerificationSupportLink, ProfileLink } from '../../../shared/links'; import DashboardFootnote from './DashboardFootnote'; import { CourseRecommendationsSlot } from '../../../plugin-slots/CourseExitPluginSlots'; const LINKEDIN_BLUE = '#2867B2'; const CourseCelebration = () => { const intl = useIntl(); const wideScreen = useWindowSize().width >= breakpoints.medium.minWidth; const { courseId } = useSelector(state => state.courseware); const dispatch = useDispatch(); const { certificateData, end, linkedinAddToProfileUrl, marketingUrl, offer, relatedPrograms, title, verifyIdentityUrl, verificationStatus, } = useModel('coursewareMeta', courseId); const { org, verifiedMode, canViewCertificate, userTimezone, } = useModel('courseHomeMeta', courseId); const { certStatus, certWebViewUrl, certificateAvailableDate, } = certificateData || {}; const { administrator } = getAuthenticatedUser(); const dashboardLink = ; const idVerificationSupportLink = ; const profileLink = ; const timezoneFormatArgs = userTimezone ? { timeZone: userTimezone } : {}; let buttonPrefix = null; let buttonLocation; let buttonText; let buttonVariant = 'outline-primary'; let buttonEvent = null; let buttonSuffix = null; let certificateImage = certificate; let footnote; let message; let certHeader; let visitEvent = 'celebration_generic'; // These cases are taken from the edx-platform `get_cert_data` function found in lms/courseware/views/views.py switch (certStatus) { case 'downloadable': certHeader = intl.formatMessage(messages.certificateHeaderDownloadable); message = (

); if (certWebViewUrl) { buttonLocation = `${getConfig().LMS_BASE_URL}${certWebViewUrl}`; buttonText = intl.formatMessage(messages.viewCertificateButton); } if (linkedinAddToProfileUrl) { buttonPrefix = ( ); } buttonEvent = 'view_cert'; visitEvent = 'celebration_with_cert'; footnote = ; break; case 'earned_but_not_available': { const endDate = ; const certAvailableDate = ; certHeader = intl.formatMessage(messages.certificateHeaderNotAvailable); message = ( <>

{intl.formatMessage(messages.certificateNotAvailableBodyAccessCert)}

); visitEvent = 'celebration_with_unavailable_cert'; footnote = ; break; } case 'requesting': // The requesting status needs a different button because it does a POST instead of a GET. // So we don't set buttonLocation and instead define a custom button as a buttonPrefix. buttonEvent = 'request_cert'; buttonPrefix = ( ); certHeader = intl.formatMessage(messages.certificateHeaderRequestable); message = (

{intl.formatMessage(messages.requestCertificateBodyText)}

); visitEvent = 'celebration_with_requestable_cert'; footnote = ; break; case 'unverified': certHeader = intl.formatMessage(messages.certificateHeaderUnverified); visitEvent = 'celebration_unverified'; footnote = ; if (verificationStatus === 'pending') { message = (

{intl.formatMessage(messages.verificationPending)}

); } else { buttonText = intl.formatMessage(messages.verifyIdentityButton); buttonEvent = 'verify_id'; buttonLocation = verifyIdentityUrl; // todo: check for idVerificationSupportLink null message = (

); } break; case 'audit_passing': case 'honor_passing': if (verifiedMode) { certHeader = intl.formatMessage(messages.certificateHeaderUpgradable); message = (

}} description="Body text when the learner needs to upgrade to earn a certifcate and they have passed the course" />
{getConfig().SUPPORT_URL_VERIFIED_CERTIFICATE && ( {intl.formatMessage(messages.verifiedCertificateSupportLink)} )}

); buttonText = intl.formatMessage(messages.upgradeButton); buttonEvent = 'upgrade'; buttonLocation = verifiedMode.upgradeUrl; buttonVariant = 'primary'; if (offer) { buttonSuffix = ( {offer.code}), percent: offer.percentage, }} description="Shown if learner can use a discount code when they upgrade the course" /> ); } certificateImage = certificateLocked; visitEvent = 'celebration_upgrade'; if (verifiedMode.accessExpirationDate) { footnote = ; } else { footnote = ; } } else { visitEvent = 'celebration_audit_no_upgrade'; } break; default: if (!canViewCertificate) { // We reuse the cert event here. Since this default state is so // Similar to the earned_not_available state, this event name should be fine // to cover the same cases. visitEvent = 'celebration_with_unavailable_cert'; certHeader = intl.formatMessage(messages.certificateHeaderNotAvailable); const endDate = intl.formatDate(end, { year: 'numeric', month: 'long', day: 'numeric', ...timezoneFormatArgs, }); message = ( <>

{intl.formatMessage(messages.certificateNotAvailableEndDateBody, { endDate })}

{intl.formatMessage(messages.certificateNotAvailableBodyAccessCert)}

); } break; } useEffect(() => logVisit(org, courseId, administrator, visitEvent), [org, courseId, administrator, visitEvent]); return ( <> {`${intl.formatMessage(messages.congratulationsHeader)} | ${title} | ${getConfig().SITE_NAME}`}
{intl.formatMessage(messages.congratulationsHeader)}
{intl.formatMessage(messages.completedCourseHeader)} {marketingUrl && ` ${intl.formatMessage(messages.shareMessage)}`}
{!wideScreen && ( {`${intl.formatMessage(messages.congratulationsImage)}`} )} {wideScreen && ( {`${intl.formatMessage(messages.congratulationsImage)}`} )}
{certHeader && (
{certHeader}
{message}
{buttonPrefix} {buttonLocation && ( )} {buttonSuffix}
{certStatus !== 'unverified' && (
{`${intl.formatMessage(messages.certificateImage)}`}
)}
)} {relatedPrograms && relatedPrograms.map(program => ( ))} {footnote}
); }; export default CourseCelebration;