docbrown/app/javascript/onboarding/components/IntroSlide.jsx
Ridhwana 7a9629172d
Profile generalization for the onboarding workflow (#11629)
* feat: v1 of the profile form

* feat: fix inputs and create a handleChange event

* feat: update the submit values to represent values from the form

* feat: ensure that errors and success is handled on send

* refactor: remove unused code

* feat: replace the old profile form with a new one

* fix: use the renames file

* refactor: safety net for groups

* chore: fix code climate issue

* tests: amend + add tests

* test: fix broken spec

* feat: update the setup for the test

* tests: refactored them to move the fake response into the before all

* feat: clunky way to quickly cater for color field since it was a quick and easy implementation

* feat: add a field.description to the color field

* refactor: pull some duplicate code into a new function

* chore: cater for a textarea field

* overflow issue

* refactor: use FormField instead of manual divs

* Update spec/requests/users_onboarding_spec.rb

Co-authored-by: Vaidehi Joshi <vaidehi.sj@gmail.com>

* Update spec/requests/users_onboarding_spec.rb

Co-authored-by: Vaidehi Joshi <vaidehi.sj@gmail.com>

* refactor: move out of method and into a constant

* refactor: user_onboarding_update to be more readable

* refactor: use current.save instead of declaring a new variable

* refactor: remove explicit check for bookean

* refactor: use request from '@utilities/http' instead :)

* refactor: no need for if with destructured groups

* refactor: move color field to its own component

* chore: remove colorfield now thats its a component

* fix: forgot about field

* feat: a text area component

* chore: remove textField function in favor of component

* refactor: checkbox refactor

* refactor: add a switch statement

* chore: move into a more organized folder

* fix: move the handler to props and off from field

* fix: add a conditional so we dont hit an error undefined method `success?' for nil:NilClass

* refactor: change from component to function

* feat: add a key attribute

* refactor: add role for readers

* refactor: remove unnecessary guard clauses

* refactor: use function instead of an arrow

* chore: document components

* test

* padding

* fixes

* test: fix the tests by using more general matchers

Co-authored-by: Paweł Ludwiczak <ludwiczakpawel@gmail.com>
Co-authored-by: Vaidehi Joshi <vaidehi.sj@gmail.com>
2020-12-08 19:53:00 +02:00

216 lines
6.4 KiB
JavaScript

import { h, Component } from 'preact';
import PropTypes from 'prop-types';
import { getContentOfToken, userData, updateOnboarding } from '../utilities';
import Navigation from './Navigation';
/* eslint-disable camelcase */
class IntroSlide extends Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.user = userData();
this.state = {
checked_code_of_conduct: false,
checked_terms_and_conditions: false,
text: null,
};
}
componentDidMount() {
updateOnboarding('v2: intro, code of conduct, terms & conditions');
}
onSubmit() {
const { next } = this.props;
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);
next();
}
});
}
handleChange(event) {
const { name } = event.target;
this.setState((currentState) => ({
[name]: !currentState[name],
}));
}
handleShowText(event, id) {
event.preventDefault();
this.setState({ text: document.getElementById(id).innerHTML });
}
isButtonDisabled() {
const {
checked_code_of_conduct,
checked_terms_and_conditions,
} = this.state;
return !checked_code_of_conduct || !checked_terms_and_conditions;
}
render() {
const {
slidesCount,
currentSlideIndex,
prev,
communityConfig,
} = this.props;
const {
checked_code_of_conduct,
checked_terms_and_conditions,
text,
} = this.state;
if (text) {
return (
<div className="onboarding-main crayons-modal crayons-modal--m">
<div className="crayons-modal__box overflow-auto">
<div className="onboarding-content terms-and-conditions-wrapper">
<button
type="button"
onClick={() => this.setState({ text: null })}
>
Back
</button>
<div
className="terms-and-conditions-content"
/* eslint-disable react/no-danger */
dangerouslySetInnerHTML={{ __html: text }}
/* eslint-enable react/no-danger */
/>
</div>
</div>
</div>
);
}
return (
<div
data-testid="onboarding-intro-slide"
className="onboarding-main introduction crayons-modal crayons-modal--m"
>
<div className="crayons-modal__box overflow-auto">
<div className="onboarding-content">
<figure>
<img
src={communityConfig.communityLogo}
className="sticker-logo"
alt={communityConfig.communityName}
/>
</figure>
<h1
data-testid="onboarding-introduction-title"
className="introduction-title"
>
{this.user.name}
&mdash; welcome to {communityConfig.communityName}!
</h1>
<h2 className="introduction-subtitle">
{communityConfig.communityDescription}
</h2>
</div>
<div className="checkbox-form-wrapper">
<form className="checkbox-form">
<fieldset>
<ul>
<li className="checkbox-item">
<label
data-testid="checked-code-of-conduct"
htmlFor="checked_code_of_conduct"
className="lh-base py-1"
>
<input
type="checkbox"
id="checked_code_of_conduct"
name="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>
</li>
<li className="checkbox-item">
<label
data-testid="checked-terms-and-conditions"
htmlFor="checked_terms_and_conditions"
className="lh-base py-1"
>
<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>
</li>
</ul>
</fieldset>
</form>
<Navigation
disabled={this.isButtonDisabled()}
className="intro-slide"
prev={prev}
slidesCount={slidesCount}
currentSlideIndex={currentSlideIndex}
next={this.onSubmit}
hidePrev
/>
</div>
</div>
</div>
);
}
}
IntroSlide.propTypes = {
prev: PropTypes.func.isRequired,
next: PropTypes.func.isRequired,
slidesCount: PropTypes.number.isRequired,
currentSlideIndex: PropTypes.func.isRequired,
communityConfig: PropTypes.shape({
communityLogo: PropTypes.string.isRequired,
communityName: PropTypes.string.isRequired,
communityDescription: PropTypes.string.isRequired,
}).isRequired,
};
export default IntroSlide;
/* eslint-enable camelcase */