Skip to content

Instantly share code, notes, and snippets.

@remy90
Last active May 18, 2023 10:37
Show Gist options
  • Save remy90/7cc539c8dd52e95589542610e561f7b3 to your computer and use it in GitHub Desktop.
Save remy90/7cc539c8dd52e95589542610e561f7b3 to your computer and use it in GitHub Desktop.
Basic Repro
import { useField, useFormFields } from 'payload/components/forms'
import ReactSelect from 'payload/dist/admin/components/elements/ReactSelect'
import React, { useEffect, useState } from 'react'
import {
generateOptions
ConditionalLogicOption,
getAnswerOptionsFromAnswerTypes,
} from './helpers'
import { Option } from 'payload/dist/admin/components/elements/ReactSelect/types'
const ConditionField: React.FC<{ path: string; name: string }> = ({ path, name }) => {
const { fields } = useFormFields(([fields, dispatch]) => ({ fields, dispatch }))
const [prerequisites, setPrerequisites] = useState<ConditionalLogicOption[]>([])
const { value: reactSelectedValue, setValue: setReactSelectedvalue } = useField<string>({ path })
const [options, setOptions] = useState<Option[]>([])
const [questionPaths, setQuestionPaths] = useState<string[]>([])
const [answerPaths, setAnswerPaths] = useState<string[]>([])
const [selectedOption, setSelectedOption] = useState<Option>({
value: reactSelectedValue,
})
const handlePrerequisiteChange = ({ label, value }: Option) => {
if (label) {
setSelectedOption({ label, value })
setReactSelectedvalue(value)
} else {
setSelectedOption({ label: null, value: null })
setReactSelectedvalue(null)
}
}
useEffect(() => {
const numberOfPages = fields[`pages`].value
const pageNumbers = Array.apply(null, Array(numberOfPages)).map((_, index) => index)
setQuestionPaths(pageNumbers.map(pageNo => `pages.${pageNo}.content.questions.0.text`))
setAnswerPaths(
pageNumbers.flatMap(pageNo =>
getAnswerOptionsFromAnswerTypes(
fields[`pages.${pageNo}.content.questions.0.answerType.0.blockType`],
)?.map<string>(option => `pages.${pageNo}.content.questions.0.answerType.0.${option}`),
),
)
}, [])
useEffect(() => {
setPrerequisites([...generateOptions(fields)])
}, [
fields[`pages`].value,
questionPaths.map(path => fields[path]?.value).length,
answerPaths.map(path => fields[path]?.value).length,
])
const createSelectOptions = (options: ConditionalLogicOption[]) =>
options.map<Option>((option, i) => ({
label: `${option.question} = ${option.answer}`,
value: `${option.qId}=${i}`,
}))
useEffect(() => {
setOptions(createSelectOptions(prerequisites))
}, [prerequisites])
return (
<div className='render-fields field-type row prerequisite-container '>
<ReactSelect
placeholder='A condition before displaying this question'
onChange={handlePrerequisiteChange}
value={options.find(({ value }) => value === selectedOption.value)}
options={options}
isClearable={true}
/>
</div>
)
}
export default ConditionField
export const generateOptions: (pageState: Fields) => ConditionalLogicOption[] = pageState => {
const numberOfPages = pageState.pages.value
const pageNumbers = Array.apply(null, Array(numberOfPages)).map((_, index) => index)
const questionAnswerCombinations: ConditionalLogicOption[] =
pageNumbers
?.flatMap(
(pageNo: number) =>
getAnswerOptionsFromAnswerTypes(
pageState[`pages.${pageNo}.content.questions.0.answerType.0.blockType`],
)?.map<ConditionalLogicOption>(option => ({
qId: pageState[`pages.${pageNo}.content.questions.0.id`].value as string,
question: pageState[`pages.${pageNo}.content.questions.0.text`].value as string,
answer:
(pageState[`pages.${pageNo}.content.questions.0.answerType.0.${option}`]
?.value as string) || '',
})) ?? [],
)
?.filter((option: ConditionalLogicOption) => option.question && option.answer) ?? []
return questionAnswerCombinations
}
import type { Block } from 'payload/types'
import { getRichTextField, pageFields } from '@/blocks/PageType'
import { questionFields, questionText } from '@/blocks/Questions'
import { basicQuestionAnswerTypes } from '@/blocks/Questions/Basic'
import { blockFields } from '@/fields/blockFields'
import ConditionField from '@/fields/ConditionField'
export const StandardPage: Block = {
slug: 'standardPage',
labels: {
singular: 'Standard page',
plural: 'Standard pages',
},
fields: [
blockFields({
name: 'content',
fields: [
pageFields,
{
type: 'row',
fields: [
{
type: 'array',
name: 'logic',
fields: [
{
name: 'Condition',
type: 'text',
admin: {
components: {
Field: ConditionField,
},
},
},
],
},
],
},
],
}),
],
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment