diff --git a/components/Checkboxes.tsx b/components/Checkboxes.tsx new file mode 100644 index 0000000..3564455 --- /dev/null +++ b/components/Checkboxes.tsx @@ -0,0 +1,61 @@ +import React, { ChangeEvent, useEffect, useState } from 'react' +import { v4 } from 'uuid' + +import styles from '../styles/Checkboxes.module.css' + +export type CheckboxesProps = { + disabled?: boolean + options: string[] + updateCallback?: (update: string) => void +} +const Checkboxes = ({ + disabled = false, + options, + updateCallback +}: CheckboxesProps) => { + const [selectedOptions, updateSelectedOptions] = useState( + options.map(() => false) + ) + + useEffect( + () => { + if (!updateCallback) return + updateCallback(selectedOptions.toString()) + }, + // eslint-disable-next-line react-hooks/exhaustive-deps + [selectedOptions] + ) + + const uuid = v4() + + const onSelectionChange = (e: ChangeEvent) => { + const index = parseInt((e.target as HTMLInputElement).value) + const clonedSelectedOptions = Array.from(selectedOptions) + clonedSelectedOptions[index] = !clonedSelectedOptions[index] + updateSelectedOptions(clonedSelectedOptions) + } + + return ( +
+ {options?.map((option, index) => ( + + ))} +
+ ) +} +export { Checkboxes } diff --git a/components/QuestionRenderer.tsx b/components/QuestionRenderer.tsx index 18df686..9072105 100644 --- a/components/QuestionRenderer.tsx +++ b/components/QuestionRenderer.tsx @@ -1,6 +1,7 @@ /* eslint-disable complexity */ import { useTranslations } from 'next-intl' +import { Checkboxes } from './Checkboxes' import { RadioButtonProps, RadioButtons } from './RadioButtons' import { SatisfactionSlider, @@ -48,6 +49,15 @@ const QuestionRenderer = ({ const renderQuestion = (type: string) => { switch (type) { + case 'checkbox': + if (!('options' in question)) return failure + return ( + + ) case 'radio': if (!('options' in question)) return failure return ( diff --git a/components/stories/Checkboxes.story.tsx b/components/stories/Checkboxes.story.tsx new file mode 100644 index 0000000..a7b4163 --- /dev/null +++ b/components/stories/Checkboxes.story.tsx @@ -0,0 +1,27 @@ +import React from 'react' +import { action } from '@storybook/addon-actions' +import { ComponentMeta } from '@storybook/react' + +import { Checkboxes } from '../Checkboxes' + +export default { + component: Checkboxes, + title: 'Check Boxes' +} as ComponentMeta + +export const Default = () => ( + +) + +export const WithTitle = () => ( + <> +

How many stars are there in the sky?

+ + +) diff --git a/config.yaml b/config.yaml index 64c2eb9..c8ca13f 100644 --- a/config.yaml +++ b/config.yaml @@ -16,6 +16,14 @@ questions: type: "textarea" # This is an example of a non-internationalized question title: "What do you think of this survey?" + - + type: "checkbox" + title: "Which emotions does this survey bring out within you?" + options: + - "Joy" + - "Delight" + - "Ecstasy" + - "Happy" - # This question type provides a slider and a corresponding emoji-based # satisfaction display diff --git a/package.json b/package.json index 91b8e6b..c548ba1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,9 @@ { "name": "survey", "version": "0.1.0", - "engines": { "node": "18.x" }, + "engines": { + "node": ">=18.x" + }, "scripts": { "dev": "next dev", "build": "next build", diff --git a/styles/Checkboxes.module.css b/styles/Checkboxes.module.css new file mode 100644 index 0000000..fdce6c2 --- /dev/null +++ b/styles/Checkboxes.module.css @@ -0,0 +1,20 @@ +.container { + font-size: 25px; +} + +.container label { + display: grid; + align-items: center; + grid-template-columns: 25px 1fr; + grid-gap: 1ch; + padding-bottom: 0.33333ch; +} +.container label input { + height: 25px; + width: 25px; +} + +.button ~ .label { + color: #333; + transition: all 0.1s ease-in-out; +}