179 lines
6.9 KiB
TypeScript
179 lines
6.9 KiB
TypeScript
import React, { useMemo, useState } from 'react';
|
|
import { Formik, FormikHelpers, FormikState } from 'formik';
|
|
import * as Yup from 'yup';
|
|
import SubmitButton from './SubmitButton';
|
|
import TextField from '@mui/material/TextField';
|
|
import ShowHidePassword from '@ente/shared/components/Form/ShowHidePassword';
|
|
import { FlexWrapper } from '@ente/shared/components/Container';
|
|
import { Button, FormHelperText } from '@mui/material';
|
|
import { t } from 'i18next';
|
|
|
|
interface formValues {
|
|
inputValue: string;
|
|
}
|
|
export interface SingleInputFormProps {
|
|
callback: (
|
|
inputValue: string,
|
|
setFieldError: (errorMessage: string) => void,
|
|
resetForm: (nextState?: Partial<FormikState<formValues>>) => void
|
|
) => Promise<void>;
|
|
fieldType: 'text' | 'email' | 'password';
|
|
placeholder: string;
|
|
buttonText: string;
|
|
submitButtonProps?: any;
|
|
initialValue?: string;
|
|
secondaryButtonAction?: () => void;
|
|
disableAutoFocus?: boolean;
|
|
hiddenPreInput?: any;
|
|
caption?: any;
|
|
hiddenPostInput?: any;
|
|
autoComplete?: string;
|
|
blockButton?: boolean;
|
|
hiddenLabel?: boolean;
|
|
disableAutoComplete?: boolean;
|
|
}
|
|
|
|
export default function SingleInputForm(props: SingleInputFormProps) {
|
|
const { submitButtonProps } = props;
|
|
const { sx: buttonSx, ...restSubmitButtonProps } = submitButtonProps ?? {};
|
|
|
|
const [loading, SetLoading] = useState(false);
|
|
const [showPassword, setShowPassword] = useState(false);
|
|
|
|
const submitForm = async (
|
|
values: formValues,
|
|
{ setFieldError, resetForm }: FormikHelpers<formValues>
|
|
) => {
|
|
SetLoading(true);
|
|
await props.callback(
|
|
values.inputValue,
|
|
(message) => setFieldError('inputValue', message),
|
|
resetForm
|
|
);
|
|
SetLoading(false);
|
|
};
|
|
|
|
const handleClickShowPassword = () => {
|
|
setShowPassword(!showPassword);
|
|
};
|
|
|
|
const handleMouseDownPassword = (
|
|
event: React.MouseEvent<HTMLButtonElement>
|
|
) => {
|
|
event.preventDefault();
|
|
};
|
|
|
|
const validationSchema = useMemo(() => {
|
|
switch (props.fieldType) {
|
|
case 'text':
|
|
return Yup.object().shape({
|
|
inputValue: Yup.string().required(t('REQUIRED')),
|
|
});
|
|
case 'password':
|
|
return Yup.object().shape({
|
|
inputValue: Yup.string().required(t('REQUIRED')),
|
|
});
|
|
case 'email':
|
|
return Yup.object().shape({
|
|
inputValue: Yup.string()
|
|
.email(t('EMAIL_ERROR'))
|
|
.required(t('REQUIRED')),
|
|
});
|
|
}
|
|
}, [props.fieldType]);
|
|
|
|
return (
|
|
<Formik<formValues>
|
|
initialValues={{ inputValue: props.initialValue ?? '' }}
|
|
onSubmit={submitForm}
|
|
validationSchema={validationSchema}
|
|
validateOnChange={false}
|
|
validateOnBlur={false}>
|
|
{({ values, errors, handleChange, handleSubmit }) => (
|
|
<form noValidate onSubmit={handleSubmit}>
|
|
{props.hiddenPreInput}
|
|
<TextField
|
|
hiddenLabel={props.hiddenLabel}
|
|
variant="filled"
|
|
fullWidth
|
|
type={showPassword ? 'text' : props.fieldType}
|
|
id={props.fieldType}
|
|
name={props.fieldType}
|
|
{...(props.hiddenLabel
|
|
? { placeholder: props.placeholder }
|
|
: { label: props.placeholder })}
|
|
value={values.inputValue}
|
|
onChange={handleChange('inputValue')}
|
|
error={Boolean(errors.inputValue)}
|
|
helperText={errors.inputValue}
|
|
disabled={loading}
|
|
autoFocus={!props.disableAutoFocus}
|
|
autoComplete={props.autoComplete}
|
|
InputProps={{
|
|
autoComplete:
|
|
props.disableAutoComplete ||
|
|
props.fieldType === 'password'
|
|
? 'off'
|
|
: 'on',
|
|
endAdornment: props.fieldType === 'password' && (
|
|
<ShowHidePassword
|
|
showPassword={showPassword}
|
|
handleClickShowPassword={
|
|
handleClickShowPassword
|
|
}
|
|
handleMouseDownPassword={
|
|
handleMouseDownPassword
|
|
}
|
|
/>
|
|
),
|
|
}}
|
|
/>
|
|
<FormHelperText
|
|
sx={{
|
|
position: 'relative',
|
|
top: errors.inputValue ? '-22px' : '0',
|
|
float: 'right',
|
|
padding: '0 8px',
|
|
}}>
|
|
{props.caption}
|
|
</FormHelperText>
|
|
{props.hiddenPostInput}
|
|
<FlexWrapper
|
|
justifyContent={'flex-end'}
|
|
flexWrap={
|
|
props.blockButton ? 'wrap-reverse' : 'nowrap'
|
|
}>
|
|
{props.secondaryButtonAction && (
|
|
<Button
|
|
onClick={props.secondaryButtonAction}
|
|
size="large"
|
|
color="secondary"
|
|
sx={{
|
|
'&&&': {
|
|
mt: !props.blockButton ? 2 : 0.5,
|
|
mb: !props.blockButton ? 4 : 0,
|
|
mr: !props.blockButton ? 1 : 0,
|
|
...buttonSx,
|
|
},
|
|
}}
|
|
{...restSubmitButtonProps}>
|
|
{t('CANCEL')}
|
|
</Button>
|
|
)}
|
|
<SubmitButton
|
|
sx={{
|
|
'&&&': {
|
|
mt: 2,
|
|
...buttonSx,
|
|
},
|
|
}}
|
|
buttonText={props.buttonText}
|
|
loading={loading}
|
|
{...restSubmitButtonProps}
|
|
/>
|
|
</FlexWrapper>
|
|
</form>
|
|
)}
|
|
</Formik>
|
|
);
|
|
}
|