SingleInputForm.tsx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import React, { useMemo, useState } from 'react';
  2. import { Formik, FormikHelpers, FormikState } from 'formik';
  3. import * as Yup from 'yup';
  4. import SubmitButton from './SubmitButton';
  5. import TextField from '@mui/material/TextField';
  6. import ShowHidePassword from './Form/ShowHidePassword';
  7. import { FlexWrapper } from './Container';
  8. import { Button, FormHelperText } from '@mui/material';
  9. import { t } from 'i18next';
  10. interface formValues {
  11. inputValue: string;
  12. }
  13. export interface SingleInputFormProps {
  14. callback: (
  15. inputValue: string,
  16. setFieldError: (errorMessage: string) => void,
  17. resetForm: (nextState?: Partial<FormikState<formValues>>) => void
  18. ) => Promise<void>;
  19. fieldType: 'text' | 'email' | 'password';
  20. placeholder: string;
  21. buttonText: string;
  22. submitButtonProps?: any;
  23. initialValue?: string;
  24. secondaryButtonAction?: () => void;
  25. disableAutoFocus?: boolean;
  26. hiddenPreInput?: any;
  27. caption?: any;
  28. hiddenPostInput?: any;
  29. autoComplete?: string;
  30. blockButton?: boolean;
  31. hiddenLabel?: boolean;
  32. disableAutoComplete?: boolean;
  33. }
  34. export default function SingleInputForm(props: SingleInputFormProps) {
  35. const { submitButtonProps } = props;
  36. const { sx: buttonSx, ...restSubmitButtonProps } = submitButtonProps ?? {};
  37. const [loading, SetLoading] = useState(false);
  38. const [showPassword, setShowPassword] = useState(false);
  39. const submitForm = async (
  40. values: formValues,
  41. { setFieldError, resetForm }: FormikHelpers<formValues>
  42. ) => {
  43. SetLoading(true);
  44. await props.callback(
  45. values.inputValue,
  46. (message) => setFieldError('inputValue', message),
  47. resetForm
  48. );
  49. SetLoading(false);
  50. };
  51. const handleClickShowPassword = () => {
  52. setShowPassword(!showPassword);
  53. };
  54. const handleMouseDownPassword = (
  55. event: React.MouseEvent<HTMLButtonElement>
  56. ) => {
  57. event.preventDefault();
  58. };
  59. const validationSchema = useMemo(() => {
  60. switch (props.fieldType) {
  61. case 'text':
  62. return Yup.object().shape({
  63. inputValue: Yup.string().required(t('REQUIRED')),
  64. });
  65. case 'password':
  66. return Yup.object().shape({
  67. inputValue: Yup.string().required(t('REQUIRED')),
  68. });
  69. case 'email':
  70. return Yup.object().shape({
  71. inputValue: Yup.string()
  72. .email(t('EMAIL_ERROR'))
  73. .required(t('REQUIRED')),
  74. });
  75. }
  76. }, [props.fieldType]);
  77. return (
  78. <Formik<formValues>
  79. initialValues={{ inputValue: props.initialValue ?? '' }}
  80. onSubmit={submitForm}
  81. validationSchema={validationSchema}
  82. validateOnChange={false}
  83. validateOnBlur={false}>
  84. {({ values, errors, handleChange, handleSubmit }) => (
  85. <form noValidate onSubmit={handleSubmit}>
  86. {props.hiddenPreInput}
  87. <TextField
  88. hiddenLabel={props.hiddenLabel}
  89. variant="filled"
  90. fullWidth
  91. type={showPassword ? 'text' : props.fieldType}
  92. id={props.fieldType}
  93. name={props.fieldType}
  94. {...(props.hiddenLabel
  95. ? { placeholder: props.placeholder }
  96. : { label: props.placeholder })}
  97. value={values.inputValue}
  98. onChange={handleChange('inputValue')}
  99. error={Boolean(errors.inputValue)}
  100. helperText={errors.inputValue}
  101. disabled={loading}
  102. autoFocus={!props.disableAutoFocus}
  103. autoComplete={props.autoComplete}
  104. InputProps={{
  105. autoComplete:
  106. props.disableAutoComplete ||
  107. props.fieldType === 'password'
  108. ? 'off'
  109. : 'on',
  110. endAdornment: props.fieldType === 'password' && (
  111. <ShowHidePassword
  112. showPassword={showPassword}
  113. handleClickShowPassword={
  114. handleClickShowPassword
  115. }
  116. handleMouseDownPassword={
  117. handleMouseDownPassword
  118. }
  119. />
  120. ),
  121. }}
  122. />
  123. <FormHelperText
  124. sx={{
  125. position: 'relative',
  126. top: errors.inputValue ? '-22px' : '0',
  127. float: 'right',
  128. padding: '0 8px',
  129. }}>
  130. {props.caption}
  131. </FormHelperText>
  132. {props.hiddenPostInput}
  133. <FlexWrapper
  134. justifyContent={'flex-end'}
  135. flexWrap={
  136. props.blockButton ? 'wrap-reverse' : 'nowrap'
  137. }>
  138. {props.secondaryButtonAction && (
  139. <Button
  140. onClick={props.secondaryButtonAction}
  141. size="large"
  142. color="secondary"
  143. sx={{
  144. '&&&': {
  145. mt: !props.blockButton ? 2 : 0.5,
  146. mb: !props.blockButton ? 4 : 0,
  147. mr: !props.blockButton ? 1 : 0,
  148. ...buttonSx,
  149. },
  150. }}
  151. {...restSubmitButtonProps}>
  152. {t('CANCEL')}
  153. </Button>
  154. )}
  155. <SubmitButton
  156. sx={{
  157. '&&&': {
  158. mt: 2,
  159. ...buttonSx,
  160. },
  161. }}
  162. buttonText={props.buttonText}
  163. loading={loading}
  164. {...restSubmitButtonProps}
  165. />
  166. </FlexWrapper>
  167. </form>
  168. )}
  169. </Formik>
  170. );
  171. }