Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Checkbox question type #25

Open
wants to merge 4 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions components/Checkboxes.tsx
Original file line number Diff line number Diff line change
@@ -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]
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use useEffect here. Just make a callback function that calls updateSelectedOptions and updateCallback and call that function from line 35 where you call updateSelectedOptions now


const uuid = v4()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmm. Does this cause the id to change on every rerender? Like when a box is checked and unchecked?


const onSelectionChange = (e: ChangeEvent<HTMLInputElement>) => {
const index = parseInt((e.target as HTMLInputElement).value)
const clonedSelectedOptions = Array.from(selectedOptions)
clonedSelectedOptions[index] = !clonedSelectedOptions[index]
updateSelectedOptions(clonedSelectedOptions)
}

return (
<div className={styles.container}>
{options?.map((option, index) => (
<label htmlFor={`${uuid}-${index}`} key={index}>
<input
aria-labelledby={`${option}-label`}
className={styles.button}
defaultChecked={selectedOptions[index] === true}
disabled={disabled}
id={`${uuid}-${index}`}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not just use option or option-index?

name={uuid}
onChange={onSelectionChange}
type="checkbox"
value={index}
/>
<span className={styles.label} id={`${option}-label`}>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are using option for the ID here then why not use it for the key on label too instead of index?

{option}
</span>
</label>
))}
</div>
)
}
export { Checkboxes }
10 changes: 10 additions & 0 deletions components/QuestionRenderer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable complexity */
import { useTranslations } from 'next-intl'

import { Checkboxes } from './Checkboxes'
import { RadioButtonProps, RadioButtons } from './RadioButtons'
import {
SatisfactionSlider,
Expand Down Expand Up @@ -48,6 +49,15 @@ const QuestionRenderer = ({

const renderQuestion = (type: string) => {
switch (type) {
case 'checkbox':
if (!('options' in question)) return failure
return (
<Checkboxes
disabled={disabled}
options={question.options}
updateCallback={updateCallback}
/>
)
case 'radio':
if (!('options' in question)) return failure
return (
Expand Down
27 changes: 27 additions & 0 deletions components/stories/Checkboxes.story.tsx
Original file line number Diff line number Diff line change
@@ -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<typeof Checkboxes>

export const Default = () => (
<Checkboxes
options={['first', 'second', 'third']}
updateCallback={action('Option is selected')}
/>
)

export const WithTitle = () => (
<>
<h1>How many stars are there in the sky?</h1>
<Checkboxes
options={['one', 'two', 'three', 'four', 'five']}
updateCallback={action('Option is selected')}
/>
</>
miles-grant-ibigroup marked this conversation as resolved.
Show resolved Hide resolved
)
8 changes: 8 additions & 0 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{
"name": "survey",
"version": "0.1.0",
"engines": { "node": "18.x" },
"engines": {
"node": ">=18.x"
miles-grant-ibigroup marked this conversation as resolved.
Show resolved Hide resolved
},
"scripts": {
"dev": "next dev",
"build": "next build",
Expand Down
20 changes: 20 additions & 0 deletions styles/Checkboxes.module.css
Original file line number Diff line number Diff line change
@@ -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;
}
Loading