diff --git a/src/containers/CourseCard/components/CourseCardBanners/CourseBanner.jsx b/src/containers/CourseCard/components/CourseCardBanners/CourseBanner.jsx index db26b1c00..ea55d02c5 100644 --- a/src/containers/CourseCard/components/CourseCardBanners/CourseBanner.jsx +++ b/src/containers/CourseCard/components/CourseCardBanners/CourseBanner.jsx @@ -18,7 +18,12 @@ export const CourseBanner = ({ cardId }) => { const { formatMessage } = useIntl(); const formatDate = utilHooks.useFormatDate(); - const { hasUnmetPrerequisites, isStaff, isTooEarly } = coursewareAccess; + const { + hasUnmetPrerequisites, + isStaff, + isTooEarly, + hasUnmetPrerequisitesList, + } = coursewareAccess; if (isVerified) { return null; } @@ -44,7 +49,15 @@ export const CourseBanner = ({ cardId }) => { )} {(!isStaff && hasUnmetPrerequisites) && ( - {formatMessage(messages.prerequisitesNotMet)} + + {formatMessage(messages.prerequisitesNotMet)} + {hasUnmetPrerequisitesList.length > 0 && hasUnmetPrerequisitesList.map((prerequisite, index) => ( + <> + {index > 0 ? ', ' : ' '} + {prerequisite.display} + + ))} + )} ); diff --git a/src/containers/CourseCard/components/CourseCardBanners/CourseBanner.test.jsx b/src/containers/CourseCard/components/CourseCardBanners/CourseBanner.test.jsx index 42d40331c..c20dbfc31 100644 --- a/src/containers/CourseCard/components/CourseCardBanners/CourseBanner.test.jsx +++ b/src/containers/CourseCard/components/CourseCardBanners/CourseBanner.test.jsx @@ -71,9 +71,31 @@ describe('CourseBanner', () => { }); describe('unmet prerequisites', () => { it('should display correct message', () => { - renderCourseBanner({ enrollment: { coursewareAccess: { hasUnmetPrerequisites: true } } }); + renderCourseBanner({ + enrollment: { + coursewareAccess: { + hasUnmetPrerequisites: true, + hasUnmetPrerequisitesList: [ + { + display: 'Prereq Course 1', + about_url: 'https://example.com/about-1', + }, + { + display: 'Prereq Course 2', + about_url: 'https://example.com/about-2', + }, + ], + }, + }, + }); const preReqText = screen.getByText(formatMessage(messages.prerequisitesNotMet)); expect(preReqText).toBeInTheDocument(); + const preReqList1 = screen.getByText('Prereq Course 1'); + const preReqList2 = screen.getByText('Prereq Course 2'); + expect(preReqList1).toBeInTheDocument(); + expect(preReqList2).toBeInTheDocument(); + expect(preReqList1).toHaveAttribute('href', 'https://example.com/about-1'); + expect(preReqList2).toHaveAttribute('href', 'https://example.com/about-2'); }); }); describe('too early', () => { diff --git a/src/containers/CourseCard/components/CourseCardBanners/messages.js b/src/containers/CourseCard/components/CourseCardBanners/messages.js index a68c48ebb..b5e472542 100644 --- a/src/containers/CourseCard/components/CourseCardBanners/messages.js +++ b/src/containers/CourseCard/components/CourseCardBanners/messages.js @@ -94,7 +94,7 @@ const messages = defineMessages({ prerequisitesNotMet: { id: 'learner-dash.courseCard.banners.prerequisitesNotMet', description: 'Message to learners with unmet prerequisites', - defaultMessage: 'You can\'t access this course just yet because you have not met the pre-requisites.', + defaultMessage: 'You can\'t access this course just yet because you have not met the following pre-requisites:', }, courseHasNotStarted: { id: 'learner-dash.courseCard.banners.courseHasNotStarted', diff --git a/src/containers/CourseCard/components/hooks.js b/src/containers/CourseCard/components/hooks.js index 9d80c0ae9..24625bc24 100644 --- a/src/containers/CourseCard/components/hooks.js +++ b/src/containers/CourseCard/components/hooks.js @@ -3,7 +3,7 @@ import { reduxHooks } from 'hooks'; export const useActionDisabledState = (cardId) => { const { isMasquerading } = reduxHooks.useMasqueradeData(); const { - hasAccess, isAudit, isAuditAccessExpired, + hasAccess, isAudit, isAuditAccessExpired, coursewareAccess, } = reduxHooks.useCardEnrollmentData(cardId); const { isEntitlement, isFulfilled, canChange, hasSessions, @@ -11,12 +11,43 @@ export const useActionDisabledState = (cardId) => { const { resumeUrl, homeUrl } = reduxHooks.useCardCourseRunData(cardId); - const disableBeginCourse = !homeUrl || (isMasquerading || !hasAccess || (isAudit && isAuditAccessExpired)); - const disableResumeCourse = !resumeUrl || (isMasquerading || !hasAccess || (isAudit && isAuditAccessExpired)); - const disableViewCourse = !hasAccess || (isAudit && isAuditAccessExpired); - const disableSelectSession = !isEntitlement || isMasquerading || !hasAccess || (!canChange || !hasSessions); + const isStaff = Boolean(coursewareAccess?.isStaff) || false; + const blockedByPrereqs = Boolean(coursewareAccess?.hasUnmetPrerequisites); - const disableCourseTitle = (isEntitlement && !isFulfilled) || disableViewCourse; + const disableBeginCourse = !isStaff && ( + !homeUrl + || isMasquerading + || !hasAccess + || (isAudit && isAuditAccessExpired) + || blockedByPrereqs + ); + + const disableResumeCourse = !isStaff && ( + !resumeUrl + || (isMasquerading + || !hasAccess + || (isAudit && isAuditAccessExpired)) + || blockedByPrereqs + ); + + const disableViewCourse = !isStaff && ( + !hasAccess + || (isAudit && isAuditAccessExpired) + || blockedByPrereqs + ); + + const disableSelectSession = !isStaff && ( + !isEntitlement + || isMasquerading + || !hasAccess + || (!canChange || !hasSessions) + || blockedByPrereqs + ); + + const disableCourseTitle = !isStaff && ( + (isEntitlement && !isFulfilled) + || disableViewCourse + ); return { disableBeginCourse, @@ -24,6 +55,7 @@ export const useActionDisabledState = (cardId) => { disableViewCourse, disableSelectSession, disableCourseTitle, + blockedByPrereqs, }; };