Skip to content

Commit

Permalink
fix: Use fieldset and legend for Question and DateInput components (#742
Browse files Browse the repository at this point in the history
)

* fix: Wrap question component in fieldset w/ legend

* fix: Wrap dateInput component in fieldset w/ legend

* fix: Add labels to DateInput
Update CSS to ensure adequate spacing
Remove old label in preview/unpublished views

* fix: Remove redundant placeholder property

* fix: Add maxLength to date input

Required some changes to how paddedDate function worked. Added an eventType to allow differing behaviour on blur and input.

Tests updated and coverage added for max length
  • Loading branch information
DafyddLlyr authored Dec 8, 2021
1 parent a4486dd commit 352058d
Show file tree
Hide file tree
Showing 6 changed files with 238 additions and 144 deletions.
53 changes: 25 additions & 28 deletions editor.planx.uk/src/@planx/components/DateInput/Editor.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Box from "@material-ui/core/Box";
import { DateInput, paddedDate } from "@planx/components/DateInput/model";
import { dateSchema, parseDateInput } from "@planx/components/DateInput/model";
import { TYPES } from "@planx/components/types";
Expand Down Expand Up @@ -58,14 +59,6 @@ const DateInputComponent: React.FC<Props> = (props) => {
onChange={formik.handleChange}
/>
</InputRow>
<InputRow>
<RichTextInput
placeholder="Placeholder"
name="placeholder"
value={formik.values.placeholder}
onChange={formik.handleChange}
/>
</InputRow>
<InputRow>
<Input
// required
Expand All @@ -76,26 +69,30 @@ const DateInputComponent: React.FC<Props> = (props) => {
onChange={formik.handleChange}
/>
</InputRow>
<InputRow>
<DateInputUi
label="min"
value={formik.values.min}
error={formik.errors.min}
onChange={(newDate) => {
formik.setFieldValue("min", paddedDate(newDate));
}}
/>
</InputRow>
<InputRow>
<DateInputUi
label="max"
value={formik.values.max}
error={formik.errors.max}
onChange={(newDate) => {
formik.setFieldValue("max", paddedDate(newDate));
}}
/>
</InputRow>
<Box mt={2}>
<InputRow>
<DateInputUi
label="min"
value={formik.values.min}
error={formik.errors.min}
onChange={(newDate: string, eventType: string) => {
formik.setFieldValue("min", paddedDate(newDate, eventType));
}}
/>
</InputRow>
</Box>
<Box mt={2}>
<InputRow>
<DateInputUi
label="max"
value={formik.values.max}
error={formik.errors.max}
onChange={(newDate: string, eventType: string) => {
formik.setFieldValue("max", paddedDate(newDate, eventType));
}}
/>
</InputRow>
</Box>
</ModalSectionContent>
</ModalSection>
<MoreInformation
Expand Down
49 changes: 41 additions & 8 deletions editor.planx.uk/src/@planx/components/DateInput/Public.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ test("allows user to type into input field and click continue", async () => {

await act(async () => {
await userEvent.type(day, "2");
// Trigger blur event
await userEvent.tab();
});

expect(day).toHaveValue("02");
Expand All @@ -131,17 +133,48 @@ test("allows user to type into input field and click continue", async () => {
expect(handleSubmit).toHaveBeenCalled();
});

test("padding", () => {
// Adds zero to single digits
expect(paddedDate("2021-12-2")).toBe("2021-12-02");
expect(paddedDate("2021-3-22")).toBe("2021-03-22");
expect(paddedDate("2021-1-2")).toBe("2021-01-02");
test("date fields have a max length set", async () => {
render(<DateInput title="Enter a date" />);

const day = screen.getByPlaceholderText("DD") as HTMLInputElement;
const month = screen.getByPlaceholderText("MM") as HTMLInputElement;
const year = screen.getByPlaceholderText("YYYY") as HTMLInputElement;

expect(day.maxLength === 2);
expect(month.maxLength === 2);
expect(year.maxLength === 4);
});

test("padding on input", () => {
// Adds zero to single digits greater than 3 on input
expect(paddedDate("2021-12-6", "input")).toBe("2021-12-06");
expect(paddedDate("2021-4-22", "input")).toBe("2021-04-22");
expect(paddedDate("2021-8-4", "input")).toBe("2021-08-04");

// Leaves valid dates alone
expect(paddedDate("2021-01-06", "input")).toBe("2021-01-06");
expect(paddedDate("2021-04-22", "input")).toBe("2021-04-22");
expect(paddedDate("2021-08-04", "input")).toBe("2021-08-04");

// Leaves single 0 alone
expect(paddedDate("2021-0-4", "input")).toBe("2021-0-04");
expect(paddedDate("2021-10-0", "input")).toBe("2021-10-0");
});

test("padding on blur", () => {
// Adds zero to single digits less than or equal to 3 on blur
expect(paddedDate("2021-12-1", "blur")).toBe("2021-12-01");
expect(paddedDate("2021-3-22", "blur")).toBe("2021-03-22");
expect(paddedDate("2021-2-2", "blur")).toBe("2021-02-02");

// Removes extraneous zeroes
expect(paddedDate("2021-010-2")).toBe("2021-10-02");
// Leaves valid dates alone
expect(paddedDate("2021-01-06", "blur")).toBe("2021-01-06");
expect(paddedDate("2021-04-22", "blur")).toBe("2021-04-22");
expect(paddedDate("2021-08-04", "blur")).toBe("2021-08-04");

// Leaves single 0 alone
expect(paddedDate("2021-0-2")).toBe("2021-0-02");
expect(paddedDate("2021-0-2", "blur")).toBe("2021-0-02");
expect(paddedDate("2021-10-0", "blur")).toBe("2021-10-0");
});

test("validation", async () => {
Expand Down
46 changes: 29 additions & 17 deletions editor.planx.uk/src/@planx/components/DateInput/Public.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { makeStyles } from "@material-ui/core/styles";
import {
DateInput,
paddedDate,
Expand All @@ -17,6 +18,12 @@ import { getPreviouslySubmittedData, makeData } from "../shared/utils";

export type Props = PublicProps<DateInput, UserData>;

const useClasses = makeStyles(() => ({
fieldset: {
border: 0,
},
}));

const DateInputPublic: React.FC<Props> = (props) => {
const formik = useFormik({
initialValues: {
Expand All @@ -32,26 +39,31 @@ const DateInputPublic: React.FC<Props> = (props) => {
}),
});

const classes = useClasses();

return (
<Card handleSubmit={formik.handleSubmit}>
<QuestionHeader
title={props.title}
description={props.description}
info={props.info}
policyRef={props.policyRef}
howMeasured={props.howMeasured}
/>
<InputRow>
<DateInputComponent
value={formik.values.date}
bordered
onChange={(newDate: string) => {
// Pad it here if necessary; keep DateInputComponent simple
formik.setFieldValue("date", paddedDate(newDate));
}}
error={formik.errors.date as string}
<fieldset className={classes.fieldset}>
<legend aria-label={props.title}></legend>
<QuestionHeader
title={props.title}
description={props.description}
info={props.info}
policyRef={props.policyRef}
howMeasured={props.howMeasured}
/>
</InputRow>
<InputRow>
<DateInputComponent
value={formik.values.date}
bordered
onChange={(newDate: string, eventType: string) => {
// Pad it here if necessary; keep DateInputComponent simple
formik.setFieldValue("date", paddedDate(newDate, eventType));
}}
error={formik.errors.date as string}
/>
</InputRow>
</fieldset>
</Card>
);
};
Expand Down
15 changes: 8 additions & 7 deletions editor.planx.uk/src/@planx/components/DateInput/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ export type UserData = string;
export interface DateInput extends MoreInformation {
title: string;
description?: string;
placeholder?: string;
fn?: string;
min?: string;
max?: string;
Expand All @@ -22,7 +21,7 @@ export const isDateValid = (date: string) => {
return isComplete && isValid(parseISO(date));
};

export const paddedDate = (date: string) => {
export const paddedDate = (date: string, eventType: string) => {
const [year, month, day] = date.split("-");

// If month and/or year is single-digit, pad it
Expand All @@ -32,13 +31,16 @@ export const paddedDate = (date: string) => {
return value;
}

if (value.length === 1) {
// If the first number is greater than 3, it cannot be a valid day/month
// Automatically pad with a 0
if (parseInt(value) > 3) {
return value.padStart(2, "0");
}

// If it's already been padded, remove extraneous 0
if (value.length > 2 && value[0] === "0") {
return value.slice(1);
// When the field has been blurred, the user has completed their input
// If the value is < 10, pad with a 0
if (eventType === "blur" && value.length === 1) {
return value.padStart(2, "0");
}

// Otherwise change nothing
Expand Down Expand Up @@ -97,7 +99,6 @@ export const parseDateInput = (
): DateInput => ({
title: data?.title || "",
description: data?.description,
placeholder: data?.placeholder,
fn: data?.fn,
min: data?.min,
max: data?.max,
Expand Down
100 changes: 55 additions & 45 deletions editor.planx.uk/src/@planx/components/Question/Public/Question.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Grid from "@material-ui/core/Grid";
import { useTheme } from "@material-ui/core/styles";
import { makeStyles } from "@material-ui/core/styles";
import DecisionButton from "@planx/components/shared/Buttons/DecisionButton";
import DescriptionButton from "@planx/components/shared/Buttons/DescriptionButton";
import ImageButton from "@planx/components/shared/Buttons/ImageButton";
Expand Down Expand Up @@ -33,8 +34,15 @@ enum Layout {
Descriptions,
}

const useClasses = makeStyles(() => ({
fieldset: {
border: 0,
},
}));

const Question: React.FC<IQuestion> = (props) => {
const theme = useTheme();
const classes = useClasses();

const formik = useFormik({
initialValues: {
Expand Down Expand Up @@ -65,53 +73,55 @@ const Question: React.FC<IQuestion> = (props) => {
return (
<Card>
<form onSubmit={formik.handleSubmit}>
<QuestionHeader
title={props.text}
description={props.description}
info={props.info}
policyRef={props.policyRef}
howMeasured={props.howMeasured}
definitionImg={props.definitionImg}
img={props.img}
/>

<Grid container spacing={layout === Layout.Descriptions ? 2 : 1}>
{!props.text?.startsWith("Sorry") &&
props.responses?.map((response) => {
const onClick = () => {
formik.setFieldValue("selected.id", response.id);
formik.setFieldValue("selected.a", response.responseKey);
formik.submitForm();
};
const selected = a === response.responseKey;
const buttonProps = {
selected,
onClick,
};
<fieldset className={classes.fieldset}>
<legend aria-label={props.text}></legend>
<QuestionHeader
title={props.text}
description={props.description}
info={props.info}
policyRef={props.policyRef}
howMeasured={props.howMeasured}
definitionImg={props.definitionImg}
img={props.img}
/>
<Grid container spacing={layout === Layout.Descriptions ? 2 : 1}>
{!props.text?.startsWith("Sorry") &&
props.responses?.map((response) => {
const onClick = () => {
formik.setFieldValue("selected.id", response.id);
formik.setFieldValue("selected.a", response.responseKey);
formik.submitForm();
};
const selected = a === response.responseKey;
const buttonProps = {
selected,
onClick,
};

switch (layout) {
case Layout.Basic:
return (
<Grid item xs={12} key={response.id}>
<DecisionButton {...buttonProps} {...response} />
</Grid>
);
case Layout.Descriptions:
return (
<Grid item xs={6} sm={4} key={response.id}>
<DescriptionButton {...buttonProps} {...response} />
</Grid>
);
switch (layout) {
case Layout.Basic:
return (
<Grid item xs={12} key={response.id}>
<DecisionButton {...buttonProps} {...response} />
</Grid>
);
case Layout.Descriptions:
return (
<Grid item xs={6} sm={4} key={response.id}>
<DescriptionButton {...buttonProps} {...response} />
</Grid>
);

case Layout.Images:
return (
<Grid item xs={12} sm={6} key={response.id}>
<ImageButton {...buttonProps} {...response} />
</Grid>
);
}
})}
</Grid>
case Layout.Images:
return (
<Grid item xs={12} sm={6} key={response.id}>
<ImageButton {...buttonProps} {...response} />
</Grid>
);
}
})}
</Grid>
</fieldset>
</form>
</Card>
);
Expand Down
Loading

0 comments on commit 352058d

Please sign in to comment.