formik#Field TypeScript Examples

The following examples show how to use formik#Field. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: form-field.component.tsx    From MyWay-client with MIT License 6 votes vote down vote up
export default function FormField({
  children,
  name,
  type = "text",
  placeholder = "",
  as = null,
}: {
  children?: ReactNode | undefined;
  name: string;
  type?: string;
  placeholder?: string;
  as?: null | string;
}) {
  return (
    <Field
      name={name}
      type={type}
      placeholder={placeholder}
      as={as}
      className="w-full my-2"
    >
      {children}
    </Field>
  );
}
Example #2
Source File: SignInProject.view.tsx    From tezos-link with Apache License 2.0 6 votes vote down vote up
SignInProjectView = ({ handleSubmitForm }: NewPostViewProps) => (
  <SignInProjectCard>
    <h1>Sign In</h1>
    <Formik
      initialValues={{
        uuid: ''
      }}
      validationSchema={signInProjectValidator}
      validateOnBlur={false}
      onSubmit={values => handleSubmitForm(values)}
    >
      {formikProps => {
        const { handleSubmit } = formikProps
        return (
          <form onSubmit={handleSubmit}>
            <Field
              InputType={Input}
              component={FormInputField}
              icon="user"
              name="uuid"
              placeholder="e4efba4d-47e6-42a5-905e-589d3f673853"
            />

            <Button text="Sign in project" icon="login" type="submit" />
          </form>
        )
      }}
    </Formik>
  </SignInProjectCard>
)
Example #3
Source File: CommentForm.tsx    From End-to-End-Web-Testing-with-Cypress with MIT License 6 votes vote down vote up
CommentForm: React.FC<CommentFormProps> = ({ transactionId, transactionComment }) => {
  const classes = useStyles();
  const initialValues = { content: "" };

  return (
    <div>
      <Formik
        initialValues={initialValues}
        validationSchema={validationSchema}
        onSubmit={(values, { setSubmitting }) => {
          setSubmitting(true);
          transactionComment({ transactionId, ...values });
        }}
      >
        {() => (
          <Form className={classes.form}>
            <Field name="content">
              {({ field, meta }: FieldProps) => (
                <TextField
                  variant="outlined"
                  margin="dense"
                  fullWidth
                  id={`transaction-comment-input-${transactionId}`}
                  type="text"
                  placeholder="Write a comment..."
                  inputProps={{ "data-test": `transaction-comment-input-${transactionId}` }}
                  error={meta.touched && Boolean(meta.error)}
                  helperText={meta.touched ? meta.error : ""}
                  {...field}
                />
              )}
            </Field>
          </Form>
        )}
      </Formik>
    </div>
  );
}
Example #4
Source File: NewProject.view.tsx    From tezos-link with Apache License 2.0 6 votes vote down vote up
NewProjectView = ({ handleSubmitForm, loading  }: NewPostViewProps) => {
        const [networkValue, setNetwork] = useState('MAINNET')

        return (
        <NewProjectCard>
            <h1>New Project</h1>
            <Formik
                initialValues={{title: '', network: ''}}
                validationSchema={newProjectValidator}
                validateOnBlur={false}
                onSubmit={(values, actions) => handleSubmitForm({ ...values, network: networkValue }, actions)}
            >
                {formikProps => {
                    const {handleSubmit} = formikProps
                    return (
                        <div>
                            <Select
                                options={['MAINNET', 'CARTHAGENET']}
                                defaultOption={networkValue}
                                selectCallback={(e: string) => setNetwork(e)}
                            />
                            <form onSubmit={handleSubmit}>

                                <Field InputType={Input} component={FormInputField} icon="user" name="title"
                                       placeholder="Project title"/>

                                <Button text="Create project" icon="sign-up" type="submit" loading={loading}/>
                            </form>
                        </div>
                    )
                }}
            </Formik>
        </NewProjectCard>
    )
}
Example #5
Source File: Input.tsx    From panvala with Apache License 2.0 6 votes vote down vote up
StyledInput = styled(Field)`
  box-sizing: border-box;
  display: block;
  width: 100%;
  font-size: 0.875em;
  margin-top: 8px;
  padding: 16px 8px;
  border-radius: 8px;

  ${space};
  ${color};
  ${layout};
  ${typography};
  ${flexbox};
  ${border};
  ${background}
  ${shadow};
  ${position};
`
Example #6
Source File: InputBox.tsx    From slice-machine with Apache License 2.0 6 votes vote down vote up
InputBox: React.FunctionComponent<InputBoxProps> = ({
  name,
  label,
  placeholder,
  error,
  dataCy,
}) => (
  <Box mb={3}>
    <Label htmlFor={name} mb={2}>
      {label}
    </Label>
    <Field
      name={name}
      type="text"
      placeholder={placeholder}
      as={Input}
      autoComplete="off"
      {...(dataCy ? { "data-cy": dataCy } : null)}
    />
    {error ? (
      <Text
        data-cy={dataCy ? `${dataCy}-error` : "input-error"}
        sx={{ color: "error", mt: 1 }}
      >
        {error}
      </Text>
    ) : null}
  </Box>
)
Example #7
Source File: index.tsx    From advanced-formik-validations-with-yup with MIT License 6 votes vote down vote up
FormikField: React.FC<FormikFieldProps> = ({ name, label, type = "text", required = false}) => {
  return (
    <div className="FormikField">
      <Field
        required={required}
        autoComplete="off"
        as={TextField}
        label={label}
        name={name}
        fullWidth
        type={type}
        helperText={<ErrorMessage name={name} />}
      />
    </div>
  );
}
Example #8
Source File: index.tsx    From Mokku with MIT License 6 votes vote down vote up
Input = styled(Field).attrs({ id: "mock-create-input" })<{
  small?: boolean;
  marginRight?: boolean;
}>`
  border: 1px solid ${({ theme }) => theme.colors.border};
  border-radius: 4px;
  border-style: solid;
  ${({ small }) => small && `width: 124px;`};
  ${({ marginRight }) => marginRight && `margin-right: 8px;`};
`
Example #9
Source File: Autocomplete.test.tsx    From abacus with GNU General Public License v2.0 6 votes vote down vote up
test('it shows as loading data', () => {
  const isLoading = true

  const { container } = render(
    <MockFormik initialValues={{ name: 'no_name' }}>
      <Field
        component={Autocomplete}
        name='name'
        id='name'
        fullWidth
        options={[]}
        loading={isLoading}
        renderInput={(params: AutocompleteRenderInputParams) => {
          return (
            <MuiTextField
              {...params}
              placeholder='wp_username'
              helperText='Use WordPress.com username.'
              variant='outlined'
              required
              label='Owner'
              InputProps={{
                ...autocompleteInputProps(params, isLoading),
                startAdornment: <InputAdornment position='start'>@</InputAdornment>,
              }}
              InputLabelProps={{
                shrink: true,
              }}
            />
          )
        }}
      />
    </MockFormik>,
  )
  expect(container).toMatchSnapshot('loading')
})
Example #10
Source File: index.tsx    From Account-Manager with MIT License 6 votes vote down vote up
FormInput: FC<ComponentProps> = ({
  hideErrorBlock = false,
  hideErrorText = false,
  label,
  required,
  ...baseInputProps
}) => {
  const {className, name} = baseInputProps;
  const {errors, touched} = useFormContext();
  const error = !!errors[name] && !!touched[name];

  return (
    <div className={clsx('FormInput FormFieldComponent', className)}>
      {renderFormLabel({className, label, name, required})}
      <Field {...baseInputProps} as={Input} className="FormField" error={error} required={required} />
      {hideErrorBlock ? null : renderFormError({className, hideErrorText, name})}
    </div>
  );
}
Example #11
Source File: add-training-goal-task.form.component.tsx    From MyWay-client with MIT License 6 votes vote down vote up
export default function AddTrainingGoalTaskForm({
  dogId,
  goalId,
}: {
  dogId: number;
  goalId: number;
}) {
  return (
    <Formik
      initialValues={{ description: "" }}
      onSubmit={(values, actions) => {
        axios.post(`/api/dogs/${dogId}/training-goals/${goalId}/tasks`, {
          ...values,
        });
      }}
    >
      <Form>
        <Field name="description" placeholder="description" />
        <ErrorMessage name="description" />

        <button type="submit">Add Task</button>
      </Form>
    </Formik>
  );
}
Example #12
Source File: Beginning.tsx    From abacus with GNU General Public License v2.0 6 votes vote down vote up
Beginning = (): JSX.Element => {
  const classes = useStyles()

  return (
    <div className={classes.root}>
      <Typography variant='h4' gutterBottom>
        Design and Document Your Experiment
      </Typography>
      <Typography variant='body2'>
        We think one of the best ways to prevent a failed experiment is by documenting what you hope to learn.{/* */}
        <br />
        <br />
      </Typography>
      <Alert severity='info'>
        <Link underline='always' href='https://github.com/Automattic/experimentation-platform/wiki' target='_blank'>
          Our wiki is a great place to start
        </Link>
        , it will instruct you on creating a P2 post.
      </Alert>
      <Field
        className={classes.p2EntryField}
        component={TextField}
        id='experiment.p2Url'
        name='experiment.p2Url'
        placeholder='https://your-p2-post-here'
        label={`Your Post's URL`}
        variant='outlined'
        InputLabelProps={{
          shrink: true,
        }}
      />
    </div>
  )
}
Example #13
Source File: index.tsx    From youtube-2020-june-multi-step-form-formik with MIT License 5 votes vote down vote up
export default function Home() {
  return (
    <Card>
      <CardContent>
        <FormikStepper
          initialValues={{
            firstName: '',
            lastName: '',
            millionaire: false,
            money: 0,
            description: '',
          }}
          onSubmit={async (values) => {
            await sleep(3000);
            console.log('values', values);
          }}
        >
          <FormikStep label="Personal Data">
            <Box paddingBottom={2}>
              <Field fullWidth name="firstName" component={TextField} label="First Name" />
            </Box>
            <Box paddingBottom={2}>
              <Field fullWidth name="lastName" component={TextField} label="Last Name" />
            </Box>
            <Box paddingBottom={2}>
              <Field
                name="millionaire"
                type="checkbox"
                component={CheckboxWithLabel}
                Label={{ label: 'I am a millionaire' }}
              />
            </Box>
          </FormikStep>
          <FormikStep
            label="Bank Accounts"
            validationSchema={object({
              money: mixed().when('millionaire', {
                is: true,
                then: number()
                  .required()
                  .min(
                    1_000_000,
                    'Because you said you are a millionaire you need to have 1 million'
                  ),
                otherwise: number().required(),
              }),
            })}
          >
            <Box paddingBottom={2}>
              <Field
                fullWidth
                name="money"
                type="number"
                component={TextField}
                label="All the money I have"
              />
            </Box>
          </FormikStep>
          <FormikStep label="More Info">
            <Box paddingBottom={2}>
              <Field fullWidth name="description" component={TextField} label="Description" />
            </Box>
          </FormikStep>
        </FormikStepper>
      </CardContent>
    </Card>
  );
}
Example #14
Source File: index.tsx    From Mokku with MIT License 5 votes vote down vote up
Input = styled(Field)<{ small?: boolean }>`
  height: 25px;
  border: 1px solid ${({ theme }) => theme.colors.border};
  border-radius: 4px;
  border-style: solid;
  ${({ small }) => small && `width: 124px;`};
`
Example #15
Source File: Login.tsx    From krmanga with MIT License 5 votes vote down vote up
Login = ({ navigation, dispatch, isLogin, loading }: IProps) => {

    const [disabled, setDisabled] = useState<boolean>(false);

    useEffect(() => {
        if (isLogin) {
            setTimeout(() => {
                navigation.goBack();
            }, 100);
        }
    }, [isLogin]);

    const onSubmit = (values: Values) => {

        if (disabled || loading) {
            return;
        }

        setDisabled(true);

        dispatch({
            type: "user/login",
            payload: values,
            callback: () => {
                setDisabled(false);
            }
        });
    };

    const cancel = (form: FormikProps<string>, field: FieldInputProps<string>) => {
        if (field.name === "account") {
            form.setFieldValue("account", "");
        } else if (field.name === "password") {
            form.setFieldValue("password", "");
        }
    };

    return (
        <ScrollView keyboardShouldPersistTaps="handled" style={styles.container}>
            <Formik
                initialValues={initialValues}
                onSubmit={onSubmit}
                validationSchema={customerValidation}>
                {({ handleSubmit }) => (
                    <View>
                        <Field
                            name="account"
                            placeholder="่ฏท่พ“ๅ…ฅ็”จๆˆทๅ"
                            component={Input}
                            iconName={"icon-Account"}
                            cancel={cancel}
                        />
                        <Field
                            name="password"
                            placeholder="่ฏท่พ“ๅ…ฅๅฏ†็ "
                            component={Input}
                            iconName={"icon-mima"}
                            secureTextEntry
                            cancel={cancel}
                        />
                        <View style={styles.jumpView}>
                            <Text style={styles.jumpTitle}>ๅฟ˜่ฎฐๅฏ†็ ?</Text>
                            <Touchable onPress={() => navigation.navigate("Register")}>
                                <Text style={styles.jumpTitle}>ๆณจๅ†Œ่ดฆๅท</Text>
                            </Touchable>
                        </View>
                        <Touchable disabled={disabled} onPress={handleSubmit} style={styles.login}>
                            <Text style={styles.loginText}>็™ปๅฝ•</Text>
                        </Touchable>
                    </View>
                )}
            </Formik>
        </ScrollView>
    );
}
Example #16
Source File: SwarmSelect.tsx    From bee-dashboard with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
export function SwarmSelect({ defaultValue, formik, name, options, onChange, label }: Props): ReactElement {
  const classes = useStyles()

  if (formik) {
    return (
      <>
        {label && <FormHelperText>{label}</FormHelperText>}
        <Field
          required
          component={Select}
          name={name}
          fullWidth
          variant="outlined"
          defaultValue={defaultValue || ''}
          className={classes.select}
          placeholder={label}
          MenuProps={{ MenuListProps: { disablePadding: true }, PaperProps: { square: true } }}
        >
          {options.map((x, i) => (
            <MenuItem key={i} value={x.value} className={classes.option}>
              {x.label}
            </MenuItem>
          ))}
        </Field>
      </>
    )
  }

  return (
    <>
      {label && <FormHelperText>{label}</FormHelperText>}
      <SimpleSelect
        required
        name={name}
        fullWidth
        variant="outlined"
        className={classes.select}
        defaultValue={defaultValue || ''}
        onChange={onChange}
        placeholder={label}
        MenuProps={{ MenuListProps: { disablePadding: true }, PaperProps: { square: true } }}
      >
        {options.map((x, i) => (
          <MenuItem key={i} value={x.value} className={classes.option}>
            {x.label}
          </MenuItem>
        ))}
      </SimpleSelect>
    </>
  )
}
Example #17
Source File: MetaFile.tsx    From gear-js with GNU General Public License v3.0 5 votes vote down vote up
MetaFile = (props: Props) => {
  const alert = useAlert();
  const metaFieldRef = useRef<HTMLInputElement>(null);

  const { file, className, onUpload, onDelete } = props;

  const uploadMetaFile = () => {
    metaFieldRef.current?.click();
  };

  const handleChangeMetaFile = (event: React.ChangeEvent<HTMLInputElement>) => {
    if (event.target.files && event.target.files.length) {
      const isCorrectFormat = checkFileFormat(event.target.files[0]);

      if (isCorrectFormat) {
        onUpload(event.target.files[0]);
      } else {
        alert.error('Wrong file format');
      }

      event.target.value = '';
    }
  };

  return (
    <div className={clsx(styles.upload, className)}>
      <label htmlFor="meta" className={styles.caption}>
        Metadata file:
      </label>
      <div className={styles.block}>
        <Field
          id="meta"
          name="meta"
          className={styles.hidden}
          type="file"
          innerRef={metaFieldRef}
          onChange={handleChangeMetaFile}
        />
        {file ? (
          <div className={clsx(styles.value, styles.filename)}>
            {file.name}
            <button type="button" onClick={onDelete}>
              <Trash2 color="#ffffff" size="20" strokeWidth="1" />
            </button>
          </div>
        ) : (
          <Button
            text="Select file"
            type="button"
            color="secondary"
            className={styles.button}
            onClick={uploadMetaFile}
          />
        )}
      </div>
    </div>
  );
}
Example #18
Source File: TextArea.tsx    From core with GNU Affero General Public License v3.0 5 votes vote down vote up
TextArea: React.FC<TextAreaProps> = ({ name, placeholder, theme='auto', max, setValue, value }) => {
	const ref = useRef()
	const [ emojiPickerHidden, setEmojiPickerHidden ] = useState(true)
	useOutsideClick(ref, () => {
		setEmojiPickerHidden(true)
	})
	
	return <div className='border border-grey-light dark:border-transparent h-96 text-black dark:bg-very-black dark:text-white rounded px-4 py-3 inline-block relative w-full'>
		<Field as='textarea' name={name} className='dark:border-transparent text-black dark:bg-very-black dark:text-white w-full relative h-full resize-none outline-none' placeholder={placeholder} />
		<div ref={ref}>
			<div className='absolute bottom-12 left-10 z-30'>
				{
					!emojiPickerHidden && <Picker title='์„ ํƒํ•ด์ฃผ์„ธ์š”' emoji='sunglasses' set='twitter' enableFrequentEmojiSort	theme={theme} showSkinTones={false} onSelect={(e) => {
						setEmojiPickerHidden(true)
						setValue(value + ' ' + ((e as { native: string }).native || e.colons))
					}} i18n={{
						search: '๊ฒ€์ƒ‰',
						notfound: '๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.',
						categories: {
							search: '๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ',
							recent: '์ตœ๊ทผ ์‚ฌ์šฉ',
							people: '์‚ฌ๋žŒ',
							nature: '์ž์—ฐ',
							foods: '์Œ์‹',
							activity: 'ํ™œ๋™',
							places: '์žฅ์†Œ',
							objects: '์‚ฌ๋ฌผ',
							symbols: '๊ธฐํ˜ธ',
							flags: '๊ตญ๊ธฐ',
							custom: '์ปค์Šคํ…€'
						}
					}} custom={KoreanbotsEmoji}/>
				}
			</div>
			<div className='absolute bottom-2 left-4 hidden sm:block'>
				<div className='emoji-selector-button outline-none' onClick={() => setEmojiPickerHidden(false)} onKeyPress={() => setEmojiPickerHidden(false)} role='button' tabIndex={0} />
			</div>
			{
				max && <span className={`absolute bottom-2 right-4 ${max < value.length ? ' text-red-400' : ''}`}>
					{max-value.length}
				</span>
			}
		</div>
	</div>
}
Example #19
Source File: RecurrenceEditor.tsx    From querybook with Apache License 2.0 5 votes vote down vote up
RecurrenceEditorDatePicker: React.FunctionComponent<IDatePickerProps> = ({
    label,
    onKey,
    options,
    error,
    recurrence,
    setRecurrence,
}) => {
    const formattedError = (error?.[onKey] || '').replace(
        `recurrence.on.${onKey}`,
        label
    );
    return (
        <FormField label={`Recurrence ${label}`} error={formattedError}>
            <Field
                name={`recurrence.on.${onKey}`}
                render={({ field }) => (
                    <Select<IOptionType, true>
                        menuPortalTarget={overlayRoot}
                        styles={recurrenceReactSelectStyle}
                        value={options.filter((option: { value: any }) =>
                            field.value?.includes(option.value)
                        )}
                        options={options}
                        onChange={(value) => {
                            const newRecurrence = {
                                ...recurrence,
                                on: {
                                    ...recurrence.on,
                                    [onKey]: value.map((v) => v.value),
                                },
                            };
                            setRecurrence(newRecurrence);
                        }}
                        isMulti
                    />
                )}
            />
        </FormField>
    );
}
Example #20
Source File: CheckBox.tsx    From core with GNU Affero General Public License v3.0 5 votes vote down vote up
CheckBox: React.FC<CheckBoxProps> = ({ name, ...props }) => {
	return <Field type='checkbox' name={name} className='form-checkbox text-koreanbots-blue bg-gray-300 h-4 w-4 rounded' {...props} />
}
Example #21
Source File: TagFormFields.tsx    From abacus with GNU General Public License v2.0 5 votes vote down vote up
TagFormFields = (): JSX.Element => {
  const classes = useStyles()

  return (
    <>
      <div className={classes.row}>
        <Field
          component={TextField}
          name='tag.namespace'
          id='tag.namespace'
          label='Tag namespace'
          placeholder='tag_namespace'
          helperText='Use snake_case.'
          variant='outlined'
          fullWidth
          required
          InputLabelProps={{
            shrink: true,
          }}
        />
      </div>
      <div className={classes.row}>
        <Field
          component={TextField}
          name='tag.name'
          id='tag.name'
          label='Tag name'
          placeholder='tag_name'
          helperText='Use snake_case.'
          variant='outlined'
          fullWidth
          required
          InputLabelProps={{
            shrink: true,
          }}
        />
      </div>
      <div className={classes.row}>
        <Field
          component={TextField}
          name='tag.description'
          id='tag.description'
          label='Tag description'
          placeholder='Put your Tag description here!'
          variant='outlined'
          fullWidth
          required
          multiline
          rows={4}
          InputLabelProps={{
            shrink: true,
          }}
        />
      </div>
    </>
  )
}
Example #22
Source File: dog-profile.component.tsx    From MyWay-client with MIT License 5 votes vote down vote up
export default function DogProfile({ dog }: { dog: DogDto }) {
  return (
    <div>
      <div>
        <div>
          <div>Dog{"'"}s picture</div>
          <span></span>
        </div>
        <div>
          <div>
            Upload {dog.name}
            {"'"}s photo
          </div>
          <div>
            <button>Upload photo</button>
          </div>
        </div>
      </div>
      <Formik
        initialValues={{
          name: dog.name,
          breed: dog.breed,
          age_years: calculateDiffInYears(new Date(), new Date(dog.birthDate)),
          age_months: calculateDiffInMonths(
            new Date(),
            new Date(dog.birthDate)
          ),
        }}
        onSubmit={async (values, actions) => {
          axios
            .patch(`/api/dogs/${dog.id}`, values)
            .then((res) =>
              actions.setStatus({
                status: true,
                message: "Changes were saved successfully.",
              })
            )
            .catch((e) =>
              actions.setStatus({ status: true, message: e.message })
            )
            .finally(() => actions.setSubmitting(false));
        }}
        validationSchema={DogProfileSchema}
      >
        {({ isSubmitting, status }) => (
          <Form>
            <Field name="name" type="text" placeholder="Name" />
            <ErrorMessage name="name" />

            <Field name="breed" type="text" placeholder="Breed" />
            <ErrorMessage name="breed" />

            <Field name="age_years" type="number" placeholder="Age (years)" />
            <ErrorMessage name="age_years" />

            <Field name="age_months" type="number" placeholder="Age (months)" />
            <ErrorMessage name="age_months" />

            {status && <>{status.message}</>}

            <SubmitButton isSubmitting={isSubmitting} />
          </Form>
        )}
      </Formik>
    </div>
  );
}
Example #23
Source File: index.tsx    From core with GNU Affero General Public License v3.0 4 votes vote down vote up
Bots: NextPage<BotsProps> = ({ data, desc, date, user, theme, csrfToken }) => {
	const bg = checkBotFlag(data?.flags, 'trusted') && data?.banner
	const router = useRouter()
	const [ nsfw, setNSFW ] = useState<boolean>()
	const [ reportModal, setReportModal ] = useState(false)
	const [ reportRes, setReportRes ] = useState<ResponseProps<unknown>>(null)
	useEffect(() => {
		setNSFW(localStorage.nsfw)
	}, [])
	if (!data?.id) return <NotFound />
	return <div style={bg ? { background: `linear-gradient(to right, rgba(34, 36, 38, 0.68), rgba(34, 36, 38, 0.68)), url("${data.bg}") center top / cover no-repeat fixed` } : {}}>
		<Container paddingTop className='py-10'>
			<NextSeo
				title={data.name}
				description={data.intro}
				twitter={{
					cardType: 'summary_large_image'
				}}
				openGraph={{
					images: [
						{
							url: KoreanbotsEndPoints.OG.bot(data.id, data.name, data.intro, data.category, [formatNumber(data.votes), formatNumber(data.servers)]),
							width: 2048,
							height: 1170,
							alt: 'Bot Preview Image'
						}
					]
				}}
			/>
			{
				data.state === 'blocked' ? <div className='pb-40'>
					<Message type='error'>
						<h2 className='text-lg font-black'>ํ•ด๋‹น ๋ด‡์€ ๊ด€๋ฆฌ์ž์— ์˜ํ•ด ์‚ญ์ œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.</h2>
					</Message>
				</div>
					: data.category.includes('NSFW') && !nsfw ? <NSFW onClick={() => setNSFW(true)} onDisableClick={() => localStorage.nsfw = true} /> 
						: <>
							<div className='w-full pb-2'>
								{
									data.state === 'private' ? <Message type='info'>
										<h2 className='text-lg font-black'>ํ•ด๋‹น ๋ด‡์€ ํŠน์ˆ˜๋ชฉ์  ๋ด‡์ด๋ฏ€๋กœ ์ดˆ๋Œ€ํ•˜์‹ค ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.</h2>
										<p>ํ•ด๋‹น ๋ด‡์€ ๊ณต๊ฐœ ์‚ฌ์šฉ์ด ๋ชฉ์ ์ด ์•„๋‹Œ ํŠน์ˆ˜๋ชฉ์ ๋ด‡์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋”ฐ๋กœ ์ดˆ๋Œ€ํ•˜์‹ค ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.</p>
									</Message> :
										data.state === 'reported' ?
											<Message type='error'>
												<h2 className='text-lg font-black'>ํ•ด๋‹น ๋ด‡์€ ์‹ ๊ณ ๊ฐ€ ์ ‘์ˆ˜๋˜์–ด, ๊ด€๋ฆฌ์ž์— ์˜ํ•ด ์ž ๊ธˆ ์ƒํƒœ์ž…๋‹ˆ๋‹ค.</h2>
												<p>ํ•ด๋‹น ๋ด‡ ์‚ฌ์šฉ์— ์ฃผ์˜ํ•ด์ฃผ์„ธ์š”.</p>
												<p>๋ด‡ ์†Œ์œ ์ž๋ถ„์€ <Link href='/guidelines'><a className='text-blue-500 hover:text-blue-400'>๊ฐ€์ด๋“œ๋ผ์ธ</a></Link>์— ๋Œ€ํ•œ ์œ„๋ฐ˜์‚ฌํ•ญ์„ ํ™•์ธํ•ด์ฃผ์‹œ๊ณ  <Link href='/discord'><a className='text-blue-500 hover:text-blue-400'>๋””์Šค์ฝ”๋“œ ์„œ๋ฒ„</a></Link>๋กœ ๋ฌธ์˜ํ•ด์ฃผ์„ธ์š”.</p>
											</Message> : ''
								}
							</div>
							<div className='lg:flex w-full'>
								<div className='w-full text-center lg:w-2/12'>
									<DiscordAvatar
										userID={data.id}
										size={256}
										className='w-full'
									/>
								</div>
								<div className='flex-grow px-5 py-12 w-full text-center lg:w-5/12 lg:text-left'>
									<Tag
										circular
										text={
											<>
												<i className={`fas fa-circle text-${Status[data.status]?.color}`} />{' '}
												{Status[data.status]?.text}
											</>
										}
									/>
									<h1 className='mb-2 mt-3 text-4xl font-bold' style={bg ? { color: 'white' } : {}}>
										{data.name}{' '}
										{checkBotFlag(data.flags, 'trusted') ? (
											<Tooltip placement='bottom' overlay='ํ•ด๋‹น ๋ด‡์€ ํ•œ๊ตญ ๋””์Šค์ฝ”๋“œ ๋ฆฌ์ŠคํŠธ์—์„œ ์—„๊ฒฉํ•œ ๊ธฐ์ค€์„ ํ†ต๊ณผํ•œ ๋ด‡์ž…๋‹ˆ๋‹ค!'>
												<span className='text-koreanbots-blue text-3xl'>
													<i className='fas fa-award' />
												</span>
											</Tooltip>
										) : ''}
									</h1>
									<p className={`${bg ? 'text-gray-300' : 'dark:text-gray-300 text-gray-800'} text-base`}>{data.intro}</p>
								</div>
								<div className='w-full lg:w-1/4'>
									{
										data.state === 'ok' && <LongButton
											newTab
											href={`/bots/${router.query.id}/invite`}
										>
											<h4 className='whitespace-nowrap'>
												<i className='fas fa-user-plus text-discord-blurple' /> ์ดˆ๋Œ€ํ•˜๊ธฐ
											</h4>
										</LongButton>
									}
									<Link href={`/bots/${router.query.id}/vote`}>
										<LongButton>
											<h4>
												<i className='fas fa-heart text-red-600' /> ํ•˜ํŠธ ์ถ”๊ฐ€
											</h4>
											<span className='ml-1 px-2 text-center text-black dark:text-gray-400 text-sm bg-little-white-hover dark:bg-very-black rounded-lg'>
												{formatNumber(data.votes)}
											</span>
										</LongButton>
									</Link>
									{
										((data.owners as User[]).find(el => el.id === user?.id) || checkUserFlag(user?.flags, 'staff')) && <LongButton href={`/bots/${data.id}/edit`}>
											<h4>
												<i className='fas fa-cogs' /> ๊ด€๋ฆฌํ•˜๊ธฐ
											</h4>
										</LongButton>
									}
									{
										((data.owners as User[]).find(el => el.id === user?.id) || checkUserFlag(user?.flags, 'staff')) && <LongButton onClick={async() => {
											const res = await Fetch(`/bots/${data.id}/stats`, { method: 'PATCH'} )
											if(res.code !== 200) return alert(res.message)
											else window.location.reload()
										}}>
											<h4>
												<i className='fas fa-sync' /> ์ •๋ณด ๊ฐฑ์‹ ํ•˜๊ธฐ
											</h4>
										</LongButton>
									}
								</div>
							</div>
							<Divider className='px-5' />
							<div className='hidden lg:block'>
								<Advertisement />
							</div>
							<div className='lg:flex lg:flex-row-reverse' style={bg ? { color: 'white' } : {}}>
								<div className='mb-1 w-full lg:w-1/4'>
									<h2 className='3xl mb-2 font-bold'>์ •๋ณด</h2>
									<div className='grid gap-4 grid-cols-2 px-4 py-4 text-black dark:text-gray-400 dark:bg-discord-black bg-little-white rounded-sm'>
										<div>
											<i className='far fa-flag' /> ์ ‘๋‘์‚ฌ
										</div>
										<div className='markdown-body text-black dark:text-gray-400'>
											<code>{data.prefix}</code>
										</div>
										<div>
											<i className='fas fa-users' /> ์„œ๋ฒ„์ˆ˜
										</div>
										<div>{data.servers || 'N/A'}</div>
										{
											data.shards && data.servers > 1500 && <>
												<div>
													<i className='fas fa-sitemap' /> ์ƒค๋“œ์ˆ˜
												</div>
												<div>{data.shards}</div>
											</>
										}
										<div>
											<i className='fas fa-calendar-day' /> ๋ด‡ ์ƒ์„ฑ์ผ
										</div>
										<div>{Day(date).fromNow(false)}</div>
										{
											checkBotFlag(data.flags, 'verified') ?
												<Tooltip overlay='ํ•ด๋‹น ๋ด‡์€ ๋””์Šค์ฝ”๋“œ์ธก์—์„œ ์ธ์ฆ๋œ ๋ด‡์ž…๋‹ˆ๋‹ค.'>
													<div className='col-span-2'>
														<i className='fas fa-check text-discord-blurple' /> ๋””์Šค์ฝ”๋“œ ์ธ์ฆ๋จ
													</div>
												</Tooltip>
												: ''
										}
									</div>
									<h2 className='3xl mb-2 mt-2 font-bold'>์นดํ…Œ๊ณ ๋ฆฌ</h2>
									<div className='flex flex-wrap'>
										{data.category.map(el => (
											<Tag key={el} text={el} href={`/bots/categories/${el}`} />
										))}
									</div>
									<h2 className='3xl mb-2 mt-2 font-bold'>์ œ์ž‘์ž</h2>
									{(data.owners as User[]).map(el => (
										<Owner
											key={el.id}
											id={el.id}
											tag={el.tag}
											username={el.username}
										/>
									))}
									<div className='list grid'>
										<Link href={`/bots/${router.query.id}/report`}>
											<a className='text-red-600 hover:underline cursor-pointer' aria-hidden='true'>
												<i className='far fa-flag' /> ์‹ ๊ณ ํ•˜๊ธฐ
											</a>
										</Link>
										<Modal header={`${data.name}#${data.tag} ์‹ ๊ณ ํ•˜๊ธฐ`} closeIcon isOpen={reportModal} onClose={() => {
											setReportModal(false)
											setReportRes(null)
										}} full dark={theme === 'dark'}>
											{
												reportRes?.code === 200 ? <Message type='success'>
													<h2 className='text-lg font-semibold'>์„ฑ๊ณต์ ์œผ๋กœ ์‹ ๊ณ ํ•˜์˜€์Šต๋‹ˆ๋‹ค!</h2>
													<p>๋” ์ž์„ธํ•œ ์„ค๋ช…์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! <a className='text-blue-600 hover:text-blue-500' href='/discord'>๊ณต์‹ ๋””์Šค์ฝ”๋“œ</a>์— ์ฐธ์—ฌํ•ด์ฃผ์„ธ์š”</p>
												</Message> : <Formik onSubmit={async (body) => {
													const res = await Fetch(`/bots/${data.id}/report`, { method: 'POST', body: JSON.stringify(body) })
													setReportRes(res)
												}} validationSchema={ReportSchema} initialValues={{
													category: null,
													description: '',
													_csrf: csrfToken
												}}>
													{
														({ errors, touched, values, setFieldValue }) => (
															<Form>
																<div className='mb-5'>
																	{
																		reportRes && <div className='my-5'>
																			<Message type='error'>
																				<h2 className='text-lg font-semibold'>{reportRes.message}</h2>
																				<ul className='list-disc'>
																					{reportRes.errors?.map((el, n) => <li key={n}>{el}</li>)}
																				</ul>
																			</Message>
																		</div>
																	}
																	<h3 className='font-bold'>์‹ ๊ณ  ๊ตฌ๋ถ„</h3>
																	<p className='text-gray-400 text-sm mb-1'>ํ•ด๋‹น๋˜๋Š” ํ•ญ๋ชฉ์„ ์„ ํƒํ•ด์ฃผ์„ธ์š”.</p>
																	{
																		reportCats.map(el => 
																			<div key={el}>
																				<label>
																					<Field type='radio' name='category' value={el} className='mr-1.5 py-2' />
																					{el}
																				</label>
																			</div>
																		)
																	}
																	<div className='mt-1 text-red-500 text-xs font-light'>{errors.category && touched.category ? errors.category : null}</div>
																	<h3 className='font-bold mt-2'>์„ค๋ช…</h3>
																	<p className='text-gray-400 text-sm mb-1'>์‹ ๊ณ ํ•˜์‹œ๋Š” ๋‚ด์šฉ์„ ์ž์„ธํ•˜๊ฒŒ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”.</p>
																	<TextArea name='description' placeholder='์ตœ๋Œ€ํ•œ ์ž์„ธํ•˜๊ฒŒ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”!' theme={theme === 'dark' ? 'dark' : 'light'} value={values.description} setValue={(value) => setFieldValue('description', value)} />
																	<div className='mt-1 text-red-500 text-xs font-light'>{errors.description && touched.description ? errors.description : null}</div>
																</div>
																<div className='text-right'>
																	<Button className='bg-gray-500 hover:opacity-90 text-white' onClick={()=> setReportModal(false)}>์ทจ์†Œ</Button>
																	<Button type='submit' className='bg-red-500 hover:opacity-90 text-white'>์ œ์ถœ</Button>
																</div>
															</Form>
														)
													}
												</Formik>
											}
										</Modal>
										{data.discord && (
											<a
												rel='noopener noreferrer'
												target='_blank'
												className='text-discord-blurple hover:underline'
												href={`https://discord.gg/${data.discord}`}
											>
												<i className='fab fa-discord' />
						๋””์Šค์ฝ”๋“œ ์„œ๋ฒ„
											</a>
										)}
										{data.web && (
											<a
												rel='noopener noreferrer'
												target='_blank'
												className='text-blue-500 hover:underline'
												href={data.web}
											>
												<i className='fas fa-globe' />
						์›น์‚ฌ์ดํŠธ
											</a>
										)}
										{data.git && (
											<a
												rel='noopener noreferrer'
												target='_blank'
												className='hover:underline'
												href={data.git}
											>
												<i className={`fab fa-${git[new URL(data.git).hostname]?.icon ?? 'git-alt'}`} />
												{git[new URL(data.git).hostname]?.text ?? 'Git'}
											</a>
										)}
									</div>
									<Advertisement size='tall' />
								</div>
								<div className='w-full lg:pr-5 lg:w-3/4'>
									{
										checkBotFlag(data.flags, 'hackerthon') ? <Segment className='mt-10'>
											<h1 className='text-3xl font-semibold'>
												<i className='fas fa-trophy mr-4 my-2 text-yellow-300' /> ํ•ด๋‹น ๋ด‡์€ ํ•œ๊ตญ ๋””์Šค์ฝ”๋“œ ๋ฆฌ์ŠคํŠธ ํ•ด์ปคํ†ค ์ˆ˜์ƒ์ž‘ํ’ˆ์ž…๋‹ˆ๋‹ค!
											</h1>
											<p>ํ•ด๋‹น ๋ด‡์€ ํ•œ๊ตญ ๋””์Šค์ฝ”๋“œ ๋ฆฌ์ŠคํŠธ ์ฃผ์ตœ๋กœ ์ง„ํ–‰๋˜์—ˆ๋˜ "ํ•œ๊ตญ ๋””์Šค์ฝ”๋“œ ๋ฆฌ์ŠคํŠธ ์ œ1ํšŒ ํ•ด์ปคํ†ค"์—์„œ ์šฐ์ˆ˜ํ•œ ์„ฑ์ ์„ ๊ฑฐ๋‘” ๋ด‡์ž…๋‹ˆ๋‹ค.</p>
											<p>์ž์„ธํ•œ ๋‚ด์šฉ์€ <a className='text-blue-500 hover:text-blue-400' href='https://blog.koreanbots.dev/first-hackathon-results/'>ํ•ด๋‹น ๊ธ€</a>์„ ํ™•์ธํ•ด์ฃผ์„ธ์š”.</p>
										</Segment> : ''
									}
									<Segment className='my-4'>
										<Markdown text={desc}/>
									</Segment>
									<Advertisement />
								</div>
							</div>
						</>
			}
		</Container>
	</div>
}
Example #24
Source File: index.tsx    From formik-chakra-ui with MIT License 4 votes vote down vote up
App = () => {
  return (
    <ChakraProvider>
      <Heading as="h1" size="xl" textAlign="center">
        Formik Chakra UI
      </Heading>
      <Box as="p" textAlign="center">
        Example using{' '}
        <Link href="https://github.com/kgnugur/formik-chakra-ui" isExternal>
          Formik Chakra UI{' '}
        </Link>
      </Box>

      <Formik
        initialValues={initialValues}
        onSubmit={onSubmit}
        validationSchema={validationSchema}
      >
        {({ handleSubmit, values, errors }) => (
          <Stack
            spacing={5}
            borderWidth="1px"
            rounded="lg"
            shadow="1px 1px 3px rgba(0,0,0,0.3)"
            maxWidth={800}
            p={6}
            m="10px auto"
            as="form"
            onSubmit={handleSubmit as any}
          >
            <InputControl name="firstName" label="First Name" />
            <InputControl name="lastName" label="Last Name" />
            <NumberInputControl
              name="age"
              label="Age"
              helperText="Helper text"
            />
            <CheckboxSingleControl name="employed">
              Employed
            </CheckboxSingleControl>
            <RadioGroupControl name="favoriteColor" label="Favorite Color">
              <Radio value="#ff0000">Red</Radio>
              <Radio value="#00ff00">Green</Radio>
              <Radio value="#0000ff">Blue</Radio>
            </RadioGroupControl>
            <CheckboxContainer name="toppings" label="Toppings">
              <CheckboxControl name="toppings1" value="chicken">
                Chicken
              </CheckboxControl>
              <CheckboxControl name="toppings" value="ham">
                Ham
              </CheckboxControl>
              <CheckboxControl name="toppings" value="mushrooms">
                Mushrooms
              </CheckboxControl>
              <CheckboxControl name="toppings" value="cheese">
                Cheese
              </CheckboxControl>
              <CheckboxControl name="toppings" value="tuna">
                Tuna
              </CheckboxControl>
              <CheckboxControl name="toppings" value="pineapple">
                Pineapple
              </CheckboxControl>
            </CheckboxContainer>
            <TextareaControl name="notes" label="Notes" />
            <SwitchControl name="employedd" label="Employed" />
            <SelectControl
              label="Select label"
              name="select"
              selectProps={{ placeholder: 'Select option' }}
            >
              <option value="option1">Option 1</option>
              <option value="option2">Option 2</option>
              <option value="option3">Option 3</option>
            </SelectControl>
            <SliderControl name="foo" sliderProps={{ max: 40 }} />
            <PinInputControl
              name="bar"
              pinAmount={4}
              pinInputProps={{ size: 'sm' }}
            />

            <PercentComplete />
            <FormControl
              name="customField"
              label="Custom FormControl"
              helperText="Helper text"
            >
              <Field
                as={Input}
                name="customField"
                placeholder="A custom field"
              />
            </FormControl>
            <InputControl
              name="customElements"
              label="Custom elements"
              labelProps={{ color: 'blue' }}
              errorMessageProps={{ fontWeight: 'bold' }}
              helperText="Helper text"
              helperTextProps={{ fontStyle: 'italic' }}
            />
            <ButtonGroup>
              <SubmitButton>Submit</SubmitButton>
              <ResetButton>Reset</ResetButton>
            </ButtonGroup>

            <Box as="pre" marginY={10}>
              {JSON.stringify(values, null, 2)}
              <br />
              {JSON.stringify(errors, null, 2)}
            </Box>
          </Stack>
        )}
      </Formik>
    </ChakraProvider>
  );
}
Example #25
Source File: AddAttachment.tsx    From glific-frontend with GNU Affero General Public License v3.0 4 votes vote down vote up
AddAttachment: React.FC<AddAttachmentPropTypes> = ({
  setAttachment,
  setAttachmentAdded,
  setAttachmentURL,
  setAttachmentType,
  attachmentURL,
  attachmentType,
  uploadPermission,
}: AddAttachmentPropTypes) => {
  const [errors, setErrors] = useState<any>(null);
  const [uploading, setUploading] = useState(false);
  const [fileName, setFileName] = useState<null | string>(null);
  const [verifying, setVerifying] = useState(false);
  const [uploadDisabled] = useState(!uploadPermission);

  const { t } = useTranslation();

  const [uploadMedia] = useMutation(UPLOAD_MEDIA, {
    onCompleted: (data: any) => {
      setAttachmentURL(data.uploadMedia);
      setUploading(false);
    },
    onError: () => {
      setUploading(false);
    },
  });

  const validateURL = () => {
    if (attachmentURL && attachmentType) {
      setVerifying(true);
      setErrors(null);

      validateMedia(attachmentURL, attachmentType)
        .then((response: any) => {
          if (!response.data.is_valid) {
            setVerifying(false);
            setErrors(response.data.message);
          } else if (response.data.is_valid) {
            setVerifying(false);
            setAttachmentAdded(true);

            setErrors(null);
          }
        })
        .catch((error) => {
          setLogs(error, 'error');
        });
    }
  };

  useEffect(() => {
    validateURL();
  }, [attachmentURL, attachmentType]);

  const helperText = (
    <div className={styles.HelperText}>
      {t('Please wait for the attachment URL verification')}
      <CircularProgress className={styles.ProgressIcon} />
    </div>
  );
  let timer: any = null;
  const input = {
    component: Input,
    name: 'attachmentURL',
    type: 'text',
    placeholder: t('Attachment URL'),
    helperText: verifying && helperText,
    disabled: fileName !== null,
    inputProp: {
      onBlur: (event: any) => {
        setAttachmentURL(event.target.value);
      },
      onChange: (event: any) => {
        clearTimeout(timer);
        timer = setTimeout(() => setAttachmentURL(event.target.value), 1000);
      },
    },
  };

  let formFieldItems: any = [
    {
      component: Dropdown,
      options,
      name: 'attachmentType',
      placeholder: 'Type',
      fieldValue: attachmentType,
      fieldChange: (event: any) => {
        setAttachmentType(event?.target.value);
        setErrors(null);
      },
    },
  ];

  formFieldItems = attachmentType !== '' ? [...formFieldItems, input] : formFieldItems;

  const validationSchema = Yup.object().shape({
    attachmentType: Yup.string().required(t('Type is required.')),
    attachmentURL: Yup.string().required(t('URL is required.')),
  });

  const displayWarning = () => {
    if (attachmentType === 'STICKER') {
      return (
        <div className={styles.FormHelperText}>
          <ol>
            <li>{t('Animated stickers are not supported.')}</li>
            <li>{t('Captions along with stickers are not supported.')}</li>
          </ol>
        </div>
      );
    }
    return (
      <div className={styles.FormHelperText}>
        <ol>
          <li>{t('Captions along with audio are not supported.')}</li>
        </ol>
      </div>
    );
  };

  const onSubmitHandle = (itemData: { attachmentURL: any; attachmentType: any }) => {
    setAttachmentType(itemData.attachmentType);
    setAttachmentURL(itemData.attachmentURL);
    setAttachment(false);
  };

  const addAttachment = (event: any) => {
    const media = event.target.files[0];

    if (media) {
      const mediaName = media.name;
      const extension = mediaName.slice((Math.max(0, mediaName.lastIndexOf('.')) || Infinity) + 1);
      const shortenedName = mediaName.length > 15 ? `${mediaName.slice(0, 15)}...` : mediaName;
      setFileName(shortenedName);
      setUploading(true);
      uploadMedia({
        variables: {
          media,
          extension,
        },
      });
    }
  };

  const form = (
    <Formik
      enableReinitialize
      initialValues={{ attachmentURL, attachmentType }}
      validationSchema={validationSchema}
      onSubmit={(itemData) => {
        if (!errors) {
          onSubmitHandle(itemData);
        }
      }}
    >
      {({ submitForm }) => (
        <Form className={styles.Form} data-testid="formLayout" encType="multipart/form-data">
          <DialogBox
            titleAlign="left"
            title={t('Add attachments to message')}
            handleOk={() => {
              submitForm();
            }}
            handleCancel={() => {
              setAttachment(false);
              setAttachmentType('');
              setAttachmentURL('');
              setAttachmentAdded(false);
            }}
            buttonOk={t('Add')}
            alignButtons="left"
            disableOk={verifying}
          >
            <div className={styles.DialogContent} data-testid="attachmentDialog">
              {formFieldItems.map((field: any) => (
                <Field {...field} key={field.name} validateURL={errors} />
              ))}
              {attachmentType !== '' && (
                <div className={styles.CrossIcon}>
                  <CrossIcon
                    data-testid="crossIcon"
                    onClick={() => {
                      setAttachmentType('');
                      setAttachmentURL('');
                      setAttachmentAdded(false);
                      setErrors(null);
                      setFileName(null);
                    }}
                  />
                </div>
              )}
              <div className={styles.FormError}>{errors}</div>
            </div>
            {attachmentType !== '' && (
              <>
                <div className={styles.UploadContainer}>
                  <label
                    className={`${uploadDisabled ? styles.UploadDisabled : styles.UploadEnabled} ${
                      fileName && attachmentURL ? styles.Uploaded : ''
                    }`}
                    htmlFor="uploadFile"
                  >
                    {!uploadPermission && <AlertIcon className={styles.AlertIcon} />}
                    <span>
                      {fileName !== null ? (
                        fileName
                      ) : (
                        <>
                          <UploadIcon className={styles.UploadIcon} /> Upload File
                        </>
                      )}

                      <input
                        type="file"
                        id="uploadFile"
                        data-testid="uploadFile"
                        onClick={(event) => {
                          if (uploadDisabled) {
                            event.preventDefault();
                          }
                        }}
                        onChange={(event) => {
                          addAttachment(event);
                        }}
                      />
                    </span>
                  </label>
                </div>
                {uploading && <div className={styles.WaitUpload}>Please wait for upload</div>}
              </>
            )}
            {!uploadPermission && attachmentType !== '' && (
              <div className={styles.FormHelperText}>
                {t('Please integrate Google Cloud Storage to use the upload')}
              </div>
            )}
            {attachmentType === 'STICKER' || attachmentType === 'AUDIO' ? displayWarning() : null}
          </DialogBox>
        </Form>
      )}
    </Formik>
  );

  return form;
}
Example #26
Source File: report.tsx    From core with GNU Affero General Public License v3.0 4 votes vote down vote up
ReportBot: NextPage<ReportBotProps> = ({ data, user, csrfToken }) => {
	const [ reportRes, setReportRes ] = useState<ResponseProps<unknown>>(null)
	if(!data?.id) return <NotFound />
	if(!user) return <Login>
		<NextSeo title='์‹ ๊ณ ํ•˜๊ธฐ' />
	</Login>
	return <Container paddingTop className='py-10'>
		<NextSeo title={`${data.name} ์‹ ๊ณ ํ•˜๊ธฐ`} />
		<Link href={makeBotURL(data)}>
			<a className='text-blue-500 hover:opacity-80'><i className='fas fa-arrow-left mt-3 mb-3' /> <strong>{data.name}</strong>{getJosaPicker('๋กœ')(data.name)} ๋Œ์•„๊ฐ€๊ธฐ</a>
		</Link>
		{
			reportRes?.code === 200 ? <Message type='success'>
				<h2 className='text-lg font-semibold'>์„ฑ๊ณต์ ์œผ๋กœ ์ œ์ถœํ•˜์˜€์Šต๋‹ˆ๋‹ค!</h2>
				<p>๋” ์ž์„ธํ•œ ์„ค๋ช…์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. <strong>๋ฐ˜๋“œ์‹œ <a className='text-blue-600 hover:text-blue-500' href='/discord'>๊ณต์‹ ๋””์Šค์ฝ”๋“œ</a>์— ์ฐธ์—ฌํ•ด์ฃผ์„ธ์š”!!</strong></p>
			</Message> : <Formik onSubmit={async (body) => {
				const res = await Fetch(`/bots/${data.id}/report`, { method: 'POST', body: JSON.stringify(body) })
				setReportRes(res)
			}} validationSchema={ReportSchema} initialValues={{
				category: null,
				description: '',
				_csrf: csrfToken
			}}>
				{
					({ errors, touched, values, setFieldValue }) => (
						<Form>
							<div className='mb-5'>
								{
									reportRes && <div className='my-5'>
										<Message type='error'>
											<h2 className='text-lg font-semibold'>{reportRes.message}</h2>
											<ul className='list-disc'>
												{reportRes.errors?.map((el, n) => <li key={n}>{el}</li>)}
											</ul>
										</Message>
									</div>
								}
								<h3 className='font-bold'>์‹ ๊ณ  ๊ตฌ๋ถ„</h3>
								<p className='text-gray-400 text-sm mb-1'>ํ•ด๋‹น๋˜๋Š” ํ•ญ๋ชฉ์„ ์„ ํƒํ•ด์ฃผ์„ธ์š”.</p>
								{
									reportCats.map(el => 
										<div key={el}>
											<label>
												<Field type='radio' name='category' value={el} className='mr-1.5 py-2' />
												{el}
											</label>
										</div>
									)
								}
								<div className='mt-1 text-red-500 text-xs font-light'>{errors.category && touched.category ? errors.category : null}</div>
								{
									values.category && <>
										{
											{
												[reportCats[2]]: <Message type='info'>
													<h3 className='font-bold text-xl'>๋ณธ์ธ ํ˜น์€ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ์œ„ํ—˜์— ์ฒ˜ํ•ด ์žˆ๋‚˜์š”?</h3>
													<p>๋‹น์‹ ์€ ์†Œ์ค‘ํ•œ ์‚ฌ๋žŒ์ž…๋‹ˆ๋‹ค.</p>
													<p className='list-disc list-item list-inside'>์ž์‚ด์˜ˆ๋ฐฉ์ƒ๋‹ด์ „ํ™” 1393 | ์ฒญ์†Œ๋…„์ „ํ™” 1388</p>
												</Message>,
												[reportCats[5]]: <DMCA values={values} errors={errors} touched={touched} setFieldValue={setFieldValue} />,
												[reportCats[6]]: <Message type='warning'>
													<h3 className='font-bold text-xl'>๋””์Šค์ฝ”๋“œ ์•ฝ๊ด€์„ ์œ„๋ฐ˜์‚ฌํ•ญ์„ ์‹ ๊ณ ํ•˜์‹œ๋ ค๊ณ ์š”?</h3>
													<p><a className='text-blue-400' target='_blank' rel='noreferrer' href='http://dis.gd/report'>๋””์Šค์ฝ”๋“œ ๋ฌธ์˜</a>๋ฅผ ํ†ตํ•ด ์ง์ ‘ ๋””์Šค์ฝ”๋“œ์— ์‹ ๊ณ ํ•˜์‹ค ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.</p>
												</Message>
                        
											}[values.category]
										}
										{
											!['์˜คํ”ˆ์†Œ์Šค ๋ผ์ด์„ ์Šค, ์ €์ž‘๊ถŒ ์œ„๋ฐ˜ ๋“ฑ ๊ถŒ๋ฆฌ ์นจํ•ด'].includes(values.category) && <>
												<h3 className='font-bold mt-2'>์„ค๋ช…</h3>
												<p className='text-gray-400 text-sm mb-1'>์ตœ๋Œ€ํ•œ ์ž์„ธํ•˜๊ฒŒ ๊ธฐ์žฌํ•ด์ฃผ์„ธ์š”.</p>
												<TextField values={values} errors={errors} touched={touched} setFieldValue={setFieldValue} />
											</>
										}
									</>
								}
							</div>
						</Form>
					)
				}
			</Formik>
		}
	</Container>
}
Example #27
Source File: Billing.tsx    From glific-frontend with GNU Affero General Public License v3.0 4 votes vote down vote up
BillingForm: React.FC<BillingProps> = () => {
  const stripe = useStripe();
  const elements = useElements();

  const [name, setName] = useState('');
  const [email, setEmail] = useState('');

  const [loading, setLoading] = useState(false);
  const [disable, setDisable] = useState(false);
  const [paymentMethodId, setPaymentMethodId] = useState('');
  const [cardError, setCardError] = useState<any>('');
  const [alreadySubscribed, setAlreadySubscribed] = useState(false);
  const [pending, setPending] = useState(false);
  const [couponApplied, setCouponApplied] = useState(false);
  const [coupon] = useState('');

  const { t } = useTranslation();

  const validationSchema = Yup.object().shape({
    name: Yup.string().required(t('Name is required.')),
    email: Yup.string().email().required(t('Email is required.')),
  });

  // get organization billing details
  const {
    data: billData,
    loading: billLoading,
    refetch,
  } = useQuery(GET_ORGANIZATION_BILLING, {
    fetchPolicy: 'network-only',
  });

  const [getCouponCode, { data: couponCode, loading: couponLoading, error: couponError }] =
    useLazyQuery(GET_COUPON_CODE, {
      onCompleted: ({ getCouponCode: couponCodeResult }) => {
        if (couponCodeResult.code) {
          setCouponApplied(true);
        }
      },
    });
  const [getCustomerPortal, { loading: portalLoading }] = useLazyQuery(GET_CUSTOMER_PORTAL, {
    fetchPolicy: 'network-only',
    onCompleted: (customerPortal: any) => {
      window.open(customerPortal.customerPortal.url, '_blank');
    },
  });

  const formFieldItems = [
    {
      component: Input,
      name: 'name',
      type: 'text',
      placeholder: 'Your Organization Name',
      disabled: alreadySubscribed || pending || disable,
    },
    {
      component: Input,
      name: 'email',
      type: 'text',
      placeholder: 'Email ID',
      disabled: alreadySubscribed || pending || disable,
    },
  ];

  useEffect(() => {
    // Set name and email if a customer is already created
    if (billData && billData.getOrganizationBilling?.billing) {
      const billing = billData.getOrganizationBilling?.billing;
      setName(billing?.name);
      setEmail(billing?.email);

      if (billing?.stripeSubscriptionStatus === null) {
        setPending(false);
      }
    }
  }, [billData]);

  const [updateBilling] = useMutation(UPDATE_BILLING);
  const [createBilling] = useMutation(CREATE_BILLING);

  const [createSubscription] = useMutation(CREATE_BILLING_SUBSCRIPTION, {
    onCompleted: (data) => {
      const result = JSON.parse(data.createBillingSubscription.subscription);
      // needs additional security (3d secure)
      if (result.status === 'pending') {
        if (stripe) {
          stripe
            .confirmCardSetup(result.client_secret, {
              payment_method: paymentMethodId,
            })
            .then((securityResult: any) => {
              if (securityResult.error?.message) {
                setNotification(securityResult.error?.message, 'warning');
                setLoading(false);
                refetch().then(({ data: refetchedData }) => {
                  updateBilling({
                    variables: {
                      id: refetchedData.getOrganizationBilling?.billing?.id,
                      input: {
                        stripeSubscriptionId: null,
                        stripeSubscriptionStatus: null,
                      },
                    },
                  }).then(() => {
                    refetch();
                  });
                });
              } else if (securityResult.setupIntent.status === 'succeeded') {
                setDisable(true);
                setLoading(false);
                setNotification('Your billing account is setup successfully');
              }
            });
        }
      } // successful subscription
      else if (result.status === 'active') {
        refetch();
        setDisable(true);
        setLoading(false);
        setNotification('Your billing account is setup successfully');
      }
    },
    onError: (error) => {
      refetch();
      setNotification(error.message, 'warning');
      setLoading(false);
    },
  });

  if (billLoading || portalLoading) {
    return <Loading />;
  }

  // check if the organization is already subscribed or in pending state
  if (billData && !alreadySubscribed && !pending) {
    const billingDetails = billData.getOrganizationBilling?.billing;
    if (billingDetails) {
      const { stripeSubscriptionId, stripeSubscriptionStatus } = billingDetails;
      if (stripeSubscriptionId && stripeSubscriptionStatus === 'pending') {
        setPending(true);
      } else if (stripeSubscriptionId && stripeSubscriptionStatus === 'active') {
        setAlreadySubscribed(true);
      }
    }
  }

  const stripePayment = async () => {
    if (!stripe || !elements) {
      // Stripe.js has not loaded yet. Make sure to disable
      // form submission until Stripe.js has loaded.
      return;
    }

    // Get a reference to a mounted CardElement. Elements knows how
    // to find your CardElement because there can only ever be one of
    // each type of element.
    const cardElement: any = elements.getElement(CardElement);

    // create a payment method
    const { error, paymentMethod } = await stripe.createPaymentMethod({
      type: 'card',
      card: cardElement,
    });

    if (error) {
      setLoading(false);
      refetch();
      setNotification(error.message ? error.message : 'An error occurred', 'warning');
    } else if (paymentMethod) {
      setPaymentMethodId(paymentMethod.id);

      const variables: any = {
        stripePaymentMethodId: paymentMethod.id,
      };

      if (couponApplied) {
        variables.couponCode = couponCode.getCouponCode.id;
      }

      await createSubscription({
        variables,
      });
    }
  };

  const handleSubmit = async (itemData: any) => {
    const { name: billingName, email: billingEmail } = itemData;
    setLoading(true);

    if (billData) {
      const billingDetails = billData.getOrganizationBilling?.billing;
      if (billingDetails) {
        // Check if customer needs to be updated
        if (billingDetails.name !== billingName || billingDetails.email !== billingEmail) {
          updateBilling({
            variables: {
              id: billingDetails.id,
              input: {
                name: billingName,
                email: billingEmail,
                currency: 'inr',
              },
            },
          })
            .then(() => {
              stripePayment();
            })
            .catch((error) => {
              setNotification(error.message, 'warning');
            });
        } else {
          stripePayment();
        }
      } else {
        // There is no customer created. Creating a customer first
        createBilling({
          variables: {
            input: {
              name: billingName,
              email: billingEmail,
              currency: 'inr',
            },
          },
        })
          .then(() => {
            stripePayment();
          })
          .catch((error) => {
            setNotification(error.message, 'warning');
          });
      }
    }
  };

  const backLink = (
    <div className={styles.BackLink}>
      <Link to="/settings">
        <BackIcon />
        Back to settings
      </Link>
    </div>
  );

  const cardElements = (
    <>
      <CardElement
        options={{ hidePostalCode: true }}
        className={styles.Card}
        onChange={(e) => {
          setCardError(e.error?.message);
        }}
      />
      <div className={styles.Error}>
        <small>{cardError}</small>
      </div>
      <div className={styles.Helper}>
        <small>Once subscribed you will be charged on basis of your usage automatically</small>
      </div>
    </>
  );

  const subscribed = (
    <div>
      <div className={styles.Subscribed}>
        <ApprovedIcon />
        You have an active subscription
        <div>
          Please <span>contact us</span> to deactivate
          <br />
          *Note that we do not store your credit card details, as Stripe securely does.
        </div>
      </div>

      <div
        aria-hidden
        className={styles.Portal}
        data-testid="customerPortalButton"
        onClick={() => {
          getCustomerPortal();
        }}
      >
        Visit Stripe portal <CallMadeIcon />
      </div>
    </div>
  );
  let paymentBody = alreadySubscribed || disable ? subscribed : cardElements;

  if (pending) {
    paymentBody = (
      <div>
        <div className={styles.Pending}>
          <PendingIcon className={styles.PendingIcon} />
          Your payment is in pending state
        </div>
        <div
          aria-hidden
          className={styles.Portal}
          data-testid="customerPortalButton"
          onClick={() => {
            getCustomerPortal();
          }}
        >
          Visit Stripe portal <CallMadeIcon />
        </div>
      </div>
    );
  }

  const couponDescription = couponCode && JSON.parse(couponCode.getCouponCode.metadata);
  const processIncomplete = !alreadySubscribed && !pending && !disable;
  return (
    <div className={styles.Form}>
      <Typography variant="h5" className={styles.Title}>
        <IconButton disabled className={styles.Icon}>
          <Settingicon />
        </IconButton>
        Billing
      </Typography>
      {backLink}
      <div className={styles.Description}>
        <div className={styles.UpperSection}>
          <div className={styles.Setup}>
            <div>
              <div className={styles.Heading}>One time setup</div>
              <div className={styles.Pricing}>
                <span>INR 15000</span> ($220)
              </div>
              <div className={styles.Pricing}>+ taxes</div>
              <ul className={styles.List}>
                <li>5hr consulting</li>
                <li>1 hr onboarding session</li>
              </ul>
            </div>
            <div>
              <div className={styles.Heading}>Monthly Recurring</div>
              <div className={styles.Pricing}>
                <span>INR 7,500</span> ($110)
              </div>
              <div className={styles.Pricing}>+ taxes</div>
              <ul className={styles.List}>
                <li>upto 250k messages</li>
                <li>1-10 users</li>
              </ul>
            </div>
          </div>
          <div className={styles.Additional}>
            <div className={styles.Heading}>Variable charges as usage increases</div>
            <div>For every staff member over 10 users โ€“ INR 150 ($2)</div>
            <div>For every 1K messages upto 1Mn messages โ€“ INR 10 ($0.14)</div>
            <div>For every 1K messages over 1Mn messages โ€“ INR 5 ($0.07)</div>
          </div>
        </div>
        <div className={styles.DottedSpaced} />
        <div className={styles.BottomSection}>
          <div className={styles.InactiveHeading}>
            Suspended or inactive accounts:{' '}
            <span className={styles.Amount}> INR 4,500/mo + taxes</span>
          </div>
        </div>
      </div>

      {couponApplied && (
        <div className={styles.CouponDescription}>
          <div className={styles.CouponHeading}>Coupon Applied!</div>
          <div>{couponDescription.description}</div>
        </div>
      )}

      {processIncomplete && couponError && (
        <div className={styles.CouponError}>
          <div>Invalid Coupon!</div>
        </div>
      )}

      <div>
        <Formik
          enableReinitialize
          validateOnBlur={false}
          initialValues={{
            name,
            email,
            coupon,
          }}
          validationSchema={validationSchema}
          onSubmit={(itemData) => {
            handleSubmit(itemData);
          }}
        >
          {({ values, setFieldError, setFieldTouched }) => (
            <Form>
              {processIncomplete && (
                <Field
                  component={Input}
                  name="coupon"
                  type="text"
                  placeholder="Coupon Code"
                  disabled={couponApplied}
                  endAdornment={
                    <InputAdornment position="end">
                      {couponLoading ? (
                        <CircularProgress />
                      ) : (
                        <div
                          aria-hidden
                          className={styles.Apply}
                          onClick={() => {
                            if (values.coupon === '') {
                              setFieldError('coupon', 'Please input coupon code');
                              setFieldTouched('coupon');
                            } else {
                              getCouponCode({ variables: { code: values.coupon } });
                            }
                          }}
                        >
                          {couponApplied ? (
                            <CancelOutlinedIcon
                              className={styles.CrossIcon}
                              onClick={() => setCouponApplied(false)}
                            />
                          ) : (
                            ' APPLY'
                          )}
                        </div>
                      )}
                    </InputAdornment>
                  }
                />
              )}
              {formFieldItems.map((field, index) => {
                const key = index;
                return <Field key={key} {...field} />;
              })}

              {paymentBody}

              {processIncomplete && (
                <Button
                  variant="contained"
                  data-testid="submitButton"
                  color="primary"
                  type="submit"
                  className={styles.Button}
                  disabled={!stripe || disable}
                  loading={loading}
                >
                  Subscribe for monthly billing
                </Button>
              )}
            </Form>
          )}
        </Formik>
      </div>
    </div>
  );
}
Example #28
Source File: report.tsx    From core with GNU Affero General Public License v3.0 4 votes vote down vote up
ReportUser: NextPage<ReportUserProps> = ({ data, user, csrfToken }) => {
	const [ reportRes, setReportRes ] = useState<ResponseProps<unknown>>(null)
	if(!data?.id) return <NotFound />
	if(!user) return <Login>
		<NextSeo title='์‹ ๊ณ ํ•˜๊ธฐ' />
	</Login>
	if(user?.id === data.id) return <>
		<div className='flex items-center justify-center h-screen select-none'>
			<div className='container mx-auto px-20 md:text-left text-center'>
				<h1 className='text-6xl font-semibold'>์ €๋Ÿฐ..!</h1>
				<p className='text-gray-400 text-lg mt-2'>์œ ๊ฐ์Šค๋Ÿฝ๊ฒŒ๋„ ์ž๊ธฐ ์ž์‹ ์€ ์‹ ๊ณ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.</p>
			</div>
		</div>
	</>
	return <Container paddingTop className='py-10'>
		<NextSeo title={`${data.username} ์‹ ๊ณ ํ•˜๊ธฐ`} />
		<Link href={makeUserURL(data)}>
			<a className='text-blue-500 hover:opacity-80'><i className='fas fa-arrow-left mt-3 mb-3' /> <strong>{data.username}</strong>{getJosaPicker('๋กœ')(data.username)} ๋Œ์•„๊ฐ€๊ธฐ</a>
		</Link>
		{
			reportRes?.code === 200 ? <Message type='success'>
				<h2 className='text-lg font-semibold'>์„ฑ๊ณต์ ์œผ๋กœ ์ œ์ถœํ•˜์˜€์Šต๋‹ˆ๋‹ค!</h2>
				<p>๋” ์ž์„ธํ•œ ์„ค๋ช…์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. <strong>๋ฐ˜๋“œ์‹œ <a className='text-blue-600 hover:text-blue-500' href='/discord'>๊ณต์‹ ๋””์Šค์ฝ”๋“œ</a>์— ์ฐธ์—ฌํ•ด์ฃผ์„ธ์š”!!</strong></p>
			</Message> : <Formik onSubmit={async (body) => {
				const res = await Fetch(`/users/${data.id}/report`, { method: 'POST', body: JSON.stringify(body) })
				setReportRes(res)
			}} validationSchema={ReportSchema} initialValues={{
				category: null,
				description: '',
				_csrf: csrfToken
			}}>
				{
					({ errors, touched, values, setFieldValue }) => (
						<Form>
							<div className='mb-5'>
								{
									reportRes && <div className='my-5'>
										<Message type='error'>
											<h2 className='text-lg font-semibold'>{reportRes.message}</h2>
											<ul className='list-disc'>
												{reportRes.errors?.map((el, n) => <li key={n}>{el}</li>)}
											</ul>
										</Message>
									</div>
								}
								<h3 className='font-bold'>์‹ ๊ณ  ๊ตฌ๋ถ„</h3>
								<p className='text-gray-400 text-sm mb-1'>ํ•ด๋‹น๋˜๋Š” ํ•ญ๋ชฉ์„ ์„ ํƒํ•ด์ฃผ์„ธ์š”.</p>
								{
									reportCats.map(el => 
										<div key={el}>
											<label>
												<Field type='radio' name='category' value={el} className='mr-1.5 py-2' />
												{el}
											</label>
										</div>
									)
								}
								<div className='mt-1 text-red-500 text-xs font-light'>{errors.category && touched.category ? errors.category : null}</div>
								{
									values.category && <>
										{
											values.category === '์˜คํ”ˆ์†Œ์Šค ๋ผ์ด์„ ์Šค, ์ €์ž‘๊ถŒ ์œ„๋ฐ˜ ๋“ฑ ๊ถŒ๋ฆฌ ์นจํ•ด' ? <DMCA values={values} errors={errors} touched={touched} setFieldValue={setFieldValue} /> :
												values.category === '๊ดด๋กญํž˜, ๋ชจ์š•, ๋ช…์˜ˆํ›ผ์†' ? <>
													<Message type='info'>
														<h3 className='font-bold text-xl'>๋ณธ์ธ ํ˜น์€ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ์œ„ํ—˜์— ์ฒ˜ํ•ด ์žˆ๋‚˜์š”?</h3>
														<p>๋‹น์‹ ์€ ์†Œ์ค‘ํ•œ ์‚ฌ๋žŒ์ž…๋‹ˆ๋‹ค.</p>
														<p className='list-disc list-item list-inside'>์ž์‚ด์˜ˆ๋ฐฉ์ƒ๋‹ด์ „ํ™” 1393 | ์ฒญ์†Œ๋…„์ „ํ™” 1388</p>
													</Message>
												</> : ''
										}
										{
											!['์˜คํ”ˆ์†Œ์Šค ๋ผ์ด์„ ์Šค, ์ €์ž‘๊ถŒ ์œ„๋ฐ˜ ๋“ฑ ๊ถŒ๋ฆฌ ์นจํ•ด'].includes(values.category) && <>
												<h3 className='font-bold mt-2'>์„ค๋ช…</h3>
												<p className='text-gray-400 text-sm mb-1'>์ตœ๋Œ€ํ•œ ์ž์„ธํ•˜๊ฒŒ ๊ธฐ์žฌํ•ด์ฃผ์„ธ์š”.</p>
												<TextField values={values} errors={errors} touched={touched} setFieldValue={setFieldValue} />
											</>
										}
									</>
								}
							</div>
						</Form>
					)
				}
			</Formik>
		}
	</Container>
}
Example #29
Source File: Register.tsx    From krmanga with MIT License 4 votes vote down vote up
function Register({ navigation, dispatch, isLogin, loading }: IProps) {

    const [disabled, setDisabled] = useState<boolean>(false);

    useEffect(() => {
        if (isLogin) {
            setTimeout(() => {
                navigation.goBack();
            }, 100);
        }
    }, [isLogin]);

    const onSubmit = (values: Values) => {

        if (disabled || loading) {
            return;
        }

        setDisabled(true);

        dispatch({
            type: "user/register",
            payload: values,
            callback: () => {
                setDisabled(false);
            }
        });
    };


    const cancel = (form: FormikProps<string>, field: FieldInputProps<string>) => {
        if (field.name === "account") {
            form.setFieldValue("account", "");
        } else if (field.name === "password") {
            form.setFieldValue("password", "");
        } else if (field.name === "repeat_password") {
            form.setFieldValue("repeat_password", "");
        } else if (field.name === "phone") {
            form.setFieldValue("phone", "");
        }
    };

    return (
        <ScrollView keyboardShouldPersistTaps="handled" style={styles.container}>
            <Formik
                initialValues={initialValues}
                onSubmit={onSubmit}
                validationSchema={customerValidation}>
                {({ handleSubmit }) => (
                    <View>
                        <Field
                            name="account"
                            placeholder="่ฏท่พ“ๅ…ฅ็”จๆˆทๅ"
                            component={Input}
                            iconName={"icon-Account"}
                            cancel={cancel}
                        />
                        <Field
                            name="password"
                            placeholder="่ฏท่พ“ๅ…ฅๅฏ†็ "
                            component={Input}
                            iconName={"icon-mima"}
                            secureTextEntry
                            cancel={cancel}
                        />
                        <Field
                            name="repeat_password"
                            placeholder="่ฏทๅ†่พ“ๅ…ฅๅฏ†็ "
                            component={Input}
                            iconName={"icon-mima"}
                            secureTextEntry
                            cancel={cancel}
                        />
                        <Field
                            name="phone"
                            placeholder="่ฏท่พ“ๅ…ฅๆ‰‹ๆœบๅท(้€‰ๅกซ)"
                            component={Input}
                            iconName={"icon-mobile-phone"}
                            cancel={cancel}
                        />
                        <View style={styles.jumpView}>
                            <Text style={styles.jumpTitle}>ๅฟ˜่ฎฐๅฏ†็ ?</Text>
                            <Touchable onPress={() => navigation.navigate("Login")}>
                                <Text style={styles.jumpTitle}>็ซ‹ๅณ็™ปๅฝ•</Text>
                            </Touchable>
                        </View>
                        <Touchable disabled={disabled} onPress={handleSubmit} style={styles.login}>
                            <Text style={styles.loginText}>ๆณจๅ†Œ</Text>
                        </Touchable>
                    </View>
                )}
            </Formik>
        </ScrollView>
    );
}