mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-26 17:16:11 -05:00
Merge pull request #3144 from benjiwheeler/join-flow-add-birth-date-step
Join flow add birth date step
This commit is contained in:
commit
4ae69e1b49
7 changed files with 181 additions and 9 deletions
|
@ -24,10 +24,9 @@ const FormikSelect = ({
|
||||||
</option>
|
</option>
|
||||||
));
|
));
|
||||||
return (
|
return (
|
||||||
<div className="col-sm-9 row">
|
<div className="select">
|
||||||
<Field
|
<Field
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'select',
|
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
component="select"
|
component="select"
|
||||||
|
|
143
src/components/join-flow/birthdate-step.jsx
Normal file
143
src/components/join-flow/birthdate-step.jsx
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
const bindAll = require('lodash.bindall');
|
||||||
|
const classNames = require('classnames');
|
||||||
|
const React = require('react');
|
||||||
|
const PropTypes = require('prop-types');
|
||||||
|
import {Formik} from 'formik';
|
||||||
|
const {injectIntl, intlShape} = require('react-intl');
|
||||||
|
|
||||||
|
const FormikSelect = require('../../components/formik-forms/formik-select.jsx');
|
||||||
|
const JoinFlowStep = require('./join-flow-step.jsx');
|
||||||
|
|
||||||
|
require('./join-flow-steps.scss');
|
||||||
|
|
||||||
|
const getBirthMonthOptions = intl => ([
|
||||||
|
{value: 'null', label: intl.formatMessage({id: 'general.month'})},
|
||||||
|
{value: '1', label: intl.formatMessage({id: 'general.monthJanuary'})},
|
||||||
|
{value: '2', label: intl.formatMessage({id: 'general.monthFebruary'})},
|
||||||
|
{value: '3', label: intl.formatMessage({id: 'general.monthMarch'})},
|
||||||
|
{value: '4', label: intl.formatMessage({id: 'general.monthApril'})},
|
||||||
|
{value: '5', label: intl.formatMessage({id: 'general.monthMay'})},
|
||||||
|
{value: '6', label: intl.formatMessage({id: 'general.monthJune'})},
|
||||||
|
{value: '7', label: intl.formatMessage({id: 'general.monthJuly'})},
|
||||||
|
{value: '8', label: intl.formatMessage({id: 'general.monthAugust'})},
|
||||||
|
{value: '9', label: intl.formatMessage({id: 'general.monthSeptember'})},
|
||||||
|
{value: '10', label: intl.formatMessage({id: 'general.monthOctober'})},
|
||||||
|
{value: '11', label: intl.formatMessage({id: 'general.monthNovember'})},
|
||||||
|
{value: '12', label: intl.formatMessage({id: 'general.monthDecember'})}
|
||||||
|
]);
|
||||||
|
|
||||||
|
const getBirthYearOptions = intl => {
|
||||||
|
const curYearRaw = (new Date()).getYear();
|
||||||
|
const curYear = curYearRaw + 1900;
|
||||||
|
// including both 1900 and current year, there are (curYearRaw + 1) options.
|
||||||
|
const numYearOptions = curYearRaw + 1;
|
||||||
|
const birthYearOptions = Array(numYearOptions).fill()
|
||||||
|
.map((defaultVal, i) => (
|
||||||
|
{value: String(curYear - i), label: String(curYear - i)}
|
||||||
|
));
|
||||||
|
birthYearOptions.unshift({
|
||||||
|
value: 'null',
|
||||||
|
label: intl.formatMessage({id: 'general.year'})
|
||||||
|
});
|
||||||
|
return birthYearOptions;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BirthDateStep extends React.Component {
|
||||||
|
constructor (props) {
|
||||||
|
super(props);
|
||||||
|
bindAll(this, [
|
||||||
|
'handleValidSubmit',
|
||||||
|
'validateForm',
|
||||||
|
'validateSelect'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
validateSelect (selection) {
|
||||||
|
if (selection === 'null') {
|
||||||
|
return this.props.intl.formatMessage({id: 'form.validationRequired'});
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
validateForm () {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
handleValidSubmit (formData, formikBag) {
|
||||||
|
formikBag.setSubmitting(false);
|
||||||
|
this.props.onNextStep(formData);
|
||||||
|
}
|
||||||
|
render () {
|
||||||
|
const birthMonthOptions = getBirthMonthOptions(this.props.intl);
|
||||||
|
const birthYearOptions = getBirthYearOptions(this.props.intl);
|
||||||
|
return (
|
||||||
|
<Formik
|
||||||
|
initialValues={{
|
||||||
|
birth_month: 'null',
|
||||||
|
birth_year: 'null'
|
||||||
|
}}
|
||||||
|
validate={this.validateForm}
|
||||||
|
validateOnBlur={false}
|
||||||
|
validateOnChange={false}
|
||||||
|
onSubmit={this.handleValidSubmit}
|
||||||
|
>
|
||||||
|
{props => {
|
||||||
|
const {
|
||||||
|
errors,
|
||||||
|
handleSubmit,
|
||||||
|
isSubmitting
|
||||||
|
} = props;
|
||||||
|
return (
|
||||||
|
<JoinFlowStep
|
||||||
|
description={this.props.intl.formatMessage({id: 'registration.birthDateStepDescription'})}
|
||||||
|
headerImgSrc="/images/hoc/getting-started.jpg"
|
||||||
|
title={this.props.intl.formatMessage({id: 'general.joinScratch'})}
|
||||||
|
waiting={isSubmitting}
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
'col-sm-9',
|
||||||
|
'row',
|
||||||
|
'birthdate-select-row'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<FormikSelect
|
||||||
|
className={classNames(
|
||||||
|
'join-flow-select',
|
||||||
|
'join-flow-select-month',
|
||||||
|
{fail: errors.birth_month}
|
||||||
|
)}
|
||||||
|
error={errors.birth_month}
|
||||||
|
id="birth_month"
|
||||||
|
name="birth_month"
|
||||||
|
options={birthMonthOptions}
|
||||||
|
validate={this.validateSelect}
|
||||||
|
validationClassName="validation-full-width-input"
|
||||||
|
/>
|
||||||
|
<FormikSelect
|
||||||
|
className={classNames(
|
||||||
|
'join-flow-select',
|
||||||
|
{fail: errors.birth_year}
|
||||||
|
)}
|
||||||
|
error={errors.birth_year}
|
||||||
|
id="birth_year"
|
||||||
|
name="birth_year"
|
||||||
|
options={birthYearOptions}
|
||||||
|
validate={this.validateSelect}
|
||||||
|
validationClassName="validation-full-width-input"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</JoinFlowStep>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Formik>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BirthDateStep.propTypes = {
|
||||||
|
intl: intlShape,
|
||||||
|
onNextStep: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
const IntlBirthDateStep = injectIntl(BirthDateStep);
|
||||||
|
|
||||||
|
module.exports = IntlBirthDateStep;
|
|
@ -10,11 +10,17 @@ require('./join-flow-step.scss');
|
||||||
const JoinFlowStep = ({
|
const JoinFlowStep = ({
|
||||||
children,
|
children,
|
||||||
description,
|
description,
|
||||||
|
headerImgSrc,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
title,
|
title,
|
||||||
waiting
|
waiting
|
||||||
}) => (
|
}) => (
|
||||||
<form onSubmit={onSubmit}>
|
<form onSubmit={onSubmit}>
|
||||||
|
{headerImgSrc && (
|
||||||
|
<div className="join-flow-header-image">
|
||||||
|
<img src={headerImgSrc} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div>
|
<div>
|
||||||
<ModalInnerContent className="join-flow-inner-content">
|
<ModalInnerContent className="join-flow-inner-content">
|
||||||
{title && (
|
{title && (
|
||||||
|
@ -38,6 +44,7 @@ const JoinFlowStep = ({
|
||||||
JoinFlowStep.propTypes = {
|
JoinFlowStep.propTypes = {
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
description: PropTypes.string,
|
description: PropTypes.string,
|
||||||
|
headerImgSrc: PropTypes.string,
|
||||||
onSubmit: PropTypes.func,
|
onSubmit: PropTypes.func,
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
waiting: PropTypes.bool
|
waiting: PropTypes.bool
|
||||||
|
|
|
@ -21,3 +21,13 @@
|
||||||
padding: 2.3125rem 0 2.5rem;
|
padding: 2.3125rem 0 2.5rem;
|
||||||
font-size: .875rem;
|
font-size: .875rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* overflow will only work if this class is set on parent of img, not img itself */
|
||||||
|
.join-flow-header-image {
|
||||||
|
width: 100%;
|
||||||
|
height: 7.5rem;
|
||||||
|
overflow: hidden;
|
||||||
|
margin: 0;
|
||||||
|
border-top-left-radius: 1rem;
|
||||||
|
border-top-right-radius: 1rem;
|
||||||
|
}
|
||||||
|
|
|
@ -22,6 +22,19 @@
|
||||||
transform: translate(21.5625rem, 0);
|
transform: translate(21.5625rem, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
select.join-flow-select {
|
||||||
|
width: 9.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.join-flow-select-month {
|
||||||
|
margin-right: .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.join-flow-password-section {
|
.join-flow-password-section {
|
||||||
margin-top: 1.125rem;
|
margin-top: 1.125rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.birthdate-select-row {
|
||||||
|
display: flex;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
|
@ -7,7 +7,8 @@ const injectIntl = require('../../lib/intl.jsx').injectIntl;
|
||||||
const intlShape = require('../../lib/intl.jsx').intlShape;
|
const intlShape = require('../../lib/intl.jsx').intlShape;
|
||||||
|
|
||||||
const Progression = require('../progression/progression.jsx');
|
const Progression = require('../progression/progression.jsx');
|
||||||
const JoinFlowSteps = require('./join-flow-steps.jsx');
|
const UsernameStep = require('./username-step.jsx');
|
||||||
|
const BirthDateStep = require('./birthdate-step.jsx');
|
||||||
|
|
||||||
/*
|
/*
|
||||||
eslint-disable react/prefer-stateless-function, react/no-unused-prop-types, no-useless-constructor
|
eslint-disable react/prefer-stateless-function, react/no-unused-prop-types, no-useless-constructor
|
||||||
|
@ -35,9 +36,8 @@ class JoinFlow extends React.Component {
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Progression step={this.state.step}>
|
<Progression step={this.state.step}>
|
||||||
<JoinFlowSteps.UsernameStep
|
<UsernameStep onNextStep={this.handleAdvanceStep} />
|
||||||
onNextStep={this.handleAdvanceStep}
|
<BirthDateStep onNextStep={this.handleAdvanceStep} />
|
||||||
/>
|
|
||||||
</Progression>
|
</Progression>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
/* eslint-disable react/no-multi-comp */
|
|
||||||
const bindAll = require('lodash.bindall');
|
const bindAll = require('lodash.bindall');
|
||||||
const classNames = require('classnames');
|
const classNames = require('classnames');
|
||||||
const React = require('react');
|
const React = require('react');
|
||||||
|
@ -190,11 +189,12 @@ class UsernameStep extends React.Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* eslint-enable */
|
|
||||||
|
|
||||||
UsernameStep.propTypes = {
|
UsernameStep.propTypes = {
|
||||||
intl: intlShape,
|
intl: intlShape,
|
||||||
onNextStep: PropTypes.func
|
onNextStep: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.UsernameStep = injectIntl(UsernameStep);
|
const IntlUsernameStep = injectIntl(UsernameStep);
|
||||||
|
|
||||||
|
module.exports = IntlUsernameStep;
|
Loading…
Reference in a new issue