Skip to content

Commit

Permalink
Merge pull request #50 from mihaa1/feat/add-option-for-signup-field-o…
Browse files Browse the repository at this point in the history
…verrides

added override options to signup component
  • Loading branch information
lakhansamani authored Oct 15, 2024
2 parents 9c756b7 + c3670d7 commit 9394884
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 148 deletions.
4 changes: 4 additions & 0 deletions src/components/AuthorizerRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useAuthorizer } from '../contexts/AuthorizerContext';
import { StyledWrapper } from '../styledComponents';
import { Views } from '../constants';
import { AuthorizerSignup } from './AuthorizerSignup';
import type { FormFieldsOverrides } from './AuthorizerSignup';
import { AuthorizerForgotPassword } from './AuthorizerForgotPassword';
import { AuthorizerSocialLogin } from './AuthorizerSocialLogin';
import { AuthorizerMagicLinkLogin } from './AuthorizerMagicLinkLogin';
Expand All @@ -19,13 +20,15 @@ export const AuthorizerRoot: FC<{
onForgotPassword?: (data: any) => void;
onPasswordReset?: () => void;
roles?: string[];
signupFieldsOverrides?: FormFieldsOverrides
}> = ({
onLogin,
onSignup,
onMagicLinkLogin,
onForgotPassword,
onPasswordReset,
roles,
signupFieldsOverrides
}) => {
const [view, setView] = useState(Views.Login);
const { config } = useAuthorizer();
Expand Down Expand Up @@ -79,6 +82,7 @@ export const AuthorizerRoot: FC<{
onSignup={onSignup}
urlProps={urlProps}
roles={roles}
fieldOverrides={signupFieldsOverrides}
/>
)}

Expand Down
252 changes: 104 additions & 148 deletions src/components/AuthorizerSignup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,27 @@ import { OtpDataType } from '../types';
import { AuthorizerVerifyOtp } from './AuthorizerVerifyOtp';
import { getEmailPhoneLabels, getEmailPhonePlaceholder } from '../utils/labels';

interface InputDataType {
given_name: string | null;
family_name: string | null;
email_or_phone_number: string | null;
password: string | null;
confirmPassword: string | null;
}
type Field =
| 'given_name'
| 'family_name'
| 'email_or_phone_number'
| 'password'
| 'confirmPassword';

type FieldOverride = {
label: string;
placeholder: string;
hide?: boolean;
notRequired?: boolean;
};

type InputDataType = {
[K in Field]: string | null;
};

export type FormFieldsOverrides = {
[K in Field]?: FieldOverride;
};

const initOtpData: OtpDataType = {
is_screen_visible: false,
Expand All @@ -33,7 +47,8 @@ export const AuthorizerSignup: FC<{
onSignup?: (data: AuthToken) => void;
urlProps?: Record<string, any>;
roles?: string[];
}> = ({ setView, onSignup, urlProps, roles }) => {
fieldOverrides?: FormFieldsOverrides;
}> = ({ setView, onSignup, urlProps, roles, fieldOverrides }) => {
const [error, setError] = useState(``);
const [loading, setLoading] = useState(false);
const [otpData, setOtpData] = useState<OtpDataType>({ ...initOtpData });
Expand All @@ -55,9 +70,8 @@ export const AuthorizerSignup: FC<{
const { authorizerRef, config, setAuthData } = useAuthorizer();
const [disableSignupButton, setDisableSignupButton] = useState(false);

const onInputChange = async (field: string, value: string) => {
const onInputChange = async (field: string, value: string) =>
setFormData({ ...formData, [field]: value });
};

const onSubmit = async (e: any) => {
e.preventDefault();
Expand All @@ -81,8 +95,8 @@ export const AuthorizerSignup: FC<{
return;
}
const data: SignupInput = {
email: email,
phone_number: phone_number,
email,
phone_number,
given_name: formData.given_name || '',
family_name: formData.family_name || '',
password: formData.password || '',
Expand Down Expand Up @@ -151,11 +165,15 @@ export const AuthorizerSignup: FC<{
}
};

const onErrorClose = () => {
setError(``);
};
const onErrorClose = () => setError(``);

useEffect(() => {
if (
fieldOverrides?.given_name?.notRequired ||
fieldOverrides?.given_name?.hide
) {
return;
}
if ((formData.given_name || '').trim() === '') {
setErrorData({ ...errorData, given_name: 'First Name is required' });
} else {
Expand All @@ -164,6 +182,12 @@ export const AuthorizerSignup: FC<{
}, [formData.given_name]);

useEffect(() => {
if (
fieldOverrides?.family_name?.notRequired ||
fieldOverrides?.family_name?.hide
) {
return;
}
if ((formData.family_name || '').trim() === '') {
setErrorData({ ...errorData, family_name: 'Last Name is required' });
} else {
Expand Down Expand Up @@ -247,6 +271,55 @@ export const AuthorizerSignup: FC<{
);
}

const renderField = (
key: Field,
label: string,
placeholder: string,
type?: 'text' | 'password'
) => {
const fieldOverride = fieldOverrides?.[key];
if (fieldOverride?.hide) {
return null;
}
return (
<div className={styles['styled-form-group']}>
<label
className={styles['form-input-label']}
htmlFor={`authorizer-sign-up-${key}`}
>
{!fieldOverride?.notRequired && <span>* </span>}
{fieldOverride?.label ?? label}
</label>
<input
name={key}
id={`authorizer-sign-up-${key}`}
className={`${styles['form-input-field']} ${
errorData[key] ? styles['input-error-content'] : null
}`}
placeholder={fieldOverride?.placeholder ?? placeholder}
type={type}
value={formData[key] || ''}
onChange={e => onInputChange(key, e.target.value)}
/>
{errorData[key] && (
<div className={styles['form-input-error']}>{errorData[key]}</div>
)}
</div>
);
};

const shouldFieldBlockSubmit = (key: Field) => {
if (
(formData[key] ||
fieldOverrides?.[key]?.notRequired ||
fieldOverrides?.[key]?.hide) &&
!errorData[key]
) {
return false;
}
return true;
};

return (
<>
{error && (
Expand All @@ -260,135 +333,20 @@ export const AuthorizerSignup: FC<{
!config.is_magic_link_login_enabled && (
<>
<form onSubmit={onSubmit} name="authorizer-sign-up-form">
<div className={styles['styled-form-group']}>
<label
className={styles['form-input-label']}
htmlFor="authorizer-sign-up-given-name"
>
<span>* </span>First Name
</label>
<input
name="given_name"
id="authorizer-sign-up-given-name"
className={`${styles['form-input-field']} ${
errorData.given_name ? styles['input-error-content'] : null
}`}
placeholder="eg. John"
type="text"
value={formData.given_name || ''}
onChange={e => onInputChange('given_name', e.target.value)}
/>
{errorData.given_name && (
<div className={styles['form-input-error']}>
{errorData.given_name}
</div>
)}
</div>
<div className={styles['styled-form-group']}>
<label
className={styles['form-input-label']}
htmlFor="authorizer-sign-up-family-name"
>
<span>* </span>Last Name
</label>
<input
name="family_name"
id="authorizer-sign-up-family-name"
className={`${styles['form-input-field']} ${
errorData.family_name ? styles['input-error-content'] : null
}`}
placeholder="eg. Doe"
type="text"
value={formData.family_name || ''}
onChange={e => onInputChange('family_name', e.target.value)}
/>
{errorData.family_name && (
<div className={styles['form-input-error']}>
{errorData.family_name}
</div>
)}
</div>
<div className={styles['styled-form-group']}>
<label
className={styles['form-input-label']}
htmlFor="authorizer-sign-up-email-or-phone-number"
>
<span>* </span>
{getEmailPhoneLabels(config)}
</label>
<input
name="email_or_phone_number"
id="authorizer-sign-up-email-or-phone-number"
className={`${styles['form-input-field']} ${
errorData.email_or_phone_number
? styles['input-error-content']
: null
}`}
placeholder={getEmailPhonePlaceholder(config)}
type="text"
value={formData.email_or_phone_number || ''}
onChange={e =>
onInputChange('email_or_phone_number', e.target.value)
}
/>
{errorData.email_or_phone_number && (
<div className={styles['form-input-error']}>
{errorData.email_or_phone_number}
</div>
)}
</div>
<div className={styles['styled-form-group']}>
<label
className={styles['form-input-label']}
htmlFor="authorizer-sign-up-password"
>
<span>* </span>Password
</label>
<input
name="password"
id="authorizer-sign-up-password"
className={`${styles['form-input-field']} ${
errorData.password ? styles['input-error-content'] : null
}`}
placeholder="********"
type="password"
value={formData.password || ''}
onChange={e => onInputChange('password', e.target.value)}
/>
{errorData.password && (
<div className={styles['form-input-error']}>
{errorData.password}
</div>
)}
</div>
<div className={styles['styled-form-group']}>
<label
className={styles['form-input-label']}
htmlFor="authorizer-sign-up-confirm-password"
>
<span>* </span>Confirm Password
</label>
<input
name="confirmPassword"
id="authorizer-sign-up-confirm-password"
className={`${styles['form-input-field']} ${
errorData.confirmPassword
? styles['input-error-content']
: null
}`}
placeholder="********"
type="password"
value={formData.confirmPassword || ''}
onChange={e =>
onInputChange('confirmPassword', e.target.value)
}
/>
{errorData.confirmPassword && (
<div className={styles['form-input-error']}>
{errorData.confirmPassword}
</div>
)}
</div>
{renderField('given_name', 'First Name', 'eg. John', 'text')}
{renderField('family_name', 'Last Name', 'eg. Doe', 'text')}
{renderField(
'email_or_phone_number',
getEmailPhoneLabels(config),
getEmailPhonePlaceholder(config)
)}
{renderField('password', 'Password', '********', 'password')}
{renderField(
'confirmPassword',
'Confirm Password',
'********',
'password'
)}
{config.is_strong_password_enabled && (
<>
<PasswordStrengthIndicator
Expand All @@ -404,13 +362,11 @@ export const AuthorizerSignup: FC<{
disabled={
loading ||
disableSignupButton ||
!!errorData.given_name ||
!!errorData.family_name ||
shouldFieldBlockSubmit('given_name') ||
shouldFieldBlockSubmit('family_name') ||
!!errorData.email_or_phone_number ||
!!errorData.password ||
!!errorData.confirmPassword ||
!formData.given_name ||
!formData.family_name ||
!formData.email_or_phone_number ||
!formData.password ||
!formData.confirmPassword
Expand Down

0 comments on commit 9394884

Please sign in to comment.