-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #57 from clean-commit/1.2.0
Forms components added
- Loading branch information
Showing
14 changed files
with
399 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import React from 'react' | ||
import Form from '@/components/Form/Form' | ||
|
||
export default class PagePreview extends React.Component { | ||
render() { | ||
const blocks = this.props.widgetsFor('rows').toJS() | ||
let blocksUpdated = [] | ||
let hasBlocks = Array.isArray(blocks) | ||
if (hasBlocks) { | ||
blocksUpdated = blocks.map((block) => block.data) | ||
} | ||
|
||
return ( | ||
<div> | ||
{hasBlocks ? ( | ||
<div className="mx-auto max-w-2xl py-24"> | ||
<Form | ||
data={{ | ||
settings: { | ||
resolver: 'Preview', | ||
event_id: false, | ||
success_msg: 'Thank you!', | ||
}, | ||
rows: blocksUpdated, | ||
}} | ||
preview={true} | ||
/> | ||
</div> | ||
) : ( | ||
<div class="flex items-center justify-center py-24 text-center"> | ||
<h1>Add first block to start creating your form</h1> | ||
</div> | ||
)} | ||
</div> | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
import React, { useState } from 'react' | ||
import { useForm } from 'react-hook-form' | ||
import ButtonField from './partials/ButtonField' | ||
import Checkbox from './partials/Checkbox' | ||
import ContentSection from './partials/ContentSection' | ||
import Input from './partials/Input' | ||
import Submit from './partials/Submit' | ||
import TextArea from './partials/TextArea' | ||
import { handleGoal, cn } from '@/lib/helper' | ||
|
||
const encode = (data) => { | ||
return Object.keys(data) | ||
.map((key) => encodeURIComponent(key) + '=' + encodeURIComponent(data[key])) | ||
.join('&') | ||
} | ||
|
||
export default function Form({ data, white }) { | ||
const [isSend, setIsSend] = useState(false) | ||
const [isSending, setIsSending] = useState(false) | ||
const { | ||
register, | ||
handleSubmit, | ||
setValue, | ||
reset, | ||
formState: { errors: fieldErrors }, | ||
} = useForm() | ||
|
||
const onSubmit = async (formData) => { | ||
setIsSending(true) | ||
if (data.settings.resolver === 'Form') { | ||
fetch('/', { | ||
method: 'POST', | ||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, | ||
body: encode({ 'form-name': data.title, ...formData }), | ||
}) | ||
.then(() => { | ||
setIsSend(true) | ||
handleGoal(data.settings.event_id) | ||
setTimeout(() => { | ||
reset() | ||
setIsSending(false) | ||
}, 200) | ||
}) | ||
.catch((error) => setIsSending(false)) | ||
} | ||
|
||
if (data.settings.resolver === 'ConvertKit') { | ||
const res = await fetch('/api/subscribe', { | ||
method: 'POST', | ||
body: JSON.stringify(formData), | ||
}) | ||
const returned = JSON.parse(await res.json()) | ||
if (returned.success === true) { | ||
setIsSend(true) | ||
handleGoal(data.settings.event_id) | ||
setTimeout(() => { | ||
reset() | ||
}, 200) | ||
} | ||
setIsSending(false) | ||
} | ||
} | ||
|
||
return ( | ||
<div className="relative -mx-2 w-full overflow-hidden px-2 sm:w-auto"> | ||
<div | ||
className={cn( | ||
'absolute z-10 flex h-full w-full items-center justify-center transition-all', | ||
{ | ||
'-translate-y-full opacity-0': !isSend, | ||
}, | ||
)} | ||
> | ||
<div className="text-center text-2xl"> | ||
{data?.settings?.success_msg} | ||
</div> | ||
</div> | ||
<form | ||
className={cn('grid gap-6 transition-all', { | ||
'-translate-y-full opacity-0': isSend, | ||
})} | ||
name={data.title} | ||
onSubmit={handleSubmit(onSubmit)} | ||
data-netlify={data.settings.resolver === 'Form'} | ||
> | ||
{data.rows && | ||
data.rows.map((row, i) => ( | ||
<div | ||
key={i} | ||
className={cn( | ||
'flex flex-col justify-between gap-4 md:gap-6 lg:flex-row', | ||
{ | ||
'items-center': row.position === 'center', | ||
}, | ||
{ | ||
'items-end': row.position === 'bottom', | ||
}, | ||
)} | ||
> | ||
{row.fields && | ||
row.fields.map((field, i) => { | ||
switch (field.type) { | ||
case 'input': | ||
return ( | ||
<Input | ||
data={field} | ||
white={white} | ||
key={i} | ||
setValue={setValue} | ||
register={register} | ||
errors={fieldErrors} | ||
/> | ||
) | ||
case 'textarea': | ||
return ( | ||
<TextArea | ||
data={field} | ||
key={i} | ||
register={register} | ||
errors={fieldErrors} | ||
/> | ||
) | ||
case 'checkbox': | ||
return ( | ||
<Checkbox | ||
data={field} | ||
key={i} | ||
register={register} | ||
errors={fieldErrors} | ||
/> | ||
) | ||
case 'submit': | ||
return <Submit data={field} sending={isSending} key={i} /> | ||
case 'button': | ||
return <ButtonField data={field} key={i} /> | ||
case 'text': | ||
return <ContentSection data={field} key={i} /> | ||
default: | ||
return <></> | ||
} | ||
})} | ||
</div> | ||
))} | ||
</form> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import React from 'react' | ||
import Form from './Form' | ||
import { useForms } from '@/hooks/useForms' | ||
|
||
export default function FormWrapper({ formId, white }) { | ||
const forms = useForms() | ||
|
||
const { | ||
node: { frontmatter: form }, | ||
} = forms.find(({ node: item }) => item.frontmatter.id === formId) | ||
|
||
return <Form data={form} white={white}></Form> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import React from 'react' | ||
import Button from '../../UI/Button' | ||
|
||
export default function ButtonField({ data }) { | ||
return ( | ||
<div> | ||
<Button button={data?.button}>{data?.button?.content}</Button> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import React from 'react' | ||
import Label from '@/components/UI/Label' | ||
|
||
export default function Checkbox({ | ||
data, | ||
register, | ||
disabled = false, | ||
errors, | ||
...props | ||
}) { | ||
const name = data?.name ? data?.name : 'test-check' | ||
const error = errors[name] | ||
return ( | ||
<div className="w-full "> | ||
<Label htmlFor={name}> | ||
<div className="flex cursor-pointer gap-3"> | ||
<div className="mt-0.5 flex items-start justify-center"> | ||
<input | ||
type="checkbox" | ||
{...props} | ||
{...register(name)} | ||
id={name} | ||
disabled={disabled} | ||
value={true} | ||
aria-invalid={error ? 'true' : 'false'} | ||
required={data?.required} | ||
className="border-black-300 relative cursor-pointer rounded-sm bg-zinc-100 focus:ring-0" | ||
/> | ||
</div> | ||
<div className="text-dark-500 text-sm font-normal">{data?.label}</div> | ||
</div> | ||
</Label> | ||
<div className="block text-left text-sm text-red-600"> | ||
{error?.message} | ||
</div> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import React from 'react' | ||
import Text from '@/components/UI/Text' | ||
|
||
export default function ContentSection({ data }) { | ||
return ( | ||
<div> | ||
<Text className="text-sm">{data?.content}</Text> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import React from 'react' | ||
import classNames from 'clsx' | ||
import { slugify, cn } from '@/lib/helper' | ||
|
||
export default function Input({ | ||
data, | ||
register, | ||
disabled = false, | ||
setValue, | ||
errors, | ||
white, | ||
...props | ||
}) { | ||
const name = data?.label ? slugify(data?.label, '_') : 'preview' | ||
const error = errors[name] | ||
if (data?.value) { | ||
setValue(name, data.value) | ||
} | ||
|
||
return ( | ||
<div | ||
className={classNames('w-full', { | ||
hidden: data?.input_type === 'hidden', | ||
})} | ||
> | ||
<input | ||
{...props} | ||
{...register(name)} | ||
id={name} | ||
disabled={disabled} | ||
autoComplete={data?.autocomplete || 'on'} | ||
aria-invalid={error ? 'true' : 'false'} | ||
required={data?.required} | ||
type={data?.input_type} | ||
placeholder={`${data?.label}${data?.required ? '*' : ''}`} | ||
className={cn( | ||
'block h-14 w-full rounded-lg border border-gray-600 px-5 transition-colors placeholder:text-gray-700 focus:border-blue-400 focus:ring-0 sm:h-16', | ||
{ | ||
'w-full border-gray-400 bg-white sm:w-96': white, | ||
'bg-gray-100': !white, | ||
}, | ||
)} | ||
></input> | ||
<div className="block text-left text-sm text-red-600"> | ||
{error?.message} | ||
</div> | ||
{white} | ||
</div> | ||
) | ||
} |
Oops, something went wrong.