Skip to content

Commit

Permalink
feat: create gender id pattern edit form tckt-365
Browse files Browse the repository at this point in the history
  • Loading branch information
kalasgarov committed Nov 27, 2024
1 parent b6ddf13 commit 4fafc9d
Show file tree
Hide file tree
Showing 8 changed files with 334 additions and 0 deletions.
10 changes: 10 additions & 0 deletions packages/common/src/locales/en/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,15 @@ export const en = {
hint: 'For example, 555-11-0000',
errorTextMustContainChar: 'String must contain at least 1 character(s)',
},
genderId: {
...defaults,
displayName: 'Gender Identity label',
fieldLabel: 'Gender Identity label',
hintLabel: 'Gender Identity hint label',
hint: 'For example, man, woman, non-binary',
errorTextMustContainChar: 'String must contain at least 1 character(s)',
preferNotToAnswerTextLabel:
'Prefer not to share my gender identity label',
},
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import dateIcon from './images/date-icon.svg';
import dropDownIcon from './images/dropdown-icon.svg';
import dropDownOptionIcon from './images/dropdownoption-icon.svg';
import emailInputIcon from './images/email-icon.svg';
import genderId from './images/gender-id-icon.svg';
import longanswerIcon from './images/longanswer-icon.svg';
import pageIcon from './images/page-icon.svg';
import phoneIcon from './images/phone-icon.svg';
Expand All @@ -32,6 +33,7 @@ const icons: Record<string, string | any> = {
'dropdown-icon.svg': dropDownIcon,
'dropdownoption-icon.svg': dropDownOptionIcon,
'email-icon.svg': emailInputIcon,
'gender-id-icon.svg': genderId,
'longanswer-icon.svg': longanswerIcon,
'page-icon.svg': pageIcon,
'phone-icon.svg': phoneIcon,
Expand Down Expand Up @@ -101,6 +103,7 @@ const sidebarPatterns: DropdownPattern[] = [
['email-input', defaultFormConfig.patterns['email-input']],
['fieldset', defaultFormConfig.patterns['fieldset']],
['form-summary', defaultFormConfig.patterns['form-summary']],
['gender-id', defaultFormConfig.patterns['gender-id']],
['input', defaultFormConfig.patterns['input']],
['package-download', defaultFormConfig.patterns['package-download']],
['paragraph', defaultFormConfig.patterns['paragraph']],
Expand All @@ -120,6 +123,7 @@ export const fieldsetPatterns: DropdownPattern[] = [
['date-of-birth', defaultFormConfig.patterns['date-of-birth']],
['email-input', defaultFormConfig.patterns['email-input']],
['form-summary', defaultFormConfig.patterns['form-summary']],
['gender-id', defaultFormConfig.patterns['gender-id']],
['input', defaultFormConfig.patterns['input']],
['package-download', defaultFormConfig.patterns['package-download']],
['paragraph', defaultFormConfig.patterns['paragraph']],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import type { Meta, StoryObj } from '@storybook/react';
import { userEvent, expect } from '@storybook/test';
import { within } from '@testing-library/react';

import { type GenderIdPattern } from '@atj/forms';
import { createPatternEditStoryMeta } from '../common/story-helper.js';
import FormEdit from '../../index.js';
import { enLocale as message } from '@atj/common';

const pattern: GenderIdPattern = {
id: 'gender-identity-1',
type: 'gender-id',
data: {
label: message.patterns.genderId.displayName,
required: false,
hint: undefined,
preferNotToAnswerText: message.patterns.genderId.preferNotToAnswerTextLabel,
},
};

const storyConfig: Meta = {
title: 'Edit components/GenderIdPattern',
...createPatternEditStoryMeta({
pattern,
}),
} as Meta<typeof FormEdit>;

export default storyConfig;

export const Basic: StoryObj<typeof FormEdit> = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const updatedLabel = 'Gender identity update';
const updatedHint = 'Updated hint for Gender identity';
const updatedPreferNotToAnswerText =
'Updated prefer not to share my gender identity text';

await userEvent.click(
canvas.getByText(message.patterns.genderId.displayName)
);

const labelInput = canvas.getByLabelText(
message.patterns.genderId.fieldLabel
);
await userEvent.clear(labelInput);
await userEvent.type(labelInput, updatedLabel);

const hintInput = canvas.getByLabelText(
message.patterns.genderId.hintLabel
);
await userEvent.clear(hintInput);
await userEvent.type(hintInput, updatedHint);

const preferNotToAnswerInput = canvas.getByLabelText(
message.patterns.genderId.preferNotToAnswerTextLabel
);
await userEvent.clear(preferNotToAnswerInput);
await userEvent.type(preferNotToAnswerInput, updatedPreferNotToAnswerText);

const form = labelInput?.closest('form');
form?.requestSubmit();

await expect(await canvas.findByText(updatedLabel)).toBeInTheDocument();
await expect(await canvas.findByText(updatedHint)).toBeInTheDocument();
await expect(
await canvas.findByText(updatedPreferNotToAnswerText)
).toBeInTheDocument();
},
};

export const WithoutHint: StoryObj<typeof FormEdit> = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const updatedLabel = 'Gender identity update';
const updatedPreferNotToAnswerText =
'Prefer not to update my gender identity';

await userEvent.click(
canvas.getByText(message.patterns.genderId.displayName)
);

const labelInput = canvas.getByLabelText(
message.patterns.genderId.fieldLabel
);
await userEvent.clear(labelInput);
await userEvent.type(labelInput, updatedLabel);

const preferNotToAnswerInput = canvas.getByLabelText(
message.patterns.genderId.preferNotToAnswerTextLabel
);
await userEvent.clear(preferNotToAnswerInput);
await userEvent.type(preferNotToAnswerInput, updatedPreferNotToAnswerText);

const form = labelInput?.closest('form');
form?.requestSubmit();

await expect(await canvas.findByText(updatedLabel)).toBeInTheDocument();
await expect(
await canvas.findByText(updatedPreferNotToAnswerText)
).toBeInTheDocument();
await expect(
await canvas.queryByLabelText(message.patterns.genderId.hintLabel)
).toBeNull();
},
};

export const WithoutCheckbox: StoryObj<typeof FormEdit> = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const updatedLabel = 'Gender identity update';
const updatedHint = 'Updated hint for Gender identity';

await userEvent.click(
canvas.getByText(message.patterns.genderId.displayName)
);

const labelInput = canvas.getByLabelText(
message.patterns.genderId.fieldLabel
);
await userEvent.clear(labelInput);
await userEvent.type(labelInput, updatedLabel);

const hintInput = canvas.getByLabelText(
message.patterns.genderId.hintLabel
);
await userEvent.clear(hintInput);
await userEvent.type(hintInput, updatedHint);

const form = labelInput?.closest('form');
form?.requestSubmit();

await expect(await canvas.findByText(updatedLabel)).toBeInTheDocument();
await expect(
await canvas.queryByLabelText(message.patterns.genderId.hintLabel)
).toBeNull();
},
};

export const Error: StoryObj<typeof FormEdit> = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);

await userEvent.click(
canvas.getByText(message.patterns.genderId.displayName)
);

const labelInput = canvas.getByLabelText(
message.patterns.genderId.fieldLabel
);
await userEvent.clear(labelInput);
labelInput.blur();

await expect(
await canvas.findByText(
message.patterns.selectDropdown.errorTextMustContainChar
)
).toBeInTheDocument();
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* @vitest-environment jsdom
*/
import { describeStories } from '../../../../test-helper.js';
import meta, * as stories from './GenderIdPatternEdit.stories.js';

describeStories(meta, stories);
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import classnames from 'classnames';
import React from 'react';

import { type GenderIdProps } from '@atj/forms';
import { type GenderIdPattern } from '@atj/forms';

import GenderId from '../../../../Form/components/GenderId/index.js';
import { PatternEditComponent } from '../../types.js';

import { PatternEditActions } from '../common/PatternEditActions.js';
import { PatternEditForm } from '../common/PatternEditForm.js';
import { usePatternEditFormContext } from '../common/hooks.js';
import { enLocale as message } from '@atj/common';
import styles from '../../formEditStyles.module.css';

const GenderIdPatternEdit: PatternEditComponent<GenderIdProps> = ({
focus,
previewProps,
}) => {
return (
<>
{focus ? (
<PatternEditForm
pattern={focus.pattern}
editComponent={<EditComponent pattern={focus.pattern} />}
></PatternEditForm>
) : (
<div
className={`${styles.genderIdPattern} padding-left-3 padding-bottom-3 padding-right-3`}
>
<GenderId {...previewProps} />
</div>
)}
</>
);
};

const EditComponent = ({ pattern }: { pattern: GenderIdPattern }) => {
const { fieldId, getFieldState, register } =
usePatternEditFormContext<GenderIdPattern>(pattern.id);
const label = getFieldState('label');
const hint = getFieldState('hint');
const preferNotToAnswerText = getFieldState('preferNotToAnswerText');

return (
<div className="grid-row grid-gap">
<div className="tablet:grid-col-6 mobile-lg:grid-col-12 margin-bottom-2">
<label
className={classnames('usa-label', {
'usa-label--error': label.error,
})}
>
{message.patterns.genderId.fieldLabel}
{label.error ? (
<span className="usa-error-message" role="alert">
{label.error.message}
</span>
) : null}
<input
className="usa-input"
id={fieldId('label')}
defaultValue={pattern.data.label}
{...register('label')}
type="text"
autoFocus
/>
</label>
</div>
<div className="tablet:grid-col-6 mobile-lg:grid-col-12 margin-bottom-2">
<label
className={classnames('usa-label', {
'usa-label--error': hint.error,
})}
>
{message.patterns.genderId.hintLabel}
{hint.error ? (
<span className="usa-error-message" role="alert">
{hint.error.message}
</span>
) : null}
<input
className="usa-input"
id={fieldId('hint')}
defaultValue={pattern.data.hint}
{...register('hint')}
type="text"
/>
</label>
</div>
<div className="tablet:grid-col-6 mobile-lg:grid-col-12 margin-bottom-2">
<label
className={classnames('usa-label', {
'usa-label--error': preferNotToAnswerText.error,
})}
>
{message.patterns.genderId.preferNotToAnswerTextLabel}
{preferNotToAnswerText.error ? (
<span className="usa-error-message" role="alert">
{preferNotToAnswerText.error.message}
</span>
) : null}
<input
className="usa-input"
id={fieldId('preferNotToAnswerText')}
defaultValue={''}
{...register('preferNotToAnswerText')}
type="text"
/>
</label>
</div>
<div className="grid-col-12">
<PatternEditActions>
<span className="usa-checkbox">
<input
style={{ display: 'inline-block' }}
className="usa-checkbox__input bg-primary-lighter"
type="checkbox"
id={fieldId('required')}
{...register('required')}
defaultChecked={pattern.data.required}
/>
<label
style={{ display: 'inline-block' }}
className="usa-checkbox__label"
htmlFor={fieldId('required')}
>
Required
</label>
</span>
</PatternEditActions>
</div>
</div>
);
};

export default GenderIdPatternEdit;
2 changes: 2 additions & 0 deletions packages/design/src/FormManager/FormEdit/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import DateOfBirthPatternEdit from './DateOfBirthPatternEdit.js';
import EmailInputPatternEdit from './EmailInputPatternEdit.js';
import FieldsetEdit from './FieldsetEdit.js';
import FormSummaryEdit from './FormSummaryEdit.js';
import GenderIdPatternEdit from './GenderIdPatternEdit/index.js';
import InputPatternEdit from './InputPatternEdit.js';
import PackageDownloadPatternEdit from './PackageDownloadPatternEdit.js';
import PageSetEdit from './PageSetEdit.js';
Expand All @@ -29,6 +30,7 @@ export const defaultPatternEditComponents: EditComponentForPattern = {
'email-input': EmailInputPatternEdit as PatternEditComponent,
fieldset: FieldsetEdit as PatternEditComponent,
'form-summary': FormSummaryEdit as PatternEditComponent,
'gender-id': GenderIdPatternEdit as PatternEditComponent,
input: InputPatternEdit as PatternEditComponent,
'package-download': PackageDownloadPatternEdit as PatternEditComponent,
page: PageEdit as PatternEditComponent,
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions packages/forms/src/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,18 @@ export type SocialSecurityNumberProps = PatternProps<{
value: string;
}>;

export type GenderIdProps = PatternProps<{
type: 'gender-id';
genderId: string;
hint?: string;
label: string;
required: boolean;
error?: FormError;
value: string;
preferNotToAnswerText?: string;
preferNotToAnswerChecked?: boolean;
}>;

export type SequenceProps = PatternProps<{
type: 'sequence';
}>;
Expand Down

0 comments on commit 4fafc9d

Please sign in to comment.