feat: add recommendations modal
Description: Add recommendations buttons and modal for painted door experiment VAN-1601
This commit is contained in:
60
src/components/ModalView/index.jsx
Normal file
60
src/components/ModalView/index.jsx
Normal file
@@ -0,0 +1,60 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { ModalDialog, ActionRow, Button } from '@edx/paragon';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import messages from './messages';
|
||||
|
||||
export const ModalView = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
}) => {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const handleClose = () => {
|
||||
onClose(false);
|
||||
};
|
||||
return (
|
||||
<div className="containers">
|
||||
<ModalDialog
|
||||
title=""
|
||||
isOpen={isOpen}
|
||||
onClose={handleClose}
|
||||
hasCloseButton={false}
|
||||
isFullscreenScroll
|
||||
>
|
||||
<ModalDialog.Header>
|
||||
<ModalDialog.Title>
|
||||
<h3 className="mt-2">{formatMessage(messages.recommendationsModalHeading)}</h3>
|
||||
</ModalDialog.Title>
|
||||
</ModalDialog.Header>
|
||||
<ModalDialog.Body>
|
||||
<div className="modal-continer">
|
||||
<p className="mt-2">{formatMessage(messages.recommendationsFeatureText)}</p>
|
||||
<p>{formatMessage(messages.recommendationsAlertedText)}</p>
|
||||
</div>
|
||||
</ModalDialog.Body>
|
||||
<ModalDialog.Footer>
|
||||
<ActionRow>
|
||||
<ModalDialog.CloseButton variant="tertiary">
|
||||
{formatMessage(messages.modalSkipButton)}
|
||||
</ModalDialog.CloseButton>
|
||||
<Button variant="primary">{formatMessage(messages.modalCountMeButton)}</Button>
|
||||
</ActionRow>
|
||||
</ModalDialog.Footer>
|
||||
</ModalDialog>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ModalView.defaultProps = {
|
||||
isOpen: false,
|
||||
onClose: () => {},
|
||||
};
|
||||
|
||||
ModalView.propTypes = {
|
||||
onClose: PropTypes.func,
|
||||
isOpen: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default ModalView;
|
||||
31
src/components/ModalView/messages.js
Normal file
31
src/components/ModalView/messages.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
recommendationsFeatureText: {
|
||||
id: 'RecommendationsPanel.recommendationsFeatureText',
|
||||
defaultMessage: 'Personalized recommendations feature is not yet available. We are working hard on bringing it to your learner home in the near future.',
|
||||
description: 'recommendations feature text',
|
||||
},
|
||||
recommendationsAlertedText: {
|
||||
id: 'RecommendationsPanel.recommendationsAlertedText',
|
||||
defaultMessage: 'Would you like to be alerted when it becomes available?',
|
||||
description: 'recommendations alerted text',
|
||||
},
|
||||
recommendationsModalHeading: {
|
||||
id: 'RecommendationsPanel.recommendationsModalHeading',
|
||||
defaultMessage: 'Thank you for your interest!',
|
||||
description: 'Heading of modal',
|
||||
},
|
||||
modalSkipButton: {
|
||||
id: 'RecommendationsPanel.modalSkipButton',
|
||||
defaultMessage: 'Skip for now',
|
||||
description: 'button for Skip for now',
|
||||
},
|
||||
modalCountMeButton: {
|
||||
id: 'RecommendationsPanel.modalCountMeButton',
|
||||
defaultMessage: 'Count me in!',
|
||||
description: 'button for Count me in!',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
@@ -12,9 +12,10 @@ import { reduxHooks } from 'hooks';
|
||||
|
||||
import { findCoursesNavDropdownClicked } from '../hooks';
|
||||
|
||||
import ModalView from '../../../components/ModalView';
|
||||
import messages from '../messages';
|
||||
|
||||
export const CollapseMenuBody = ({ isOpen }) => {
|
||||
export const CollapseMenuBody = ({ isOpen, isRecommendationModalOpen, setRecommendationModal }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
const { authenticatedUser } = React.useContext(AppContext);
|
||||
|
||||
@@ -40,6 +41,12 @@ export const CollapseMenuBody = ({ isOpen }) => {
|
||||
>
|
||||
{formatMessage(messages.discoverNew)}
|
||||
</Button>
|
||||
<Button
|
||||
variant="inverse-primary"
|
||||
onClick={() => setRecommendationModal(true)}
|
||||
>
|
||||
{formatMessage(messages.recommendedForYou)}
|
||||
</Button>
|
||||
<Button as="a" href={getConfig().SUPPORT_URL} variant="inverse-primary">
|
||||
{formatMessage(messages.help)}
|
||||
</Button>
|
||||
@@ -92,6 +99,7 @@ export const CollapseMenuBody = ({ isOpen }) => {
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
<ModalView isOpen={isRecommendationModalOpen} onClose={setRecommendationModal} />
|
||||
</div>
|
||||
)
|
||||
);
|
||||
@@ -99,6 +107,13 @@ export const CollapseMenuBody = ({ isOpen }) => {
|
||||
|
||||
CollapseMenuBody.propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
isRecommendationModalOpen: PropTypes.bool,
|
||||
setRecommendationModal: PropTypes.func,
|
||||
};
|
||||
|
||||
CollapseMenuBody.defaultProps = {
|
||||
isRecommendationModalOpen: false,
|
||||
setRecommendationModal: () => {},
|
||||
};
|
||||
|
||||
export default CollapseMenuBody;
|
||||
|
||||
@@ -26,6 +26,12 @@ exports[`CollapseMenuBody render 1`] = `
|
||||
>
|
||||
Discover New
|
||||
</Button>
|
||||
<Button
|
||||
onClick={[Function]}
|
||||
variant="inverse-primary"
|
||||
>
|
||||
Recommended for you
|
||||
</Button>
|
||||
<Button
|
||||
as="a"
|
||||
href="http://localhost:18000/support"
|
||||
@@ -61,6 +67,10 @@ exports[`CollapseMenuBody render 1`] = `
|
||||
>
|
||||
Sign Out
|
||||
</Button>
|
||||
<ModalView
|
||||
isOpen={false}
|
||||
onClose={[Function]}
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -92,6 +102,12 @@ exports[`CollapseMenuBody render unauthenticated 1`] = `
|
||||
>
|
||||
Discover New
|
||||
</Button>
|
||||
<Button
|
||||
onClick={[Function]}
|
||||
variant="inverse-primary"
|
||||
>
|
||||
Recommended for you
|
||||
</Button>
|
||||
<Button
|
||||
as="a"
|
||||
href="http://localhost:18000/support"
|
||||
@@ -99,5 +115,9 @@ exports[`CollapseMenuBody render unauthenticated 1`] = `
|
||||
>
|
||||
Help
|
||||
</Button>
|
||||
<ModalView
|
||||
isOpen={false}
|
||||
onClose={[Function]}
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Menu, Close } from '@edx/paragon/icons';
|
||||
@@ -15,6 +15,7 @@ export const CollapsedHeader = () => {
|
||||
const { formatMessage } = useIntl();
|
||||
const isCollapsed = useIsCollapsed();
|
||||
const { isOpen, toggleIsOpen } = useLearnerDashboardHeaderData();
|
||||
const [isRecommendationModalOpen, setRecommendationModal] = useState(false);
|
||||
|
||||
return (
|
||||
isCollapsed && (
|
||||
@@ -36,7 +37,11 @@ export const CollapsedHeader = () => {
|
||||
/>
|
||||
<BrandLogo />
|
||||
</header>
|
||||
<CollapseMenuBody isOpen={isOpen} />
|
||||
<CollapseMenuBody
|
||||
isOpen={isOpen}
|
||||
setRecommendationModal={setRecommendationModal}
|
||||
isRecommendationModalOpen={isRecommendationModalOpen}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
@@ -11,12 +11,14 @@ import AuthenticatedUserDropdown from './AuthenticatedUserDropdown';
|
||||
|
||||
import { useIsCollapsed, findCoursesNavClicked } from '../hooks';
|
||||
import messages from '../messages';
|
||||
import ModalView from '../../../components/ModalView';
|
||||
import BrandLogo from '../BrandLogo';
|
||||
|
||||
export const ExpandedHeader = () => {
|
||||
const { formatMessage } = useIntl();
|
||||
const { courseSearchUrl } = reduxHooks.usePlatformSettingsData();
|
||||
const isCollapsed = useIsCollapsed();
|
||||
const [isRecommendationModalOpen, setRecommendationModal] = useState(false);
|
||||
|
||||
const exploreCoursesClick = findCoursesNavClicked(urls.baseAppUrl(courseSearchUrl));
|
||||
|
||||
@@ -51,6 +53,13 @@ export const ExpandedHeader = () => {
|
||||
>
|
||||
{formatMessage(messages.discoverNew)}
|
||||
</Button>
|
||||
<Button
|
||||
variant="inverse-primary"
|
||||
className="p-4"
|
||||
onClick={() => setRecommendationModal(true)}
|
||||
>
|
||||
{formatMessage(messages.recommendedForYou)}
|
||||
</Button>
|
||||
<span className="flex-grow-1" />
|
||||
<Button
|
||||
as="a"
|
||||
@@ -63,6 +72,7 @@ export const ExpandedHeader = () => {
|
||||
</div>
|
||||
|
||||
<AuthenticatedUserDropdown />
|
||||
<ModalView isOpen={isRecommendationModalOpen} onClose={setRecommendationModal} />
|
||||
</header>
|
||||
)
|
||||
);
|
||||
|
||||
@@ -51,6 +51,11 @@ const messages = defineMessages({
|
||||
defaultMessage: 'Discover New',
|
||||
description: 'Header link for switching to discover page.',
|
||||
},
|
||||
recommendedForYou: {
|
||||
id: 'learnerVariantDashboard.recommendedForYou',
|
||||
defaultMessage: 'Recommended for you',
|
||||
description: 'Header link for recommended page.',
|
||||
},
|
||||
logoAltText: {
|
||||
id: 'learnerVariantDashboard.logoAltText',
|
||||
defaultMessage: 'edX, Inc. Dashboard',
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Button } from '@edx/paragon';
|
||||
import { Search } from '@edx/paragon/icons';
|
||||
import { baseAppUrl } from 'data/services/lms/urls';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { reduxHooks } from 'hooks';
|
||||
import track from './track';
|
||||
import CourseCard from './components/CourseCard';
|
||||
import messages from './messages';
|
||||
import ModalView from '../../components/ModalView';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
@@ -18,34 +15,34 @@ export const LoadedView = ({
|
||||
isControl,
|
||||
}) => {
|
||||
const { formatMessage } = useIntl();
|
||||
const { courseSearchUrl } = reduxHooks.usePlatformSettingsData();
|
||||
const [isOpen, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="p-4 w-100 panel-background">
|
||||
<h3 className="pb-2">{isControl === false
|
||||
? formatMessage(messages.recommendationsHeading) : formatMessage(messages.popularCoursesHeading)}
|
||||
</h3>
|
||||
<div>
|
||||
{courses.map((course) => (
|
||||
<CourseCard
|
||||
key={course.courseKey}
|
||||
course={course}
|
||||
isControl={isControl}
|
||||
/>
|
||||
))}
|
||||
<>
|
||||
<div className="p-4 w-100 panel-background">
|
||||
<h3 className="pb-2">{isControl === false
|
||||
? formatMessage(messages.recommendationsHeading) : formatMessage(messages.popularCoursesHeading)}
|
||||
</h3>
|
||||
<div>
|
||||
{courses.map((course) => (
|
||||
<CourseCard
|
||||
key={course.courseKey}
|
||||
course={course}
|
||||
isControl={isControl}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className="text-center explore-courses-btn">
|
||||
<Button
|
||||
variant="brand"
|
||||
onClick={() => setOpen(true)}
|
||||
>
|
||||
{formatMessage(messages.seeAllRecommendationsButton)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-center explore-courses-btn">
|
||||
<Button
|
||||
variant="tertiary"
|
||||
iconBefore={Search}
|
||||
as="a"
|
||||
href={baseAppUrl(courseSearchUrl)}
|
||||
onClick={track.findCoursesWidgetClicked(baseAppUrl(courseSearchUrl))}
|
||||
>
|
||||
{formatMessage(messages.exploreCoursesButton)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<ModalView isOpen={isOpen} onClose={setOpen} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -16,6 +16,11 @@ const messages = defineMessages({
|
||||
defaultMessage: 'Explore courses',
|
||||
description: 'Button to explore more courses on recommendations panel',
|
||||
},
|
||||
seeAllRecommendationsButton: {
|
||||
id: 'RecommendationsPanel.seeAllRecommendationsButton',
|
||||
defaultMessage: 'See All Recommendations',
|
||||
description: 'Button to see all recommendations',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
|
||||
Reference in New Issue
Block a user