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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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>
);
}