mirror of
https://github.com/astuto/astuto.git
synced 2025-12-15 19:27:52 +01:00
Form refactoring (#142)
This commit is contained in:
committed by
GitHub
parent
d078e659c6
commit
9592ac3d1d
@@ -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;
|
||||
@@ -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} />
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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} />
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user