diff --git a/cms/cms.js b/cms/cms.js
index e46ab1b..0262b07 100644
--- a/cms/cms.js
+++ b/cms/cms.js
@@ -1,12 +1,13 @@
-import CMS from 'decap-cms-app';
-import { Widget as UuidWidget } from 'netlify-cms-widget-id';
-import { Widget as PermalinkWidget } from 'netlify-cms-widget-permalink';
-
-import pages from './collections/pages';
-import posts from './collections/posts';
-import authors from './collections/authors';
-import settings from './collections/settings';
-import PagePreview from './previews/Page';
+import CMS from 'decap-cms-app'
+import { Widget as UuidWidget } from 'netlify-cms-widget-id'
+import { Widget as PermalinkWidget } from 'netlify-cms-widget-permalink'
+import authors from './collections/authors'
+import forms from './collections/forms'
+import pages from './collections/pages'
+import posts from './collections/posts'
+import settings from './collections/settings'
+import FormPreview from './previews/FormPreview'
+import PagePreview from './previews/Page'
const config = {
config: {
@@ -23,9 +24,14 @@ const config = {
},
media_folder: '/static/img',
public_folder: '/img',
- collections: [pages, posts, authors, settings],
+ collections: [pages, posts, authors, forms, settings],
},
-};
+}
+
+
+CMS.registerPreviewStyle('../commons.css')
+CMS.registerPreviewTemplate('pages', PagePreview)
+CMS.registerPreviewTemplate('forms', FormPreview)
const injectCustomStyle = () => {
const style = document.createElement('style')
@@ -39,10 +45,7 @@ const injectCustomStyle = () => {
injectCustomStyle()
-CMS.registerPreviewStyle('../commons.css');
-CMS.registerPreviewTemplate('pages', PagePreview);
-
-CMS.registerWidget(UuidWidget);
-CMS.registerWidget(PermalinkWidget);
+CMS.registerWidget(UuidWidget)
+CMS.registerWidget(PermalinkWidget)
-CMS.init(config);
+CMS.init(config)
diff --git a/cms/previews/FormPreview.js b/cms/previews/FormPreview.js
new file mode 100644
index 0000000..c2beea2
--- /dev/null
+++ b/cms/previews/FormPreview.js
@@ -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 (
+
+ {hasBlocks ? (
+
+
+
+ ) : (
+
+
Add first block to start creating your form
+
+ )}
+
+ )
+ }
+}
diff --git a/content/forms/example.md b/content/forms/example.md
index 5cbb820..72a1b74 100644
--- a/content/forms/example.md
+++ b/content/forms/example.md
@@ -51,14 +51,5 @@ rows:
- fields:
- type: submit
label: Take the first step
- - type: button
- button:
- variant: default
- content: Let's go to google!!
- url: 'https://google.com'
position: center
- - position: bottom
- fields:
- - type: text
- content: Yo yo yo
---
diff --git a/jsconfig.json b/jsconfig.json
index 8c39ffb..9a2681a 100644
--- a/jsconfig.json
+++ b/jsconfig.json
@@ -4,7 +4,7 @@
"paths": {
"@/*": ["./src/*"],
"~/*": ["./*"],
- "img": ["./static/img/*"]
+ "img/*": ["./static/img/*"]
}
},
"exclude": ["node_modules"]
diff --git a/src/blocks/Content.js b/src/blocks/Content.js
index 92c603d..c13611c 100644
--- a/src/blocks/Content.js
+++ b/src/blocks/Content.js
@@ -1,5 +1,6 @@
import React from 'react'
import Container from '@/components/UI/Container'
+import Section from '@/components/UI/Section'
import Text from '@/components/UI/Text'
export default function Content({ data }) {
diff --git a/src/components/Form/Form.js b/src/components/Form/Form.js
new file mode 100644
index 0000000..0d7bed7
--- /dev/null
+++ b/src/components/Form/Form.js
@@ -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 (
+
+
+
+ {data?.settings?.success_msg}
+
+
+
+
+ )
+}
diff --git a/src/components/Form/FormWrapper.js b/src/components/Form/FormWrapper.js
new file mode 100644
index 0000000..4d2dd0a
--- /dev/null
+++ b/src/components/Form/FormWrapper.js
@@ -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
+}
diff --git a/src/components/Form/partials/ButtonField.js b/src/components/Form/partials/ButtonField.js
new file mode 100644
index 0000000..69dca62
--- /dev/null
+++ b/src/components/Form/partials/ButtonField.js
@@ -0,0 +1,10 @@
+import React from 'react'
+import Button from '../../UI/Button'
+
+export default function ButtonField({ data }) {
+ return (
+
+
+
+ )
+}
diff --git a/src/components/Form/partials/Checkbox.js b/src/components/Form/partials/Checkbox.js
new file mode 100644
index 0000000..13871f4
--- /dev/null
+++ b/src/components/Form/partials/Checkbox.js
@@ -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 (
+
+
+
+ {error?.message}
+
+
+ )
+}
diff --git a/src/components/Form/partials/ContentSection.js b/src/components/Form/partials/ContentSection.js
new file mode 100644
index 0000000..434ab36
--- /dev/null
+++ b/src/components/Form/partials/ContentSection.js
@@ -0,0 +1,10 @@
+import React from 'react'
+import Text from '@/components/UI/Text'
+
+export default function ContentSection({ data }) {
+ return (
+
+ {data?.content}
+
+ )
+}
diff --git a/src/components/Form/partials/Input.js b/src/components/Form/partials/Input.js
new file mode 100644
index 0000000..6aabe29
--- /dev/null
+++ b/src/components/Form/partials/Input.js
@@ -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 (
+
+
+
+ {error?.message}
+
+ {white}
+
+ )
+}
diff --git a/src/components/Form/partials/Submit.js b/src/components/Form/partials/Submit.js
new file mode 100644
index 0000000..0d2ef62
--- /dev/null
+++ b/src/components/Form/partials/Submit.js
@@ -0,0 +1,41 @@
+import React from 'react'
+import Button from '@/components/UI/Button'
+import { cn } from '@/lib/helper'
+
+export default function Submit({ data, sending }) {
+ return (
+
+
+
+ )
+}
diff --git a/src/components/Form/partials/TextArea.js b/src/components/Form/partials/TextArea.js
new file mode 100644
index 0000000..147f086
--- /dev/null
+++ b/src/components/Form/partials/TextArea.js
@@ -0,0 +1,30 @@
+import React from 'react'
+import { slugify } from '@/lib/helper'
+
+export default function TextArea({
+ data,
+ register,
+ disabled = false,
+ errors,
+ ...props
+}) {
+ const name = data?.label ? slugify(data?.label, '_') : 'testing'
+ const error = errors[name]
+ return (
+
+
+
+ {error?.message}
+
+
+ )
+}
diff --git a/src/components/UI/Button.js b/src/components/UI/Button.js
index d5a7fd7..77b64b2 100644
--- a/src/components/UI/Button.js
+++ b/src/components/UI/Button.js
@@ -6,7 +6,7 @@ export default function Button({ className, button, children, ...props }) {
let buttonStyle = 'group inline-block font-bold text-dark-500 dark:text-white'
switch (button?.variant) {
case 'button':
- buttonStyle = `${buttonStyle} border-dark-500 border dark:border-white bg-dark-500 dark:bg-white text-white dark:text-black py-2 px-6 text-center dark:hover:bg-transparent hover:bg-transparent hover:text-dark-500 dark:hover:text-white transition-colors`
+ buttonStyle = `${buttonStyle} border-dark-500 border dark:border-white bg-dark-500 dark:bg-white text-black dark:text-black py-2 px-6 text-center dark:hover:bg-transparent hover:bg-transparent hover:text-dark-500 dark:hover:text-white transition-colors`
break
case 'outlined':
buttonStyle = `${buttonStyle} border-dark-500 border dark:border-white py-2 px-6 text-center dark:hover:bg-white hover:bg-dark-500 hover:text-white dark:hover:text-black transition-colors`