Form refactoring (#142)

This commit is contained in:
Riccardo Graziosi
2022-07-22 16:50:36 +02:00
committed by GitHub
parent d078e659c6
commit 9592ac3d1d
22 changed files with 557 additions and 1060 deletions

View File

@@ -1,4 +1,5 @@
import * as React from 'react';
import { useForm, SubmitHandler } from 'react-hook-form';
import I18n from 'i18n-js';
import Button from '../../common/Button';
@@ -10,7 +11,7 @@ interface Props {
name?: string;
description?: string;
handleSubmit?(
handleCreate?(
name: string,
description: string,
onSuccess: Function,
@@ -22,101 +23,75 @@ interface Props {
): void;
}
interface State {
interface IBoardForm {
name: string;
description: string;
}
class BoardForm extends React.Component<Props, State> {
initialState: State = {
name: '',
description: '',
};
const BoardForm = ({
mode,
id,
name,
description,
handleCreate,
handleUpdate,
}: Props) => {
const {
register,
handleSubmit,
reset,
formState: { isValid },
} = useForm<IBoardForm>({
mode: 'onChange',
defaultValues: {
name: name || '',
description: description || '',
},
});
constructor(props: Props) {
super(props);
this.state = this.props.mode === 'create' ?
this.initialState
:
{
name: this.props.name,
description: this.props.description,
};
this.onSubmit = this.onSubmit.bind(this);
}
isFormValid() {
return this.state.name && this.state.name.length > 0;
}
onNameChange(nameText: string) {
this.setState({
name: nameText,
});
}
onDescriptionChange(descriptionText: string) {
this.setState({
description: descriptionText,
});
}
onSubmit() {
if (this.props.mode === 'create') {
this.props.handleSubmit(
this.state.name,
this.state.description,
() => this.setState({...this.initialState}),
const onSubmit: SubmitHandler<IBoardForm> = data => {
if (mode === 'create') {
handleCreate(
data.name,
data.description,
() => reset({ name: '', description: '' })
);
} else {
this.props.handleUpdate(this.props.id, this.state.name, this.state.description);
handleUpdate(id, data.name, data.description);
}
}
render() {
const {mode} = this.props;
const {name, description} = this.state;
return (
<form className="boardForm">
<div className="boardMandatoryForm">
<input
type="text"
placeholder={I18n.t('site_settings.boards.form.name')}
value={name}
onChange={e => this.onNameChange(e.target.value)}
autoFocus
className="form-control"
/>
<Button
onClick={e => {
e.preventDefault();
this.onSubmit();
}}
className="newBoardButton"
disabled={!this.isFormValid()}
>
{
mode === 'create' ?
I18n.t('common.buttons.create')
:
I18n.t('common.buttons.update')
}
</Button>
</div>
<textarea
placeholder={I18n.t('site_settings.boards.form.description')}
value={description}
onChange={e => this.onDescriptionChange(e.target.value)}
className="form-control"
return (
<form onSubmit={handleSubmit(onSubmit)} className="boardForm">
<div className="boardMandatoryForm">
<input
{...register('name', { required: true })}
placeholder={I18n.t('site_settings.boards.form.name')}
autoFocus
className="formControl"
/>
</form>
);
}
<Button
onClick={() => null}
className="newBoardButton"
disabled={!isValid}
>
{
mode === 'create' ?
I18n.t('common.buttons.create')
:
I18n.t('common.buttons.update')
}
</Button>
</div>
<textarea
{...register('description')}
placeholder={I18n.t('site_settings.boards.form.description')}
className="formControl"
/>
</form>
);
}
export default BoardForm;

View File

@@ -130,7 +130,7 @@ class BoardsSiteSettingsP extends React.Component<Props> {
<Box>
<h2>{I18n.t('site_settings.boards.new')}</h2>
<BoardForm mode='create' handleSubmit={this.handleSubmit} />
<BoardForm mode='create' handleCreate={this.handleSubmit} />
</Box>
<SiteSettingsInfoBox areUpdating={settingsAreUpdating || boards.areLoading} error={settingsError} />

View File

@@ -1,9 +1,9 @@
import * as React from 'react';
import { useForm, SubmitHandler } from 'react-hook-form';
import I18n from 'i18n-js';
import Box from '../../common/Box';
import SiteSettingsInfoBox from '../../common/SiteSettingsInfoBox';
import { ISiteSettingsGeneralForm } from '../../../reducers/SiteSettings/generalReducer';
import Button from '../../common/Button';
import HttpStatus from '../../../constants/http_status';
import {
@@ -12,18 +12,22 @@ import {
TENANT_BRAND_LOGO_ONLY,
TENANT_BRAND_NONE,
} from '../../../interfaces/ITenant';
import { DangerText } from '../../common/CustomTexts';
export interface ISiteSettingsGeneralForm {
siteName: string;
siteLogo: string;
brandDisplaySetting: string;
locale: string;
}
interface Props {
originForm: ISiteSettingsGeneralForm;
authenticityToken: string;
form: ISiteSettingsGeneralForm;
areDirty: boolean;
areLoading: boolean;
areUpdating: boolean;
error: string;
requestTenant(): void;
updateTenant(
siteName: string,
siteLogo: string,
@@ -31,136 +35,118 @@ interface Props {
locale: string,
authenticityToken: string
): Promise<any>;
handleChangeSiteName(siteName: string): void;
handleChangeSiteLogo(siteLogo: string): void;
handleChangeBrandDisplaySetting(brandDisplaySetting: string)
handleChangeLocale(locale: string): void;
}
class GeneralSiteSettingsP extends React.Component<Props> {
constructor(props: Props) {
super(props);
const GeneralSiteSettingsP = ({
originForm,
authenticityToken,
this._handleUpdateTenant = this._handleUpdateTenant.bind(this);
}
componentDidMount() {
this.props.requestTenant();
}
_handleUpdateTenant() {
const { siteName, siteLogo, brandDisplaySetting, locale } = this.props.form;
this.props.updateTenant(
siteName,
siteLogo,
brandDisplaySetting,
locale,
this.props.authenticityToken,
areUpdating,
error,
updateTenant,
}: Props) => {
const {
register,
handleSubmit,
formState: { isDirty, isSubmitSuccessful, errors }
} = useForm<ISiteSettingsGeneralForm>({
defaultValues: {
siteName: originForm.siteName,
siteLogo: originForm.siteLogo,
brandDisplaySetting: originForm.brandDisplaySetting,
locale: originForm.locale,
},
});
const onSubmit: SubmitHandler<ISiteSettingsGeneralForm> = data => {
updateTenant(
data.siteName,
data.siteLogo,
data.brandDisplaySetting,
data.locale,
authenticityToken,
).then(res => {
if (res?.status !== HttpStatus.OK) return;
window.location.reload();
});
}
};
render() {
const {
originForm,
form,
areDirty,
areLoading,
areUpdating,
error,
return (
<>
<Box>
<h2>{ I18n.t('site_settings.general.title') }</h2>
handleChangeSiteName,
handleChangeSiteLogo,
handleChangeBrandDisplaySetting,
handleChangeLocale,
} = this.props;
return (
<>
<Box>
<h2>{ I18n.t('site_settings.general.title') }</h2>
<form>
<div className="formRow">
<div className="formGroup col-4">
<label htmlFor="siteName">{ I18n.t('site_settings.general.site_name') }</label>
<input
type="text"
value={areLoading ? originForm.siteName : form.siteName}
onChange={e => handleChangeSiteName(e.target.value)}
id="siteName"
className="formControl"
/>
</div>
<div className="formGroup col-4">
<label htmlFor="siteLogo">{ I18n.t('site_settings.general.site_logo') }</label>
<input
type="text"
value={areLoading ? originForm.siteLogo : form.siteLogo}
onChange={e => handleChangeSiteLogo(e.target.value)}
id="siteLogo"
className="formControl"
/>
</div>
<div className="formGroup col-4">
<label htmlFor="brandSetting">{ I18n.t('site_settings.general.brand_setting') }</label>
<select
value={form.brandDisplaySetting || originForm.brandDisplaySetting}
onChange={e => handleChangeBrandDisplaySetting(e.target.value)}
id="brandSetting"
className="selectPicker"
>
<option value={TENANT_BRAND_NAME_AND_LOGO}>
{ I18n.t('site_settings.general.brand_setting_both') }
</option>
<option value={TENANT_BRAND_NAME_ONLY}>
{ I18n.t('site_settings.general.brand_setting_name') }
</option>
<option value={TENANT_BRAND_LOGO_ONLY}>
{ I18n.t('site_settings.general.brand_setting_logo') }
</option>
<option value={TENANT_BRAND_NONE}>
{ I18n.t('site_settings.general.brand_setting_none') }
</option>
</select>
</div>
<form onSubmit={handleSubmit(onSubmit)}>
<div className="formRow">
<div className="formGroup col-4">
<label htmlFor="siteName">{ I18n.t('site_settings.general.site_name') }</label>
<input
{...register('siteName', { required: true })}
id="siteName"
className="formControl"
/>
<DangerText>{errors.siteName && I18n.t('site_settings.general.validations.site_name')}</DangerText>
</div>
<div className="formGroup">
<label htmlFor="locale">{ I18n.t('site_settings.general.locale') }</label>
<div className="formGroup col-4">
<label htmlFor="siteLogo">{ I18n.t('site_settings.general.site_logo') }</label>
<input
{...register('siteLogo')}
id="siteLogo"
className="formControl"
/>
</div>
<div className="formGroup col-4">
<label htmlFor="brandSetting">{ I18n.t('site_settings.general.brand_setting') }</label>
<select
value={form.locale || originForm.locale}
onChange={e => handleChangeLocale(e.target.value)}
id="locale"
{...register('brandDisplaySetting')}
id="brandSetting"
className="selectPicker"
>
<option value="en">🇬🇧 English</option>
<option value="it">🇮🇹 Italiano</option>
<option value={TENANT_BRAND_NAME_AND_LOGO}>
{ I18n.t('site_settings.general.brand_setting_both') }
</option>
<option value={TENANT_BRAND_NAME_ONLY}>
{ I18n.t('site_settings.general.brand_setting_name') }
</option>
<option value={TENANT_BRAND_LOGO_ONLY}>
{ I18n.t('site_settings.general.brand_setting_logo') }
</option>
<option value={TENANT_BRAND_NONE}>
{ I18n.t('site_settings.general.brand_setting_none') }
</option>
</select>
</div>
</form>
</div>
<div className="formGroup">
<label htmlFor="locale">{ I18n.t('site_settings.general.locale') }</label>
<select
{...register('locale')}
id="locale"
className="selectPicker"
>
<option value="en">🇬🇧 English</option>
<option value="it">🇮🇹 Italiano</option>
</select>
</div>
<br />
<Button
onClick={this._handleUpdateTenant}
disabled={!areDirty}
>
{ I18n.t('common.buttons.update') }
<Button onClick={() => null} disabled={!isDirty}>
{I18n.t('common.buttons.update')}
</Button>
</Box>
</form>
</Box>
<SiteSettingsInfoBox areUpdating={areLoading || areUpdating} error={error} areDirty={areDirty} />
</>
);
}
<SiteSettingsInfoBox
areUpdating={areUpdating}
error={error}
areDirty={isDirty && !isSubmitSuccessful}
/>
</>
);
}
export default GeneralSiteSettingsP;

View File

@@ -5,7 +5,7 @@ import { Store } from 'redux';
import GeneralSiteSettings from '../../../containers/GeneralSiteSettings';
import createStoreHelper from '../../../helpers/createStore';
import { State } from '../../../reducers/rootReducer';
import { ISiteSettingsGeneralForm } from '../../../reducers/SiteSettings/generalReducer';
import { ISiteSettingsGeneralForm } from './GeneralSiteSettingsP';
interface Props {
originForm: ISiteSettingsGeneralForm;

View File

@@ -1,4 +1,5 @@
import * as React from 'react';
import { useForm, SubmitHandler } from 'react-hook-form';
import I18n from 'i18n-js';
import Button from '../../common/Button';
@@ -12,7 +13,7 @@ interface Props {
name?: string;
color?: string;
handleSubmit?(
handleCreate?(
name: string,
color: string,
onSuccess: Function,
@@ -24,104 +25,76 @@ interface Props {
): void;
}
interface State {
interface IPostStatusForm {
name: string;
color: string;
}
class PostStatusForm extends React.Component<Props, State> {
initialState: State = {
name: '',
color: this.getRandomColor(),
};
const PostStatusForm = ({
mode,
id,
name,
color,
handleCreate,
handleUpdate,
}: Props) => {
const getRandomColor = () =>
'#' + padStart((Math.random() * 0xFFFFFF << 0).toString(16), 6, '0');
constructor(props: Props) {
super(props);
const {
register,
handleSubmit,
reset,
formState: { isValid },
} = useForm<IPostStatusForm>({
mode: 'onChange',
defaultValues: {
name: name || '',
color: color || getRandomColor(),
},
});
this.state = this.props.mode === 'create' ?
this.initialState
:
{
name: this.props.name,
color: this.props.color,
};
this.onSubmit = this.onSubmit.bind(this);
}
getRandomColor() {
return '#' + padStart((Math.random() * 0xFFFFFF << 0).toString(16), 6, '0');
}
isFormValid() {
return this.state.name && this.state.name.length > 0 &&
this.state.color && this.state.color.length === 7;
}
onNameChange(nameText: string) {
this.setState({
name: nameText,
});
}
onColorChange(colorText: string) {
this.setState({
color: colorText,
});
}
onSubmit() {
if (this.props.mode === 'create') {
this.props.handleSubmit(
this.state.name,
this.state.color,
() => this.setState({...this.initialState, color: this.getRandomColor()}),
const onSubmit: SubmitHandler<IPostStatusForm> = data => {
if (mode === 'create') {
handleCreate(
data.name,
data.color,
() => reset({ name: '', color: getRandomColor() })
);
} else {
this.props.handleUpdate(this.props.id, this.state.name, this.state.color);
handleUpdate(id, data.name, data.color);
}
}
render() {
const {mode} = this.props;
const {name, color} = this.state;
return (
<form onSubmit={handleSubmit(onSubmit)} className="postStatusForm">
<input
{...register('name', { required: true })}
placeholder={I18n.t('site_settings.post_statuses.form.name')}
autoFocus
className="formControl"
/>
<input
{...register('color', { required: true })}
type="color"
className="formControl postStatusColorInput"
/>
return (
<form className="postStatusForm">
<input
type="text"
placeholder={I18n.t('site_settings.post_statuses.form.name')}
value={name}
onChange={e => this.onNameChange(e.target.value)}
autoFocus
className="form-control"
/>
<input
type="color"
value={color}
onChange={e => this.onColorChange(e.target.value)}
className="form-control postStatusColorInput"
/>
<Button
onClick={e => {
e.preventDefault();
this.onSubmit();
}}
className="newPostStatusButton"
disabled={!this.isFormValid()}
>
{
mode === 'create' ?
I18n.t('common.buttons.create')
:
I18n.t('common.buttons.update')
}
</Button>
</form>
);
}
<Button
onClick={() => null}
className="newPostStatusButton"
disabled={!isValid}
>
{
mode === 'create' ?
I18n.t('common.buttons.create')
:
I18n.t('common.buttons.update')
}
</Button>
</form>
);
}
export default PostStatusForm;

View File

@@ -125,7 +125,7 @@ class PostStatusesSiteSettingsP extends React.Component<Props> {
<Box>
<h2>{I18n.t('site_settings.post_statuses.new')}</h2>
<PostStatusForm mode='create' handleSubmit={this.handleSubmit} />
<PostStatusForm mode='create' handleCreate={this.handleSubmit} />
</Box>
<SiteSettingsInfoBox areUpdating={settingsAreUpdating || postStatuses.areLoading} error={settingsError} />

View File

@@ -1,92 +1,83 @@
import * as React from 'react';
import { SubmitHandler, useForm } from 'react-hook-form';
import I18n from 'i18n-js';
import Box from '../common/Box';
import { TenantSignUpTenantFormState } from '../../reducers/tenantSignUpReducer';
import Button from '../common/Button';
import Spinner from '../common/Spinner';
import { DangerText } from '../common/CustomTexts';
import { ITenantSignUpTenantForm } from './TenantSignUpP';
import HttpStatus from '../../constants/http_status';
interface Props {
tenantForm: TenantSignUpTenantFormState;
handleChangeTenantSiteName(siteName: string): void;
handleChangeTenantSubdomain(subdomain: string): void;
isSubmitting: boolean;
error: string;
handleSubmit(): void;
handleSignUpSubmit(siteName: string, subdomain: string): void;
}
class TenantSignUpForm extends React.Component<Props> {
form: any;
constructor(props: Props) {
super(props);
this.form = React.createRef();
const TenantSignUpForm = ({
isSubmitting,
error,
handleSignUpSubmit,
}: Props) => {
const { register, handleSubmit, formState: { errors } } = useForm<ITenantSignUpTenantForm>();
const onSubmit: SubmitHandler<ITenantSignUpTenantForm> = data => {
handleSignUpSubmit(data.siteName, data.subdomain);
}
render() {
const {
tenantForm,
handleChangeTenantSiteName,
handleChangeTenantSubdomain,
return (
<Box customClass="tenantSignUpStep2">
<h3>{ I18n.t('signup.step2.title') }</h3>
isSubmitting,
error,
handleSubmit,
} = this.props;
<form onSubmit={handleSubmit(onSubmit)}>
<div className="formRow">
<input
{...register('siteName', { required: true })}
autoFocus
placeholder={I18n.t('signup.step2.site_name')}
id="tenantSiteName"
className="formControl"
/>
<DangerText>{errors.siteName && I18n.t('signup.step2.validations.site_name')}</DangerText>
</div>
return (
<Box customClass="tenantSignUpStep2">
<h3>{ I18n.t('signup.step2.title') }</h3>
<form ref={this.form}>
<div className="formRow">
<div className="formRow">
<div className="input-group">
<input
type="text"
autoFocus
value={tenantForm.siteName}
onChange={e => handleChangeTenantSiteName(e.target.value)}
placeholder={I18n.t('signup.step2.site_name')}
required
id="tenantSiteName"
{...register('subdomain', {
required: true,
validate: async (newSubdomain) => {
const res = await fetch(`/is_available?new_subdomain=${newSubdomain}`);
return res.status === HttpStatus.OK;
},
})}
placeholder={I18n.t('signup.step2.subdomain')}
id="tenantSubdomain"
className="formControl"
/>
</div>
<div className="formRow">
<div className="input-group">
<input
type="text"
value={tenantForm.subdomain}
onChange={e => handleChangeTenantSubdomain(e.target.value)}
placeholder={I18n.t('signup.step2.subdomain')}
required
id="tenantSubdomain"
className="formControl"
/>
<div className="input-group-append">
<div className="input-group-text">.astuto.io</div>
</div>
<div className="input-group-append">
<div className="input-group-text">.astuto.io</div>
</div>
</div>
<DangerText>
{errors.subdomain?.type === 'required' && I18n.t('signup.step2.validations.subdomain')}
</DangerText>
<DangerText>
{errors.subdomain?.type === 'validate' && I18n.t('signup.step2.validations.subdomain_already_taken')}
</DangerText>
</div>
<Button
onClick={e => {
e.preventDefault();
handleSubmit();
}}
className="tenantConfirm"
>
{ isSubmitting ? <Spinner /> : I18n.t('signup.step2.create_button') }
</Button>
<Button
onClick={() => null}
className="tenantConfirm"
>
{ isSubmitting ? <Spinner /> : I18n.t('signup.step2.create_button') }
</Button>
{ error !== '' && <DangerText>{ error }</DangerText> }
</form>
</Box>
);
}
{ error !== '' && <DangerText>{ error }</DangerText> }
</form>
</Box>
);
}
export default TenantSignUpForm;

View File

@@ -1,31 +1,15 @@
import * as React from 'react';
import { TenantSignUpTenantFormState, TenantSignUpUserFormState } from '../../reducers/tenantSignUpReducer';
import { useState } from 'react';
import HttpStatus from '../../constants/http_status';
import ConfirmSignUpPage from './ConfirmSignUpPage';
import TenantSignUpForm from './TenantSignUpForm';
import UserSignUpForm from './UserSignUpForm';
interface Props {
authenticityToken: string;
currentStep: number;
emailAuth: boolean;
isSubmitting: boolean;
error: string;
toggleEmailAuth(): void;
userForm: TenantSignUpUserFormState;
handleChangeUserFullName(fullName: string): void;
handleChangeUserEmail(email: string): void;
handleChangeUserPassword(password: string): void;
handleChangeUserPasswordConfirmation(passwordConfirmation: string): void;
handleUserFormConfirm(): void;
tenantForm: TenantSignUpTenantFormState;
handleChangeTenantSiteName(siteName: string): void;
handleChangeTenantSubdomain(subdomain: string): void;
handleSubmit(
userFullName: string,
userEmail: string,
@@ -33,92 +17,92 @@ interface Props {
siteName: string,
subdomain: string,
authenticityToken: string,
): void;
): Promise<any>;
authenticityToken: string;
}
class TenantSignUpP extends React.Component<Props> {
constructor(props: Props) {
super(props);
export interface ITenantSignUpUserForm {
fullName: string;
email: string;
password: string;
passwordConfirmation: string;
}
this._handleSubmit = this._handleSubmit.bind(this);
}
export interface ITenantSignUpTenantForm {
siteName: string;
subdomain: string;
}
_handleSubmit() {
const { userForm, tenantForm, handleSubmit } = this.props;
const TenantSignUpP = ({
isSubmitting,
error,
handleSubmit,
authenticityToken
}: Props) => {
const [userData, setUserData] = useState({
fullName: '',
email: '',
password: '',
passwordConfirmation: '',
});
const [tenantData, setTenantData] = useState({
siteName: '',
subdomain: '',
});
const [currentStep, setCurrentStep] = useState(1);
const [emailAuth, setEmailAuth] = useState(false);
const handleSignUpSubmit = (siteName: string, subdomain: string) => {
handleSubmit(
userForm.fullName,
userForm.email,
userForm.password,
tenantForm.siteName,
tenantForm.subdomain,
this.props.authenticityToken,
);
userData.fullName,
userData.email,
userData.password,
siteName,
subdomain,
authenticityToken,
).then(res => {
if (res?.status !== HttpStatus.Created) return;
setTenantData({ siteName, subdomain });
setCurrentStep(currentStep + 1);
});
}
render() {
const {
currentStep,
emailAuth,
toggleEmailAuth,
return (
<div className="tenantSignUpContainer">
{
(currentStep === 1 || currentStep === 2) &&
<UserSignUpForm
currentStep={currentStep}
setCurrentStep={setCurrentStep}
emailAuth={emailAuth}
setEmailAuth={setEmailAuth}
userData={userData}
setUserData={setUserData}
/>
}
userForm,
handleChangeUserFullName,
handleChangeUserEmail,
handleChangeUserPassword,
handleChangeUserPasswordConfirmation,
handleUserFormConfirm,
{
currentStep === 2 &&
<TenantSignUpForm
isSubmitting={isSubmitting}
error={error}
handleSignUpSubmit={handleSignUpSubmit}
/>
}
tenantForm,
handleChangeTenantSiteName,
handleChangeTenantSubdomain,
isSubmitting,
error,
} = this.props;
return (
<div className="tenantSignUpContainer">
{
(currentStep === 1 || currentStep === 2) &&
<UserSignUpForm
currentStep={currentStep}
emailAuth={emailAuth}
toggleEmailAuth={toggleEmailAuth}
userForm={userForm}
handleChangeUserFullName={handleChangeUserFullName}
handleChangeUserEmail={handleChangeUserEmail}
handleChangeUserPassword={handleChangeUserPassword}
handleChangeUserPasswordConfirmation={handleChangeUserPasswordConfirmation}
handleUserFormConfirm={handleUserFormConfirm}
/>
}
{
currentStep === 2 &&
<TenantSignUpForm
tenantForm={tenantForm}
handleChangeTenantSiteName={handleChangeTenantSiteName}
handleChangeTenantSubdomain={handleChangeTenantSubdomain}
isSubmitting={isSubmitting}
error={error}
handleSubmit={this._handleSubmit}
/>
}
{
currentStep === 3 &&
<ConfirmSignUpPage
subdomain={tenantForm.subdomain}
userEmail={userForm.email}
/>
}
</div>
);
}
{
currentStep === 3 &&
<ConfirmSignUpPage
subdomain={tenantData.subdomain}
userEmail={userData.email}
/>
}
</div>
);
}
export default TenantSignUpP;

View File

@@ -1,147 +1,115 @@
import * as React from 'react';
import { SubmitHandler, useForm } from 'react-hook-form';
import I18n from 'i18n-js';
import Box from '../common/Box';
import Button from '../common/Button';
import { TenantSignUpUserFormState } from '../../reducers/tenantSignUpReducer';
import { ITenantSignUpUserForm } from './TenantSignUpP';
import { DangerText } from '../common/CustomTexts';
interface Props {
currentStep: number;
setCurrentStep(step: number): void;
emailAuth: boolean;
toggleEmailAuth(): void;
userForm: TenantSignUpUserFormState;
handleChangeUserFullName(fullName: string): void;
handleChangeUserEmail(email: string): void;
handleChangeUserPassword(password: string): void;
handleChangeUserPasswordConfirmation(passwordConfirmation: string): void;
handleUserFormConfirm(): void;
setEmailAuth(enabled: boolean): void;
userData: ITenantSignUpUserForm;
setUserData({}: ITenantSignUpUserForm): void;
}
class UserSignUpForm extends React.Component<Props> {
form: any;
const UserSignUpForm = ({
currentStep,
setCurrentStep,
emailAuth,
setEmailAuth,
userData,
setUserData,
}: Props) => {
const { register, handleSubmit, setError, formState: { errors } } = useForm<ITenantSignUpUserForm>();
const onSubmit: SubmitHandler<ITenantSignUpUserForm> = data => {
if (data.password !== data.passwordConfirmation) {
setError('passwordConfirmation', I18n.t('signup.step1.validations.password_mismatch'));
return;
}
constructor(props: Props) {
super(props);
this.form = React.createRef();
setUserData({...data});
setCurrentStep(currentStep + 1);
}
validateUserForm(): boolean {
let isValid: boolean = this.form.current.reportValidity();
if (this.validateUserPasswordConfirmation() === false)
isValid = false;
return (
<Box customClass="tenantSignUpStep1">
<h3>{ I18n.t('signup.step1.title') }</h3>
return isValid;
}
{
currentStep === 1 && !emailAuth &&
<Button className="emailAuth" onClick={() => setEmailAuth(true)}>
{ I18n.t('signup.step1.email_auth') }
</Button>
}
validateUserPasswordConfirmation(): boolean {
const isValid = this.props.userForm.password === this.props.userForm.passwordConfirmation;
return isValid;
}
{
currentStep === 1 && emailAuth &&
<form onSubmit={handleSubmit(onSubmit)}>
<div className="formRow">
<input
{...register('fullName', { required: true, minLength: 2 })}
autoFocus
placeholder={I18n.t('common.forms.auth.full_name')}
id="userFullName"
className="formControl"
/>
<DangerText>{ errors.fullName && I18n.t('signup.step1.validations.full_name') }</DangerText>
</div>
render() {
const {
currentStep,
emailAuth,
toggleEmailAuth,
userForm,
handleChangeUserFullName,
handleChangeUserEmail,
handleChangeUserPassword,
handleChangeUserPasswordConfirmation,
handleUserFormConfirm,
} = this.props;
<div className="formRow">
<input
{...register('email', { required: true, pattern: /(.+)@(.+){2,}\.(.+){2,}/ })}
type="email"
placeholder={I18n.t('common.forms.auth.email')}
id="userEmail"
className="formControl"
/>
<DangerText>{ errors.email && I18n.t('signup.step1.validations.email') }</DangerText>
</div>
return (
<Box customClass="tenantSignUpStep1">
<h3>{ I18n.t('signup.step1.title') }</h3>
<div className="formRow">
<div className="formGroup col-6">
<input
{...register('password', { required: true, minLength: 6, maxLength: 128 })}
type="password"
placeholder={I18n.t('common.forms.auth.password')}
id="userPassword"
className="formControl"
/>
<DangerText>{ errors.password && I18n.t('signup.step1.validations.password', { n: 6 }) }</DangerText>
</div>
{
currentStep === 1 && !emailAuth &&
<Button className="emailAuth" onClick={toggleEmailAuth}>
{ I18n.t('signup.step1.email_auth') }
<div className="formGroup col-6">
<input
{...register('passwordConfirmation')}
type="password"
placeholder={I18n.t('common.forms.auth.password_confirmation')}
id="userPasswordConfirmation"
className="formControl"
/>
<DangerText>{ errors.passwordConfirmation && I18n.t('signup.step1.validations.password_mismatch') }</DangerText>
</div>
</div>
<Button
onClick={() => null}
className="userConfirm"
>
{ I18n.t('common.buttons.confirm') }
</Button>
}
</form>
}
{
currentStep === 1 && emailAuth &&
<form ref={this.form}>
<div className="formRow">
<input
type="text"
autoFocus
value={userForm.fullName}
onChange={e => handleChangeUserFullName(e.target.value)}
placeholder={I18n.t('common.forms.auth.full_name')}
required
id="userFullName"
className="formControl"
/>
</div>
<div className="formRow">
<input
type="email"
value={userForm.email}
onChange={e => handleChangeUserEmail(e.target.value)}
placeholder={I18n.t('common.forms.auth.email')}
required
id="userEmail"
className="formControl"
/>
</div>
<div className="formRow">
<div className="formGroup col-6">
<input
type="password"
value={userForm.password}
onChange={e => handleChangeUserPassword(e.target.value)}
placeholder={I18n.t('common.forms.auth.password')}
required
minLength={6}
maxLength={128}
id="userPassword"
className="formControl"
/>
</div>
<div className="formGroup col-6">
<input
type="password"
value={userForm.passwordConfirmation}
onChange={e => handleChangeUserPasswordConfirmation(e.target.value)}
placeholder={I18n.t('common.forms.auth.password_confirmation')}
required
minLength={6}
maxLength={128}
id="userPasswordConfirmation"
className={`formControl${userForm.passwordConfirmationError ? ' invalid' : ''}`}
/>
</div>
</div>
<Button
onClick={e => {
e.preventDefault();
this.validateUserForm() && handleUserFormConfirm();
}}
className="userConfirm"
>
{ I18n.t('common.buttons.confirm') }
</Button>
</form>
}
{
currentStep === 2 &&
<p><b>{userForm.fullName}</b> ({userForm.email})</p>
}
</Box>
);
}
{
currentStep === 2 &&
<p><b>{userData.fullName}</b> ({userData.email})</p>
}
</Box>
);
}
export default UserSignUpForm;