Skip to content

Commit

Permalink
feat(Form input validation): Begin make basic validations.
Browse files Browse the repository at this point in the history
  • Loading branch information
binh-dam-ibigroup committed Sep 25, 2020
1 parent 36cc529 commit dc63ad5
Show file tree
Hide file tree
Showing 7 changed files with 376 additions and 268 deletions.
9 changes: 6 additions & 3 deletions lib/components/user/existing-account-display.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,34 @@ import StackedPaneDisplay from './stacked-pane-display'
*/
class ExistingAccountDisplay extends Component {
render () {
const { onCancel, onComplete, panes } = this.props
const props = this.props
const { handleSubmit, onCancel, panes } = props
const paneSequence = [
{
pane: () => <p><LinkButton to='/savedtrips'>Edit my trips</LinkButton></p>,
title: 'My trips'
},
{
pane: panes.terms,
props: { disableCheckTerms: true },
props: { disableCheckTerms: true, ...props },
title: 'Terms'
},
{
pane: panes.notifications,
props,
title: 'Notifications'
},
{
pane: panes.locations,
props,
title: 'My locations'
}
]

return (
<StackedPaneDisplay
onCancel={onCancel}
onComplete={onComplete}
onComplete={handleSubmit}
paneSequence={paneSequence}
title='My Account'
/>
Expand Down
11 changes: 9 additions & 2 deletions lib/components/user/new-account-wizard.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import SequentialPaneDisplay from './sequential-pane-display'
/**
* This component is the new account wizard.
*/
const NewAccountWizard = ({ onComplete, panes, userData }) => {
const NewAccountWizard = props => {
const { handleSubmit, panes, values: userData } = props

const {
hasConsentedToTerms,
notificationChannel = 'email'
Expand All @@ -16,38 +18,43 @@ const NewAccountWizard = ({ onComplete, panes, userData }) => {
disableNext: !hasConsentedToTerms,
nextId: 'notifications',
pane: panes.terms,
props,
title: 'Create a new account'
},
notifications: {
nextId: notificationChannel === 'sms' ? 'verifyPhone' : 'places',
pane: panes.notifications,
prevId: 'terms',
props,
title: 'Notification preferences'
},
verifyPhone: {
disableNext: true, // TODO: implement verification.
nextId: 'places',
pane: panes.verifyPhone,
prevId: 'notifications',
props,
title: 'Verify your phone'
},
places: {
nextId: 'finish',
pane: panes.locations,
prevId: 'notifications',
props,
title: 'Add your locations'
},
finish: {
pane: panes.finish,
prevId: 'places',
props,
title: 'Account setup complete!'
}
}

return (
<SequentialPaneDisplay
initialPaneId='terms'
onComplete={onComplete}
onComplete={handleSubmit}
paneSequence={paneSequence}
/>
)
Expand Down
148 changes: 82 additions & 66 deletions lib/components/user/notification-prefs-pane.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { ButtonToolbar, ControlLabel, FormControl, FormGroup, ToggleButton, ToggleButtonGroup } from 'react-bootstrap'
import React from 'react'
import {
ButtonToolbar,
ControlLabel,
FormControl,
FormGroup,
HelpBlock,
ToggleButton,
ToggleButtonGroup
} from 'react-bootstrap'
import styled from 'styled-components'

const allowedNotificationChannels = [
Expand All @@ -27,74 +35,82 @@ const Details = styled.div`
/**
* User notification preferences pane.
*/
class NotificationPrefsPane extends Component {
static propTypes = {
onUserDataChange: PropTypes.func.isRequired,
userData: PropTypes.object.isRequired
}

_handleNotificationChannelChange = e => {
const { onUserDataChange } = this.props
onUserDataChange({ notificationChannel: e })
}
const NotificationPrefsPane = ({
errors,
handleBlur,
handleChange,
touched,
values: userData
}) => {
const {
email,
notificationChannel,
phoneNumber
} = userData

_handlePhoneNumberChange = e => {
const { onUserDataChange } = this.props
onUserDataChange({ phoneNumber: e.target.value })
let phoneValidationState = null
if (touched.phoneNumber && phoneNumber.length > 0) {
phoneValidationState = errors.phoneNumber ? 'error' : 'success'
}

render () {
const { userData } = this.props
const {
email,
notificationChannel,
phoneNumber
} = userData

return (
<div>
<p>
return (
<div>
<p>
You can receive notifications about trips you frequently take.
</p>
<FormGroup>
<ControlLabel>How would you like to receive notifications?</ControlLabel>
<ButtonToolbar>
<ToggleButtonGroup
name='notificationChannels'
onChange={this._handleNotificationChannelChange}
type='radio'
value={notificationChannel}
>
{allowedNotificationChannels.map(({ type, text }, index) => (
<ToggleButton
bsStyle={notificationChannel === type ? 'primary' : 'default'}
key={index}
value={type}
>
{text}
</ToggleButton>
))}
</ToggleButtonGroup>
</ButtonToolbar>
</FormGroup>
<Details>
{notificationChannel === 'email' && (
<FormGroup>
<ControlLabel>Notification emails will be sent out to:</ControlLabel>
<FormControl disabled type='text' value={email} />
</FormGroup>
)}
{notificationChannel === 'sms' && (
<FormGroup>
<ControlLabel>Enter your phone number for SMS notifications:</ControlLabel>
{/* TODO: Add field validation. */}
<FormControl onChange={this._handlePhoneNumberChange} type='tel' value={phoneNumber} />
</FormGroup>
)}
</Details>
</div>
)
}
</p>
<FormGroup>
<ControlLabel>How would you like to receive notifications?</ControlLabel>
<ButtonToolbar>
<ToggleButtonGroup
name='notificationChannel'
type='radio'
defaultValue={notificationChannel}
>
{allowedNotificationChannels.map(({ type, text }, index) => (
<ToggleButton
bsStyle={notificationChannel === type ? 'primary' : 'default'}
key={index}
onBlur={handleBlur}
onChange={handleChange}
value={type}
>
{text}
</ToggleButton>
))}
</ToggleButtonGroup>
</ButtonToolbar>
</FormGroup>
<Details>
{notificationChannel === 'email' && (
<FormGroup>
<ControlLabel>Notification emails will be sent out to:</ControlLabel>
<FormControl disabled type='text' value={email} />
</FormGroup>
)}
{notificationChannel === 'sms' && (
// FIXME: Merge the validation feedback upon approving PR #224.
<FormGroup validationState={phoneValidationState}>
<ControlLabel>Enter your phone number for SMS notifications:</ControlLabel>
<FormControl
name='phoneNumber'
onBlur={handleBlur}
onChange={handleChange}
type='tel'
value={phoneNumber}
/>
<FormControl.Feedback />
{errors.phoneNumber && <HelpBlock>{errors.phoneNumber}</HelpBlock>}
</FormGroup>
)}
</Details>
</div>
)
}

NotificationPrefsPane.propTypes = {
handleBlur: PropTypes.func.isRequired,
handleChange: PropTypes.func.isRequired,
values: PropTypes.object.isRequired
}

export default NotificationPrefsPane
101 changes: 51 additions & 50 deletions lib/components/user/terms-of-use-pane.js
Original file line number Diff line number Diff line change
@@ -1,62 +1,63 @@
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import React from 'react'
import { Checkbox, ControlLabel, FormGroup } from 'react-bootstrap'

/**
* User terms of use pane.
*/
class TermsOfUsePane extends Component {
static propTypes = {
disableCheckTerms: PropTypes.bool,
onUserDataChange: PropTypes.func.isRequired,
userData: PropTypes.object.isRequired
}

_handleCheckHistoryChange = e => {
const { onUserDataChange } = this.props
onUserDataChange({ storeTripHistory: e.target.checked })
}

_handleCheckTermsChange = e => {
const { onUserDataChange } = this.props
onUserDataChange({ hasConsentedToTerms: e.target.checked })
}

render () {
const { disableCheckTerms, userData } = this.props
const {
hasConsentedToTerms,
storeTripHistory
} = userData

return (
<div>
<ControlLabel>You must agree to the terms of service to continue.</ControlLabel>

<FormGroup>
<Checkbox
checked={hasConsentedToTerms}
disabled={disableCheckTerms}
onChange={disableCheckTerms ? null : this._handleCheckTermsChange}
>
{/* TODO: Implement the link */}
const TermsOfUsePane = ({
disableCheckTerms,
handleBlur,
handleChange,
values: userData
}) => {
const {
hasConsentedToTerms,
storeTripHistory
} = userData

return (
<div>
<ControlLabel>You must agree to the terms of service to continue.</ControlLabel>

<FormGroup>
<Checkbox
checked={hasConsentedToTerms}
disabled={disableCheckTerms}
name='hasConsentedToTerms'
onBlur={disableCheckTerms ? null : handleBlur}
onChange={disableCheckTerms ? null : handleChange}
>
{/* TODO: Implement the link */}
I have read and consent to the <a href='/#/terms-of-service'>Terms of Service</a> for using the Trip Planner.
</Checkbox>
</FormGroup>

<FormGroup>
<Checkbox
checked={storeTripHistory}
onChange={this._handleCheckHistoryChange}
>
{/* TODO: Implement the link */}
</Checkbox>
</FormGroup>

<FormGroup>
<Checkbox
checked={storeTripHistory}
name='storeTripHistory'
onBlur={handleBlur}
onChange={handleChange}
>
{/* TODO: Implement the link */}
Optional: I consent to the Trip Planner storing my historical planned trips in order to
improve transit services in my area. <a href='/#/terms-of-storage'>More info...</a>
</Checkbox>
</FormGroup>
</div>
)
}
</Checkbox>
</FormGroup>
</div>
)
}

TermsOfUsePane.propTypes = {
disableCheckTerms: PropTypes.bool,
handleBlur: PropTypes.func.isRequired,
handleChange: PropTypes.func.isRequired,
values: PropTypes.object.isRequired
}

TermsOfUsePane.defaultProps = {
disableCheckTerms: false
}

export default TermsOfUsePane
Loading

0 comments on commit dc63ad5

Please sign in to comment.