Compare commits

...

3 Commits

Author SHA1 Message Date
Alexander Sheehan
63bbf8d2a3 WIP: iterative steps towards demoable (non-real world functioning) product 2021-08-12 12:08:33 -04:00
manny-m
39e046f09d feat: added PartnetWelcome componenet 2021-08-11 16:52:38 -04:00
Alexander Sheehan
14c1f5b944 feat: beginnings of the recruit me some money exploits 2021-08-11 10:48:16 -04:00
9 changed files with 353 additions and 123 deletions

View File

@@ -12,7 +12,7 @@ import {
import messages from './messages'; import messages from './messages';
const AuthExtraLargeLayout = (props) => { const AuthExtraLargeLayout = (props) => {
const { intl, username, variant } = props; const { intl, username, variant, toggleWelcomeText } = props;
return ( return (
<div className="container row p-0 m-0 large-screen-container"> <div className="container row p-0 m-0 large-screen-container">
@@ -48,21 +48,23 @@ const AuthExtraLargeLayout = (props) => {
messages['welcome.to.platform'], { siteName: getConfig().SITE_NAME, username }, messages['welcome.to.platform'], { siteName: getConfig().SITE_NAME, username },
)} )}
</div> </div>
<div { !toggleWelcomeText ? (
className={classNames( <div
'text-primary', className={classNames(
{ 'text-primary',
'display-1': variant === 'xl', {
'display-2': variant === 'xxl', 'display-1': variant === 'xl',
}, 'display-2': variant === 'xxl',
)} },
> )}
{intl.formatMessage(messages['complete.your.profile.1'])} >
<span className="text-accent-a"> {intl.formatMessage(messages['complete.your.profile.1'])}
<br /> <span className="text-accent-a">
{intl.formatMessage(messages['complete.your.profile.2'])} <br />
</span> {intl.formatMessage(messages['complete.your.profile.2'])}
</div> </span>
</div>
) : null}
</Col> </Col>
</Row> </Row>
</div> </div>
@@ -86,12 +88,14 @@ const AuthExtraLargeLayout = (props) => {
AuthExtraLargeLayout.defaultProps = { AuthExtraLargeLayout.defaultProps = {
variant: 'xl', variant: 'xl',
toggleWelcomeText: false,
}; };
AuthExtraLargeLayout.propTypes = { AuthExtraLargeLayout.propTypes = {
intl: intlShape.isRequired, intl: intlShape.isRequired,
username: PropTypes.string.isRequired, username: PropTypes.string.isRequired,
variant: PropTypes.oneOf(['xl', 'xxl']), variant: PropTypes.oneOf(['xl', 'xxl']),
toggleWelcomeText: PropTypes.bool,
}; };
export default injectIntl(AuthExtraLargeLayout); export default injectIntl(AuthExtraLargeLayout);

View File

@@ -11,7 +11,7 @@ import {
import messages from './messages'; import messages from './messages';
const AuthMediumLayout = (props) => { const AuthMediumLayout = (props) => {
const { intl, username } = props; const { intl, username, toggleWelcomeText } = props;
return ( return (
<div className="container row p-0 mb-3 medium-container"> <div className="container row p-0 mb-3 medium-container">
@@ -33,13 +33,15 @@ const AuthMediumLayout = (props) => {
messages['welcome.to.platform'], { siteName: getConfig().SITE_NAME, username }, messages['welcome.to.platform'], { siteName: getConfig().SITE_NAME, username },
)} )}
</h3> </h3>
<div className="display-1 text-primary"> { !toggleWelcomeText ? (
{intl.formatMessage(messages['complete.your.profile.1'])} <div className="display-1 text-primary">
<span className="text-accent-a"> {intl.formatMessage(messages['complete.your.profile.1'])}
<br /> <span className="text-accent-a">
{intl.formatMessage(messages['complete.your.profile.2'])} <br />
</span> {intl.formatMessage(messages['complete.your.profile.2'])}
</div> </span>
</div>
) : null}
</Col> </Col>
</Row> </Row>
</div> </div>
@@ -61,9 +63,15 @@ const AuthMediumLayout = (props) => {
); );
}; };
AuthMediumLayout.defaultProps = {
toggleWelcomeText: false,
};
AuthMediumLayout.propTypes = { AuthMediumLayout.propTypes = {
intl: intlShape.isRequired, intl: intlShape.isRequired,
username: PropTypes.string.isRequired, username: PropTypes.string.isRequired,
toggleWelcomeText: PropTypes.bool,
}; };
export default injectIntl(AuthMediumLayout); export default injectIntl(AuthMediumLayout);

View File

@@ -12,7 +12,7 @@ import {
import messages from './messages'; import messages from './messages';
const AuthSmallLayout = (props) => { const AuthSmallLayout = (props) => {
const { intl, username, variant } = props; const { intl, username, variant, toggleWelcomeText } = props;
return ( return (
<div className="small-screen-header-light"> <div className="small-screen-header-light">
@@ -40,13 +40,15 @@ const AuthSmallLayout = (props) => {
messages['welcome.to.platform'], { siteName: getConfig().SITE_NAME, username }, messages['welcome.to.platform'], { siteName: getConfig().SITE_NAME, username },
)} )}
</h5> </h5>
<h1> { !toggleWelcomeText ? (
{intl.formatMessage(messages['complete.your.profile.1'])} <h1>
<br /> {intl.formatMessage(messages['complete.your.profile.1'])}
<span className="text-accent-a"> <br />
{intl.formatMessage(messages['complete.your.profile.2'])} <span className="text-accent-a">
</span> {intl.formatMessage(messages['complete.your.profile.2'])}
</h1> </span>
</h1>
) : null}
</Col> </Col>
</Row> </Row>
</div> </div>
@@ -57,12 +59,14 @@ const AuthSmallLayout = (props) => {
AuthSmallLayout.defaultProps = { AuthSmallLayout.defaultProps = {
variant: 'sm', variant: 'sm',
toggleWelcomeText: false,
}; };
AuthSmallLayout.propTypes = { AuthSmallLayout.propTypes = {
intl: intlShape.isRequired, intl: intlShape.isRequired,
username: PropTypes.string.isRequired, username: PropTypes.string.isRequired,
variant: PropTypes.oneOf(['sm', 'xs']), variant: PropTypes.oneOf(['sm', 'xs']),
toggleWelcomeText: PropTypes.bool,
}; };
export default injectIntl(AuthSmallLayout); export default injectIntl(AuthSmallLayout);

View File

@@ -17,7 +17,7 @@ import AuthExtraLargeLayout from './AuthExtraLargeLayout';
import AuthMediumLayout from './AuthMediumLayout'; import AuthMediumLayout from './AuthMediumLayout';
import AuthSmallLayout from './AuthSmallLayout'; import AuthSmallLayout from './AuthSmallLayout';
const BaseComponent = ({ children }) => { const BaseComponent = ({ children, toggleWelcomeText }) => {
const authenticatedUser = getAuthenticatedUser(); const authenticatedUser = getAuthenticatedUser();
return ( return (
@@ -33,25 +33,25 @@ const BaseComponent = ({ children }) => {
<div className={classNames('layout', { authenticated: authenticatedUser })}> <div className={classNames('layout', { authenticated: authenticatedUser })}>
<ExtraSmall> <ExtraSmall>
<div className="col-md-12 small-screen-top-stripe" /> <div className="col-md-12 small-screen-top-stripe" />
{authenticatedUser ? <AuthSmallLayout variant="xs" username={authenticatedUser.username} /> : <SmallLayout />} {authenticatedUser ? <AuthSmallLayout toggleWelcomeText={toggleWelcomeText} variant="xs" username={authenticatedUser.username} /> : <SmallLayout />}
</ExtraSmall> </ExtraSmall>
<Small> <Small>
<div className="col-md-12 small-screen-top-stripe" /> <div className="col-md-12 small-screen-top-stripe" />
{authenticatedUser ? <AuthSmallLayout username={authenticatedUser.username} /> : <SmallLayout />} {authenticatedUser ? <AuthSmallLayout toggleWelcomeText={toggleWelcomeText} username={authenticatedUser.username} /> : <SmallLayout />}
</Small> </Small>
<Medium> <Medium>
<div className="w-100 medium-screen-top-stripe" /> <div className="w-100 medium-screen-top-stripe" />
{authenticatedUser ? <AuthMediumLayout username={authenticatedUser.username} /> : <MediumLayout />} {authenticatedUser ? <AuthMediumLayout toggleWelcomeText={toggleWelcomeText} username={authenticatedUser.username} /> : <MediumLayout />}
</Medium> </Medium>
<Large> <Large>
<div className="w-100 large-screen-top-stripe" /> <div className="w-100 large-screen-top-stripe" />
{authenticatedUser ? <AuthMediumLayout username={authenticatedUser.username} /> : <MediumLayout />} {authenticatedUser ? <AuthMediumLayout toggleWelcomeText={toggleWelcomeText} username={authenticatedUser.username} /> : <MediumLayout />}
</Large> </Large>
<ExtraLarge> <ExtraLarge>
{authenticatedUser ? <AuthExtraLargeLayout username={authenticatedUser.username} /> : <LargeLayout />} {authenticatedUser ? <AuthExtraLargeLayout toggleWelcomeText={toggleWelcomeText} username={authenticatedUser.username} /> : <LargeLayout />}
</ExtraLarge> </ExtraLarge>
<ExtraExtraLarge> <ExtraExtraLarge>
{authenticatedUser ? <AuthExtraLargeLayout variant="xxl" username={authenticatedUser.username} /> : <LargeLayout />} {authenticatedUser ? <AuthExtraLargeLayout toggleWelcomeText={toggleWelcomeText} variant="xxl" username={authenticatedUser.username} /> : <LargeLayout />}
</ExtraExtraLarge> </ExtraExtraLarge>
<div className={classNames('content', { 'align-items-center mt-0': authenticatedUser })}> <div className={classNames('content', { 'align-items-center mt-0': authenticatedUser })}>
@@ -64,6 +64,11 @@ const BaseComponent = ({ children }) => {
BaseComponent.propTypes = { BaseComponent.propTypes = {
children: PropTypes.node.isRequired, children: PropTypes.node.isRequired,
toggleWelcomeText: PropTypes.bool,
}; };
BaseComponent.defaultProps = {
toggleWelcomeText: false,
}
export default BaseComponent; export default BaseComponent;

View File

@@ -38,7 +38,7 @@ initialize({
DISABLE_ENTERPRISE_LOGIN: process.env.DISABLE_ENTERPRISE_LOGIN || '', DISABLE_ENTERPRISE_LOGIN: process.env.DISABLE_ENTERPRISE_LOGIN || '',
INFO_EMAIL: process.env.INFO_EMAIL || '', INFO_EMAIL: process.env.INFO_EMAIL || '',
REGISTER_CONVERSION_COOKIE_NAME: process.env.REGISTER_CONVERSION_COOKIE_NAME || null, REGISTER_CONVERSION_COOKIE_NAME: process.env.REGISTER_CONVERSION_COOKIE_NAME || null,
ENABLE_PROGRESSIVE_PROFILING: process.env.ENABLE_PROGRESSIVE_PROFILING || false, ENABLE_PROGRESSIVE_PROFILING: true,
}); });
}, },
}, },

View File

@@ -29,6 +29,8 @@ export const EDUCATION_LEVELS = [
'other', 'other',
]; ];
export const REGISTRATION_REASONS = ['', 'job', 'learn', 'boss'];
export const GENDER_OPTIONS = ['', 'f', 'm', 'o']; export const GENDER_OPTIONS = ['', 'f', 'm', 'o'];
// Other constants // Other constants

View File

@@ -0,0 +1,152 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import {
Form,
Button,
StatefulButton,
Hyperlink,
Icon,
Collapsible,
Image,
} from '@edx/paragon';
import { Pin, Tag, Email } from '@edx/paragon/icons';
import { getConfig } from '@edx/frontend-platform';
const logoStyle = { height: '4rem' };
const PartnerWelcome = ({ onComplete }) => {
const [formValues, setFormValues] = useState({ email: '', location: '', search: '' });
const onChangeHandler = (e) => {
setFormValues({ ...formValues, [e.target.name]: e.target.value });
};
const submitToPartnerButton = (href) => (
<Button
target="_blank"
rel="noopener noreferrer"
as="a"
href={href}
size="sm"
>
Submit
</Button>
);
return (
<>
<Form>
<Collapsible
styling="card-lg"
title={<Image style={logoStyle} src="https://www.ziprecruiter.com/zrs/starterview/f810ae13/img/logos/ziprecruiter-blacktext.svg" fluid />}
>
<Form.Group controlId="email">
<Form.Control
name="email"
value={formValues.email}
onChange={(e) => onChangeHandler(e)}
floatingLabel="Email"
trailingElement={<Icon src={Email} />}
/>
</Form.Group>
<Form.Group controlId="location">
<Form.Control
name="location"
value={formValues.location}
onChange={(e) => onChangeHandler(e)}
floatingLabel="Location"
trailingElement={<Icon src={Pin} />}
/>
</Form.Group>
<Form.Group controlId="search">
<Form.Control
name="search"
value={formValues.search}
onChange={(e) => onChangeHandler(e)}
floatingLabel="Desired Title"
trailingElement={<Icon src={Tag} />}
/>
</Form.Group>
<Form.Group>
{submitToPartnerButton('https://www.ziprecruiter.com/')}
</Form.Group>
</Collapsible>
<Collapsible
styling="card-lg"
title={<Image style={logoStyle} src="https://content.linkedin.com/content/dam/me/business/en-us/amp/brand-site/v2/bg/LI-Logo.svg.original.svg" fluid />}
>
<Form.Group controlId="email">
<Form.Control
name="email"
value={formValues.email}
onChange={(e) => onChangeHandler(e)}
floatingLabel="Email"
trailingElement={<Icon src={Email} />}
/>
</Form.Group>
<Form.Group controlId="location">
<Form.Control
name="location"
value={formValues.location}
onChange={(e) => onChangeHandler(e)}
floatingLabel="Location"
trailingElement={<Icon src={Pin} />}
/>
</Form.Group>
<Form.Group controlId="search">
<Form.Control
name="search"
value={formValues.search}
onChange={(e) => onChangeHandler(e)}
floatingLabel="Desired Title"
trailingElement={<Icon src={Tag} />}
/>
</Form.Group>
<Form.Group>
{submitToPartnerButton('https://www.linkedin.com/')}
</Form.Group>
</Collapsible>
<span className="progressive-profiling-support">
<Hyperlink
isInline
variant="muted"
destination={getConfig().WELCOME_PAGE_SUPPORT_LINK}
target="_blank"
showLaunchIcon={false}
>
Learn more about our partners
</Hyperlink>
</span>
<div className="d-flex mt-4">
<StatefulButton
type="submit"
variant="brand"
className="login-button-width"
state="active"
labels={{
default: 'Complete',
pending: '',
}}
onClick={onComplete}
onMouseDown={(e) => e.preventDefault()}
/>
</div>
</Form>
</>
);
};
PartnerWelcome.propTypes = {
onComplete: PropTypes.func.isRequired,
};
export default PartnerWelcome;

View File

@@ -30,8 +30,9 @@ import messages from './messages';
import { RedirectLogistration } from '../common-components'; import { RedirectLogistration } from '../common-components';
import { DEFAULT_REDIRECT_URL, DEFAULT_STATE } from '../data/constants'; import { DEFAULT_REDIRECT_URL, DEFAULT_STATE } from '../data/constants';
import { EDUCATION_LEVELS, GENDER_OPTIONS, YEAR_OF_BIRTH_OPTIONS } from '../register/data/constants'; import { EDUCATION_LEVELS, GENDER_OPTIONS, YEAR_OF_BIRTH_OPTIONS, REGISTRATION_REASONS } from '../register/data/constants';
import WelcomePageModal from './WelcomePageModal'; import WelcomePageModal from './WelcomePageModal';
import PartnerWelcome from './PartnerWelcome';
import BaseComponent from '../base-component'; import BaseComponent from '../base-component';
const WelcomePage = (props) => { const WelcomePage = (props) => {
@@ -39,7 +40,8 @@ const WelcomePage = (props) => {
const [ready, setReady] = useState(false); const [ready, setReady] = useState(false);
const [registrationResult, setRegistrationResult] = useState({ redirectUrl: '' }); const [registrationResult, setRegistrationResult] = useState({ redirectUrl: '' });
const [values, setValues] = useState({ levelOfEducation: '', yearOfBirth: '', gender: '' }); const [values, setValues] = useState({ levelOfEducation: '', yearOfBirth: '', gender: '', reason: '' });
const [openCareerDialog, setOpenCareerDialog] = useState(false);
const [openDialog, setOpenDialog] = useState(false); const [openDialog, setOpenDialog] = useState(false);
const DASHBOARD_URL = getConfig().LMS_BASE_URL.concat(DEFAULT_REDIRECT_URL); const DASHBOARD_URL = getConfig().LMS_BASE_URL.concat(DEFAULT_REDIRECT_URL);
@@ -83,6 +85,11 @@ const WelcomePage = (props) => {
{intl.formatMessage(messages[`gender.options.${key || 'label'}`])} {intl.formatMessage(messages[`gender.options.${key || 'label'}`])}
</option> </option>
)), )),
reason: REGISTRATION_REASONS.map(key => (
<option className="data-hj-suppress" key={key} value={key}>
{intl.formatMessage(messages[`reason.options.${key || 'label'}`])}
</option>
)),
}; };
return options[fieldName]; return options[fieldName];
@@ -99,11 +106,19 @@ const WelcomePage = (props) => {
} }
}); });
props.saveUserProfile(authenticatedUser.username, snakeCaseObject(payload)); if (!openCareerDialog) {
window.optimizely.push({ if (values.reason === 'job') {
type: 'event', setOpenCareerDialog(true);
eventName: 'authn_welcome_page_submit_btn_clicked', } else {
}); props.saveUserProfile(authenticatedUser.username, snakeCaseObject(payload));
window.optimizely.push({
type: 'event',
eventName: 'authn_welcome_page_submit_btn_clicked',
});
}
} else {
props.saveUserProfile(authenticatedUser.username, snakeCaseObject(payload));
}
}; };
const handleSkip = (e) => { const handleSkip = (e) => {
@@ -122,7 +137,7 @@ const WelcomePage = (props) => {
return ( return (
<> <>
<BaseComponent> <BaseComponent toggleWelcomeText={openCareerDialog}>
<Helmet> <Helmet>
<title>{intl.formatMessage(messages['progressive.profiling.page.title'], <title>{intl.formatMessage(messages['progressive.profiling.page.title'],
{ siteName: getConfig().SITE_NAME })} { siteName: getConfig().SITE_NAME })}
@@ -137,7 +152,13 @@ const WelcomePage = (props) => {
) : null} ) : null}
<div className="mw-xs welcome-page-content"> <div className="mw-xs welcome-page-content">
<div className="welcome-page-heading"> <div className="welcome-page-heading">
<h2 className="h3 text-primary">{intl.formatMessage(messages['progressive.profiling.page.heading'])}</h2> { !openCareerDialog ? (
<h2 className="h3 text-primary">
{intl.formatMessage(messages['progressive.profiling.page.heading'])}
</h2>
) : (
<h2 className="h3 text-primary">Advance your career by signing up with one of our partners. </h2>
) }
</div> </div>
<hr className="border-light-700 mb-4" /> <hr className="border-light-700 mb-4" />
{showError ? ( {showError ? (
@@ -146,80 +167,94 @@ const WelcomePage = (props) => {
<p>{intl.formatMessage(messages['welcome.page.error.message'])}</p> <p>{intl.formatMessage(messages['welcome.page.error.message'])}</p>
</Alert> </Alert>
) : null} ) : null}
<Form> { !openCareerDialog ? (
<Form.Group controlId="levelOfEducation"> <Form>
<Form.Control <Form.Group controlId="levelOfEducation">
as="select" <Form.Control
name="levelOfEducation" as="select"
value={values.levelOfEducation} name="levelOfEducation"
onChange={(e) => onChangeHandler(e)} value={values.levelOfEducation}
trailingElement={<Icon src={ExpandMore} />} onChange={(e) => onChangeHandler(e)}
floatingLabel={intl.formatMessage(messages['education.levels.label'])} trailingElement={<Icon src={ExpandMore}/>}
> floatingLabel={intl.formatMessage(messages['education.levels.label'])}
{getOptions('levelOfEducation')} >
</Form.Control> {getOptions('levelOfEducation')}
</Form.Group> </Form.Control>
<Form.Group controlId="yearOfBirth"> </Form.Group>
<Form.Control <Form.Group controlId="yearOfBirth">
as="select" <Form.Control
name="yearOfBirth" as="select"
value={values.yearOfBirth} name="yearOfBirth"
onChange={(e) => onChangeHandler(e)} value={values.yearOfBirth}
trailingElement={<Icon src={ExpandMore} />} onChange={(e) => onChangeHandler(e)}
floatingLabel={intl.formatMessage(messages['year.of.birth.label'])} trailingElement={<Icon src={ExpandMore}/>}
> floatingLabel={intl.formatMessage(messages['year.of.birth.label'])}
<option value="">{intl.formatMessage(messages['year.of.birth.label'])}</option> >
{getOptions('yearOfBirth')} <option value="">{intl.formatMessage(messages['year.of.birth.label'])}</option>
</Form.Control> {getOptions('yearOfBirth')}
</Form.Group> </Form.Control>
<Form.Group controlId="gender" className="mb-3"> </Form.Group>
<Form.Control <Form.Group controlId="gender" className="mb-3">
as="select" <Form.Control
name="gender" as="select"
value={values.gender} name="gender"
onChange={(e) => onChangeHandler(e)} value={values.gender}
trailingElement={<Icon src={ExpandMore} />} onChange={(e) => onChangeHandler(e)}
floatingLabel={intl.formatMessage(messages['gender.options.label'])} trailingElement={<Icon src={ExpandMore}/>}
> floatingLabel={intl.formatMessage(messages['gender.options.label'])}
{getOptions('gender')} >
</Form.Control> {getOptions('gender')}
</Form.Group> </Form.Control>
<span className="progressive-profiling-support"> </Form.Group>
<Hyperlink <Form.Group controlId="purposeOfAccountCreation" className="mb-3">
isInline <Form.Control
variant="muted" as="select"
destination={getConfig().WELCOME_PAGE_SUPPORT_LINK} name="reason"
target="_blank" value={values.reason}
showLaunchIcon={false} onChange={(e) => onChangeHandler(e)}
> trailingElement={<Icon src={ExpandMore}/>}
{intl.formatMessage(messages['optional.fields.information.link'])} floatingLabel={intl.formatMessage(messages['reason.options.label'])}
</Hyperlink> >
</span> {getOptions('reason')}
<div className="d-flex mt-4"> </Form.Control>
<StatefulButton </Form.Group>
type="submit" <span className="progressive-profiling-support">
variant="brand" <Hyperlink
className="login-button-width" isInline
state={submitState} variant="muted"
labels={{ destination={getConfig().WELCOME_PAGE_SUPPORT_LINK}
default: intl.formatMessage(messages['optional.fields.submit.button']), target="_blank"
pending: '', showLaunchIcon={false}
}} >
onClick={handleSubmit} {intl.formatMessage(messages['optional.fields.information.link'])}
onMouseDown={(e) => e.preventDefault()} </Hyperlink>
/> </span>
<StatefulButton <div className="d-flex mt-4">
className="text-gray-700 font-weight-500" <StatefulButton
type="submit" type="submit"
variant="link" variant="brand"
labels={{ className="login-button-width"
default: intl.formatMessage(messages['optional.fields.skip.button']), state={submitState}
}} labels={{
onClick={handleSkip} default: intl.formatMessage(messages['optional.fields.submit.button']),
onMouseDown={(e) => e.preventDefault()} pending: '',
/> }}
</div> onClick={handleSubmit}
</Form> onMouseDown={(e) => e.preventDefault()}
/>
<StatefulButton
className="text-gray-700 font-weight-500"
type="submit"
variant="link"
labels={{
default: intl.formatMessage(messages['optional.fields.skip.button']),
}}
onClick={handleSkip}
onMouseDown={(e) => e.preventDefault()}
/>
</div>
</Form>
) : <PartnerWelcome onComplete={handleSubmit} /> }
</div> </div>
</BaseComponent> </BaseComponent>
</> </>

View File

@@ -31,6 +31,26 @@ const messages = defineMessages({
defaultMessage: 'Other/Prefer not to say', defaultMessage: 'Other/Prefer not to say',
description: 'The label for catch-all gender option.', description: 'The label for catch-all gender option.',
}, },
'reason.options.label': {
id: 'reason.options.label',
defaultMessage: 'Purpose (optional)',
description: 'Placeholder for the reasons options dropdown',
},
'reason.options.job': {
id: 'reason.options.job',
defaultMessage: 'Finding a job',
description: 'edX grants unlimited opportunities to expand and grow one\' career',
},
'reason.options.learn': {
id: 'reason.options.learn',
defaultMessage: 'Learning tons of shit',
description: 'edX ever increasing catalog of a wide array of courses allows one to explore new ares of knowledge and challenge their perception of the world.',
},
'reason.options.boss': {
id: 'reason.options.boss',
defaultMessage: 'My boss made me',
description: 'edX allows businesses and institutions to empower their employees on a mass scale, offering opportunities to learn to countless learners.',
},
'education.levels.label': { 'education.levels.label': {
id: 'education.levels.label', id: 'education.levels.label',
defaultMessage: 'Highest level of education completed (optional)', defaultMessage: 'Highest level of education completed (optional)',