diff --git a/src/course-home/outline-tab/OutlineTab.test.jsx b/src/course-home/outline-tab/OutlineTab.test.jsx
index 460cfe4f..28f7f452 100644
--- a/src/course-home/outline-tab/OutlineTab.test.jsx
+++ b/src/course-home/outline-tab/OutlineTab.test.jsx
@@ -659,6 +659,40 @@ describe('Outline Tab', () => {
await fetchAndRender();
expect(screen.queryByText('Your grade and certificate will be ready soon!')).toBeInTheDocument();
});
+ it('renders verification alert', async () => {
+ const now = new Date();
+ const yesterday = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1);
+ const tomorrow = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1);
+ setMetadata({ is_enrolled: true });
+ setTabData({
+ cert_data: {
+ cert_status: CERT_STATUS_TYPE.UNVERIFIED,
+ cert_web_view_url: null,
+ download_url: null,
+ },
+ }, {
+ date_blocks: [
+ {
+ date_type: 'course-end-date',
+ date: yesterday.toISOString(),
+ title: 'End',
+ },
+ {
+ date_type: 'certificate-available-date',
+ date: tomorrow.toISOString(),
+ title: 'Cert Available',
+ },
+ {
+ date_type: 'verification-deadline-date',
+ date: tomorrow.toISOString(),
+ link_text: 'Verify',
+ title: 'Verification Upgrade Deadline',
+ },
+ ],
+ });
+ await fetchAndRender();
+ expect(screen.queryByText('Verify your identity to earn a certificate!')).toBeInTheDocument();
+ });
});
});
diff --git a/src/course-home/outline-tab/alerts/certificate-status-alert/CertificateStatusAlert.jsx b/src/course-home/outline-tab/alerts/certificate-status-alert/CertificateStatusAlert.jsx
index ea993e18..47a1be18 100644
--- a/src/course-home/outline-tab/alerts/certificate-status-alert/CertificateStatusAlert.jsx
+++ b/src/course-home/outline-tab/alerts/certificate-status-alert/CertificateStatusAlert.jsx
@@ -8,13 +8,15 @@ import {
} from '@edx/frontend-platform/i18n';
import { Alert, Button } from '@edx/paragon';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faCheckCircle } from '@fortawesome/free-solid-svg-icons';
+import { faCheckCircle, faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
+import { getConfig } from '@edx/frontend-platform';
import certMessages from './messages';
import certStatusMessages from '../../../progress-tab/certificate-status/messages';
export const CERT_STATUS_TYPE = {
EARNED_NOT_AVAILABLE: 'earned_but_not_available',
DOWNLOADABLE: 'downloadable',
+ UNVERIFIED: 'unverified',
};
function CertificateStatusAlert({ intl, payload }) {
@@ -27,65 +29,109 @@ function CertificateStatusAlert({ intl, payload }) {
userTimezone,
} = payload;
- let variant = '';
- if (certStatusType === CERT_STATUS_TYPE.EARNED_NOT_AVAILABLE || certStatusType === CERT_STATUS_TYPE.DOWNLOADABLE) {
- variant = 'success';
- }
+ // eslint-disable-next-line react/prop-types
+ const AlertWrapper = (props) => props.children(props);
- let header = '';
- let body = '';
- let buttonVisible = false;
- let buttonMessage = '';
-
- if (certStatusType === CERT_STATUS_TYPE.EARNED_NOT_AVAILABLE) {
- const timezoneFormatArgs = userTimezone ? { timeZone: userTimezone } : {};
- const certificateAvailableDateFormatted = ;
- const courseEndDateFormatted = ;
-
- header = intl.formatMessage(certMessages.certStatusEarnedNotAvailableHeader);
- body = (
-
-
-
- );
- } else if (certStatusType === CERT_STATUS_TYPE.DOWNLOADABLE) {
- header = intl.formatMessage(certMessages.certStatusDownloadableHeader);
- if (isWebCert) {
- buttonMessage = intl.formatMessage(certStatusMessages.viewableButton);
- } else {
- buttonMessage = intl.formatMessage(certStatusMessages.downloadableButton);
+ const renderCertAwardedStatus = () => {
+ const alertProps = {
+ variant: 'success',
+ icon: faCheckCircle,
+ iconClassName: 'alert-icon text-success-500',
+ };
+ if (certStatusType === CERT_STATUS_TYPE.EARNED_NOT_AVAILABLE) {
+ const timezoneFormatArgs = userTimezone ? { timeZone: userTimezone } : {};
+ const certificateAvailableDateFormatted = ;
+ const courseEndDateFormatted = ;
+ alertProps.header = intl.formatMessage(certMessages.certStatusEarnedNotAvailableHeader);
+ alertProps.body = (
+
+
+
+ );
+ } else if (certStatusType === CERT_STATUS_TYPE.DOWNLOADABLE) {
+ alertProps.header = intl.formatMessage(certMessages.certStatusDownloadableHeader);
+ if (isWebCert) {
+ alertProps.buttonMessage = intl.formatMessage(certStatusMessages.viewableButton);
+ } else {
+ alertProps.buttonMessage = intl.formatMessage(certStatusMessages.downloadableButton);
+ }
+ alertProps.buttonVisible = true;
+ alertProps.buttonLink = certURL;
}
- buttonVisible = true;
+ return alertProps;
+ };
+
+ const renderNotIDVerifiedStatus = () => {
+ const alertProps = {
+ variant: 'warning',
+ icon: faExclamationTriangle,
+ iconClassName: 'alert-icon text-warning-500',
+ header: intl.formatMessage(certStatusMessages.unverifiedHomeHeader),
+ buttonMessage: intl.formatMessage(certStatusMessages.unverifiedHomeButton),
+ body: intl.formatMessage(certStatusMessages.unverifiedHomeBody),
+ buttonVisible: true,
+ buttonLink: getConfig().SUPPORT_URL_ID_VERIFICATION,
+ };
+
+ return alertProps;
+ };
+
+ let alertProps = {};
+ switch (certStatusType) {
+ case CERT_STATUS_TYPE.EARNED_NOT_AVAILABLE:
+ case CERT_STATUS_TYPE.DOWNLOADABLE:
+ alertProps = renderCertAwardedStatus();
+ break;
+ case CERT_STATUS_TYPE.UNVERIFIED:
+ alertProps = renderNotIDVerifiedStatus();
+ break;
+ default:
+ break;
}
+
return (
-
-
-
- {buttonVisible && (
-
-
+
+ {({
+ variant,
+ buttonVisible,
+ iconClassName,
+ icon,
+ header,
+ buttonLink,
+ body,
+ buttonMessage,
+ }) => (
+
+
+
+ {buttonVisible && (
+
+
+
+ )}
- )}
-
-
+
+
+ )}
+
);
}
diff --git a/src/course-home/outline-tab/alerts/certificate-status-alert/hooks.js b/src/course-home/outline-tab/alerts/certificate-status-alert/hooks.js
index 99c6b241..2f2f130f 100644
--- a/src/course-home/outline-tab/alerts/certificate-status-alert/hooks.js
+++ b/src/course-home/outline-tab/alerts/certificate-status-alert/hooks.js
@@ -16,6 +16,9 @@ function verifyCertStatusType(status) {
if (status === CERT_STATUS_TYPE.EARNED_NOT_AVAILABLE) {
return CERT_STATUS_TYPE.EARNED_NOT_AVAILABLE;
}
+ if (status === CERT_STATUS_TYPE.UNVERIFIED) {
+ return CERT_STATUS_TYPE.UNVERIFIED;
+ }
return '';
}
@@ -37,9 +40,7 @@ function useCertificateStatusAlert(courseId) {
certificateAvailableDate,
downloadUrl,
} = certData || {};
-
const endBlock = courseDateBlocks.find(b => b.dateType === 'course-end-date');
-
const certStatusType = verifyCertStatusType(certStatus);
const isWebCert = downloadUrl === null;
diff --git a/src/course-home/progress-tab/certificate-status/messages.js b/src/course-home/progress-tab/certificate-status/messages.js
index f8253eba..13dde252 100644
--- a/src/course-home/progress-tab/certificate-status/messages.js
+++ b/src/course-home/progress-tab/certificate-status/messages.js
@@ -77,6 +77,18 @@ const messages = defineMessages({
id: 'progress.certificateStatus.upgradeButton',
defaultMessage: 'Upgrade now',
},
+ unverifiedHomeHeader: {
+ id: 'progress.certificateStatus.unverifiedHomeHeader',
+ defaultMessage: 'Verify your identity to earn a certificate!',
+ },
+ unverifiedHomeButton: {
+ id: 'progress.certificateStatus.unverifiedHomeButton',
+ defaultMessage: 'Verify my ID',
+ },
+ unverifiedHomeBody: {
+ id: 'progress.certificateStatus.unverifiedHomeBody',
+ defaultMessage: 'In order to generate a certificate for this course, you must complete the ID verification process.',
+ },
});
export default messages;
diff --git a/src/setupTest.js b/src/setupTest.js
index fdfcf91e..4fb05c6e 100755
--- a/src/setupTest.js
+++ b/src/setupTest.js
@@ -82,7 +82,7 @@ export function initializeMockApp() {
roles: [],
administrator: false,
},
- SUPPORT_URL_ID_VERIFICATION: true,
+ SUPPORT_URL_ID_VERIFICATION: 'http://example.com',
});
const loggingService = configureLogging(MockLoggingService, {