-
Notifications
You must be signed in to change notification settings - Fork 0
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
DS-1264: feat(checkbox, checkbox-group): add required state for checkboxes #1035
base: master
Are you sure you want to change the base?
Changes from all commits
914c235
c412a6d
e6453b9
74b051d
ec1a391
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,4 +45,39 @@ describe('Checkbox', () => { | |
|
||
expect(tree).toMatchSnapshot(); | ||
}); | ||
|
||
test('should display warning message if input is invalid and not checked', () => { | ||
const wrapper = mountWithTheme( | ||
<CheckboxGroup | ||
label="Vehicule" | ||
checkboxGroup={checkboxGroup} | ||
required | ||
valid={false} | ||
id="checkbox-group-test" | ||
/>, | ||
); | ||
|
||
const warning = wrapper.find('div#checkbox-group-test_validationAlert'); | ||
expect(warning).toBeDefined(); | ||
}); | ||
|
||
test('should hide warning message if group is invalid and one input is checked', () => { | ||
const wrapper = mountWithTheme( | ||
<CheckboxGroup | ||
label="Vehicule" | ||
checkboxGroup={checkboxGroup} | ||
required | ||
valid={false} | ||
id="checkbox-group-test" | ||
/>, | ||
); | ||
|
||
const warningPreCheck = wrapper.find('div#checkbox-group-test_validationAlert'); | ||
expect(warningPreCheck).toBeDefined(); | ||
Comment on lines
+75
to
+76
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pas besoin de ce bout là, ton test précédent fait la même chose. |
||
|
||
wrapper.find('input').at(0).simulate('change'); | ||
|
||
const warningPostCheck = wrapper.find('div#checkbox-group-test_validationAlert'); | ||
expect(warningPostCheck).toEqual({}); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,11 @@ | ||
import { ChangeEvent, VoidFunctionComponent } from 'react'; | ||
import { ChangeEvent, useState, VoidFunctionComponent } from 'react'; | ||
import styled from 'styled-components'; | ||
import { useDataAttributes } from '../../hooks/use-data-attributes'; | ||
import { Checkbox } from '../checkbox/checkbox'; | ||
import { useDeviceContext } from '../device-context-provider/device-context-provider'; | ||
import { useTranslation } from '../../i18n/use-translation'; | ||
import { v4 as uuid } from '../../utils/uuid'; | ||
import { Icon } from '../icon/icon'; | ||
|
||
const Legend = styled.legend` | ||
font-size: 0.75rem; | ||
|
@@ -10,9 +14,27 @@ const Legend = styled.legend` | |
padding: 0; | ||
`; | ||
|
||
const StyledIcon = styled(Icon)` | ||
align-self: center; | ||
display: flex; | ||
margin-right: var(--spacing-base); | ||
`; | ||
|
||
const ValidationErrorAlert = styled.div<{ label: string }>` | ||
align-items: flex-start; | ||
color: ${({ theme }) => theme.component['checkbox-error-border-color']}; | ||
display: flex; | ||
margin: ${({ label }) => `${label ? 'calc(var(--spacing-1x) * -1) ' : '0'} 0 0 var(--spacing-1x) `}; | ||
padding-bottom: var(--spacing-1x); | ||
`; | ||
|
||
interface CheckboxProps { | ||
id?: string; | ||
label?: string; | ||
checkedValues?: string[]; | ||
required?: boolean; | ||
valid?: boolean; | ||
validationErrorMessage?: string; | ||
checkboxGroup: { | ||
label: string, | ||
name: string, | ||
|
@@ -25,35 +47,67 @@ interface CheckboxProps { | |
} | ||
|
||
export const CheckboxGroup: VoidFunctionComponent<CheckboxProps> = ({ | ||
id, | ||
label, | ||
checkedValues, | ||
checkboxGroup, | ||
required, | ||
valid = true, | ||
validationErrorMessage, | ||
onChange, | ||
...props | ||
}) => { | ||
const { isMobile } = useDeviceContext(); | ||
const { t } = useTranslation('checkbox'); | ||
const dataAttributes = useDataAttributes(props); | ||
const dataTestId = dataAttributes['data-testid'] ?? 'checkboxGroup'; | ||
const validationAlertId = `${id || uuid()}_validationAlert`; | ||
const [checkedState, setCheckedState] = useState( | ||
new Array(checkboxGroup.length).fill(false), | ||
); | ||
const areAllCheckboxUnchecked = checkedState.every((e) => e === false); | ||
|
||
const handleOnChange = (position: number): void => { | ||
const updatedCheckedState = checkedState.map((item, index) => (index === position ? !item : item)); | ||
|
||
setCheckedState(updatedCheckedState); | ||
}; | ||
Comment on lines
+65
to
+74
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Je suis pas certain qu'on doive gérer le state. Ça devrait être synchronisé avec les |
||
|
||
return ( | ||
<> | ||
{label && <Legend>{label}</Legend>} | ||
{ | ||
required && !valid && areAllCheckboxUnchecked | ||
&& ( | ||
<ValidationErrorAlert id={validationAlertId} label={label || ''}> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Même question There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Et le message semble affiché dès le load du component. Je pense qu'on voulait pas ça, on l'avait enlevé sur le There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Le message d'erreur devrait s'afficher si l'utilisateur n'a pas sélectionné de checkbox et qu'il submit le formulaire. La validation va fail et le message d'erreur va s'afficher. |
||
<StyledIcon name="alertOctagon" size={isMobile ? '24' : '16'} /> | ||
{validationErrorMessage || t('validationErrorMessage')} | ||
</ValidationErrorAlert> | ||
) | ||
} | ||
{checkboxGroup.map(({ | ||
defaultChecked, | ||
disabled, | ||
label: checkboxLabel, | ||
name, | ||
value, | ||
}) => ( | ||
}, pos) => ( | ||
<Checkbox | ||
key={`${name}-${value}`} | ||
checked={checkedValues?.includes(value)} | ||
data-testid={`${dataTestId}-${value}`} | ||
defaultChecked={defaultChecked} | ||
disabled={disabled} | ||
isInGroup | ||
label={checkboxLabel} | ||
name={name} | ||
required={required} | ||
valid={valid} | ||
value={value} | ||
onChange={onChange} | ||
onChange={(event: ChangeEvent<HTMLInputElement>) => { | ||
handleOnChange(pos); | ||
onChange?.(event); | ||
}} | ||
/> | ||
))} | ||
</> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Je pense que t'as pas besoin du
div
dans le sélecteur?