docbrown/app/javascript/onboarding/components/EmailListTermsConditionsForm.jsx
Ali Spittel 52c60ce37e Feature/refactored onboarding (#3333)
* set up refactored onboarding

* create onboarding page

* add in first slide and change slide functionality

* fix test suite

* profile refactor

* profile refactor

* refactor to api

* add checkbox fields

* add checkbox fields

* remove puts

* add basic css

* add styling

* add redirect

* hide back and next at first and last slides

* test refactored onboarding

* test refactored onboarding

* remove article edits

* Fix schema

* Add deleted file back in

* Add default value for checked_t&c column

* Adjust HTML structure to keep nav buttons in place

* Fix ESLint issues on Onboarding.jsx file

* Handling for undefined or empty followedTags on getUserTags

* Fix codeclimate issues

* Fix codeclimate issues

* Fix more codeclimate issues

* Fix more codeclimate issues

* Update Onboarding snapshots

* Uncheck the CoC and T&C checkboxes on render

* Update snapshots

* Return false instead of raising error

* Update spec to use new onboarding

* Redirect to onboarding if haven't seen it yet

* Prevent redirect to onboarding from /signout_confirm

* Use assign_attributes instead of saving twice

* Move COC and T&C checkbox page to second slide

* Add 'go back to original page' functionality

* Reuse ready prototype logic

* Keep track of the last visited onboarding page

* Fix email subscription bug

* Fix overflow issue for tags page

* Remove height to prevent page container scrolling

* Check for CoC and T&C for displaying onboarding

* Add InstantClick redirect and preserve referrer in client

* Fix async update + check by using localStorage

* Turn off onboarding for tests

* Finalize design for onboarding

* Finalize design for onboarding

* Make bulk follows during onboarding

* Fix bulk follow test
2019-07-26 15:53:32 -04:00

197 lines
5.5 KiB
JavaScript

import { h, Component } from 'preact';
import PropTypes from 'prop-types';
import Navigation from './Navigation';
import { getContentOfToken } from '../utilities';
class EmailTermsConditionsForm extends Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.checkRequirements = this.checkRequirements.bind(this);
this.state = {
checked_code_of_conduct: false,
checked_terms_and_conditions: false,
email_membership_newsletter: true,
email_digest_periodic: true,
message: '',
textShowing: null,
};
}
componentDidMount() {
const csrfToken = getContentOfToken('csrf-token');
fetch('/onboarding_update', {
method: 'PATCH',
headers: {
'X-CSRF-Token': csrfToken,
'Content-Type': 'application/json',
},
body: JSON.stringify({
user: { last_onboarding_page: 'emails, COC and T&C form' },
}),
credentials: 'same-origin',
});
}
onSubmit() {
if (!this.checkRequirements()) return;
const csrfToken = getContentOfToken('csrf-token');
fetch('/onboarding_checkbox_update', {
method: 'PATCH',
headers: {
'X-CSRF-Token': csrfToken,
'Content-Type': 'application/json',
},
body: JSON.stringify({ user: this.state }),
credentials: 'same-origin',
}).then(response => {
if (response.ok) {
localStorage.setItem('shouldRedirectToOnboarding', false);
const { next } = this.props;
next();
}
});
}
checkRequirements() {
const {
checked_code_of_conduct,
checked_terms_and_conditions,
} = this.state;
if (!checked_code_of_conduct) {
this.setState({
message: 'You must agree to our Code of Conduct before continuing!',
});
return;
}
if (!checked_terms_and_conditions) {
this.setState({
message:
'You must agree to our Terms and Conditions before continuing!',
});
return;
}
return true;
}
handleChange(event) {
const { name } = event.target;
this.setState(currentState => ({
[name]: !currentState[name],
}));
}
handleShowText(event, id) {
event.preventDefault();
this.setState({ textShowing: document.getElementById(id).innerHTML });
}
backToSlide() {
this.setState({ textShowing: null });
}
render() {
const {
message,
checked_code_of_conduct,
checked_terms_and_conditions,
email_membership_newsletter,
email_digest_periodic,
textShowing,
} = this.state;
const { prev } = this.props;
if (textShowing) {
return (
<div className="onboarding-main">
<div className="onboarding-content checkbox-slide">
<button onClick={() => this.backToSlide()}>BACK</button>
<div
dangerouslySetInnerHTML={{ __html: textShowing }}
style={{ height: '360px', overflow: 'scroll' }}
/>
</div>
</div>
);
}
return (
<div className="onboarding-main">
<div className="onboarding-content checkbox-slide">
<h2>Some things to check off!</h2>
{message && <span className="warning-message">{message}</span>}
<form>
<label htmlFor="checked_code_of_conduct">
<input
type="checkbox"
name="checked_code_of_conduct"
id="checked_code_of_conduct"
checked={checked_code_of_conduct}
onChange={this.handleChange}
/>
You agree to uphold our
{' '}
<a
href="/code-of-conduct"
data-no-instant
onClick={e => this.handleShowText(e, 'coc')}
>
Code of Conduct
</a>
</label>
<label htmlFor="checked_terms_and_conditions">
<input
type="checkbox"
id="checked_terms_and_conditions"
name="checked_terms_and_conditions"
checked={checked_terms_and_conditions}
onChange={this.handleChange}
/>
You agree to our
{' '}
<a
href="/terms"
data-no-instant
onClick={e => this.handleShowText(e, 'terms')}
>
Terms and Conditions
</a>
</label>
<h3>Email Preferences</h3>
<label htmlFor="email_membership_newsletter">
<input
type="checkbox"
name="email_membership_newsletter"
checked={email_membership_newsletter}
onChange={this.handleChange}
/>
Do you want to receive our weekly newsletter emails?
</label>
<label htmlFor="email_digest_periodic">
<input
type="checkbox"
name="email_digest_periodic"
checked={email_digest_periodic}
onChange={this.handleChange}
/>
Do you want to receive a periodic digest with some of the top
posts from your tags?
</label>
</form>
</div>
<Navigation prev={prev} next={this.onSubmit} />
</div>
);
}
}
EmailTermsConditionsForm.propTypes = {
prev: PropTypes.func.isRequired,
next: PropTypes.string.isRequired,
};
export default EmailTermsConditionsForm;