ente/packages/shared/components/SingleInputForm.tsx
2023-11-02 09:06:31 +05:30

180 lines
6.8 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 './Form/ShowHidePassword';
import { FlexWrapper } from './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>
);
}