chore: style refinements

This commit is contained in:
PatrikKozak
2023-03-15 11:58:40 -04:00
parent b459277c72
commit 8e814b1edd
9 changed files with 154 additions and 131 deletions

View File

@@ -7,7 +7,7 @@
{
"type": "node",
"request": "launch",
"name": "Debug Learn with Jason CMS",
"name": "Form Builder Example CMS",
"program": "${workspaceFolder}/src/server.ts",
"preLaunchTask": "npm: build:server",
"env": {
@@ -18,4 +18,4 @@
// ]
},
]
}
}

View File

@@ -74,7 +74,7 @@ export const advancedForm = {
blockType: 'number',
},
{
name: 'county',
name: 'country',
label: 'Country',
width: 50,
required: true,
@@ -92,6 +92,7 @@ export const advancedForm = {
text: 'Your shipping information submission was successful.',
},
],
type: 'h2',
},
],
emails: [

View File

@@ -78,6 +78,7 @@ export const basicForm = {
text: 'The basic form has been submitted successfully.',
},
],
type: 'h2',
},
],
emails: [

View File

@@ -48,6 +48,7 @@ export const contactForm = {
text: 'The contact form has been submitted successfully.',
},
],
type: 'h2',
},
],
emails: [

View File

@@ -60,6 +60,7 @@ export const signUpForm = {
text: 'Your sign up submission was successful.',
},
],
type: 'h2',
},
],
emails: [

View File

@@ -5,6 +5,16 @@
flex-direction: column;
}
.hasSubmitted {
align-items: center;
justify-content: center;
height: 80vh;
@include small-break {
height: 100%;
}
}
.intro {
margin-bottom: var(--base);
@@ -13,6 +23,12 @@
}
}
.confirmationMessage {
* {
margin: 0;
}
}
.fieldWrap {
position: relative;
z-index: 2;

View File

@@ -1,14 +1,14 @@
import React, { useState, useCallback } from 'react';
import { fields } from './fields';
import { Form as FormType } from 'payload-plugin-form-builder/dist/types';
import RichText from '../../RichText';
import { useForm } from 'react-hook-form';
import { useRouter } from 'next/router';
import { Gutter } from '../../Gutter';
import { Button } from '../../Button';
import React, { useState, useCallback } from 'react'
import { buildInitialFormState } from './buildInitialFormState'
import { fields } from './fields'
import { Form as FormType } from 'payload-plugin-form-builder/dist/types'
import RichText from '../../RichText'
import { useForm } from 'react-hook-form'
import { useRouter } from 'next/router'
import { Gutter } from '../../Gutter'
import { Button } from '../../Button'
import classes from './index.module.scss';
import { buildInitialFormState } from './buildInitialFormState';
import classes from './index.module.scss'
export type Value = unknown
@@ -26,157 +26,147 @@ export type FormBlockType = {
enableIntro: Boolean
form: FormType
introContent?: {
[k: string]: unknown;
}[];
[k: string]: unknown
}[]
}
export const FormBlock: React.FC<FormBlockType & {
id?: string,
}> = (props) => {
export const FormBlock: React.FC<
FormBlockType & {
id?: string
}
> = props => {
const {
enableIntro,
introContent,
form: formFromProps,
form: {
id: formID,
submitButtonLabel,
confirmationType,
redirect,
confirmationMessage
} = {},
} = props;
form: { id: formID, submitButtonLabel, confirmationType, redirect, confirmationMessage } = {},
} = props
const formMethods = useForm({
defaultValues: buildInitialFormState(formFromProps.fields)
});
const { register, handleSubmit, formState: { errors }, control, setValue, getValues } = formMethods;
defaultValues: buildInitialFormState(formFromProps.fields),
})
const {
register,
handleSubmit,
formState: { errors },
control,
setValue,
getValues,
} = formMethods
const [isLoading, setIsLoading] = useState(false);
const [hasSubmitted, setHasSubmitted] = useState<boolean>();
const [error, setError] = useState<{ status?: string, message: string } | undefined>();
const router = useRouter();
const [isLoading, setIsLoading] = useState(false)
const [hasSubmitted, setHasSubmitted] = useState<boolean>()
const [error, setError] = useState<{ status?: string; message: string } | undefined>()
const router = useRouter()
const onSubmit = useCallback((data: Data) => {
let loadingTimerID: NodeJS.Timer;
const onSubmit = useCallback(
(data: Data) => {
let loadingTimerID: NodeJS.Timer
const submitForm = async () => {
setError(undefined);
const submitForm = async () => {
setError(undefined)
const dataToSend = Object.entries(data).map(([name, value]) => ({
field: name,
value
}));
const dataToSend = Object.entries(data).map(([name, value]) => ({
field: name,
value,
}))
// delay loading indicator by 1s
loadingTimerID = setTimeout(() => {
setIsLoading(true);
}, 1000);
// delay loading indicator by 1s
loadingTimerID = setTimeout(() => {
setIsLoading(true)
}, 1000)
try {
const req = await fetch(`${process.env.NEXT_PUBLIC_CMS_URL}/api/form-submissions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
form: formID,
submissionData: dataToSend,
try {
const req = await fetch(`${process.env.NEXT_PUBLIC_CMS_URL}/api/form-submissions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
form: formID,
submissionData: dataToSend,
}),
})
})
const res = await req.json();
const res = await req.json()
clearTimeout(loadingTimerID);
clearTimeout(loadingTimerID)
if (req.status >= 400) {
setIsLoading(false);
if (req.status >= 400) {
setIsLoading(false)
setError({
status: res.status,
message: res.errors?.[0]?.message || 'Internal Server Error',
})
return
}
setIsLoading(false)
setHasSubmitted(true)
if (confirmationType === 'redirect' && redirect) {
const { url } = redirect
const redirectUrl = url
if (redirectUrl) router.push(redirectUrl)
}
} catch (err) {
console.warn(err)
setIsLoading(false)
setError({
status: res.status,
message: res.errors?.[0]?.message || 'Internal Server Error',
});
return;
message: 'Something went wrong.',
})
}
setIsLoading(false);
setHasSubmitted(true);
if (confirmationType === 'redirect' && redirect) {
const {
url
} = redirect;
const redirectUrl = url;
if (redirectUrl) router.push(redirectUrl);
}
} catch (err) {
console.warn(err);
setIsLoading(false);
setError({
message: 'Something went wrong.'
});
}
}
submitForm();
}, [
router,
formID,
redirect,
confirmationType,
]);
submitForm()
},
[router, formID, redirect, confirmationType],
)
return (
<Gutter>
<div className={classes.form}>
<div
className={[
classes.form,
hasSubmitted && classes.hasSubmitted,
].filter(Boolean).join(' ')}
>
{enableIntro && introContent && !hasSubmitted && (
<RichText
className={classes.intro}
content={introContent}
/>
<RichText className={classes.intro} content={introContent} />
)}
{!isLoading && hasSubmitted && confirmationType === 'message' && (
<RichText content={confirmationMessage} />
)}
{isLoading && !hasSubmitted && (
<p>
Loading, please wait...
</p>
)}
{error && (
<div>
{`${error.status || '500'}: ${error.message || ''}`}
</div>
<RichText className={classes.confirmationMessage} content={confirmationMessage} />
)}
{isLoading && !hasSubmitted && <p>Loading, please wait...</p>}
{error && <div>{`${error.status || '500'}: ${error.message || ''}`}</div>}
{!hasSubmitted && (
<form id={formID} onSubmit={handleSubmit(onSubmit)}>
<div className={classes.fieldWrap}>
{formFromProps && formFromProps.fields && formFromProps.fields.map((field, index) => {
const Field: React.FC<any> = fields?.[field.blockType];
if (Field) {
return (
<React.Fragment key={index}>
<Field
form={formFromProps}
{...field}
{...formMethods}
register={register}
errors={errors}
control={control}
/>
</React.Fragment>
)
}
return null;
})}
{formFromProps &&
formFromProps.fields &&
formFromProps.fields.map((field, index) => {
const Field: React.FC<any> = fields?.[field.blockType]
if (Field) {
return (
<React.Fragment key={index}>
<Field
form={formFromProps}
{...field}
{...formMethods}
register={register}
errors={errors}
control={control}
/>
</React.Fragment>
)
}
return null
})}
</div>
<Button
label={submitButtonLabel}
appearance="primary"
el="button"
form={formID}
/>
<Button label={submitButtonLabel} appearance="primary" el="button" form={formID} />
</form>
)}
</div>

View File

@@ -38,6 +38,7 @@ const Blocks: React.FC<{
<VerticalPadding
key={isFormBlock ? formID : index}
top='small'
bottom='small'
>
{/*@ts-ignore*/}
<Block

View File

@@ -34,11 +34,23 @@
.appearance--primary {
background-color: var(--color-black);
color: var(--color-white);
&:hover, &:focus {
background-color: var(--color-white);
color: var(--color-black);
box-shadow: inset 0 0 0 1px var(--color-black);
}
}
.appearance--secondary {
background-color: var(--color-white);
box-shadow: inset 0 0 0 1px var(--color-black);
&:hover, &:focus {
background-color: var(--color-black);
color: var(--color-white);
box-shadow: inset 0 0 0 1px var(--color-black);
}
}
.appearance--default {