From 6ef441ad307215d38a50b2ef1bfd1111e0829e72 Mon Sep 17 00:00:00 2001 From: "K. Allagbe" Date: Mon, 25 Nov 2024 17:18:17 -0500 Subject: [PATCH 1/7] issue #326: cautions step --- public/locales/en/labelDataValidationPage.json | 9 ++++++--- public/locales/fr/labelDataValidationPage.json | 9 ++++++--- .../label-data-validation/__tests__/page.test.tsx | 11 ++++++++--- src/app/label-data-validation/page.tsx | 10 ++++++++++ src/components/CautionsForm.tsx | 12 ++++++++++++ 5 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 src/components/CautionsForm.tsx diff --git a/public/locales/en/labelDataValidationPage.json b/public/locales/en/labelDataValidationPage.json index b7484a2b..042922b3 100644 --- a/public/locales/en/labelDataValidationPage.json +++ b/public/locales/en/labelDataValidationPage.json @@ -1,7 +1,4 @@ { - "organizations": { - "stepTitle": "Organizations" - }, "baseInformation": { "stepTitle": "Base Information", "fields": { @@ -32,6 +29,12 @@ } } }, + "organizations": { + "stepTitle": "Organizations" + }, + "cautions": { + "stepTitle": "Cautions" + }, "verifiedQuantityMultiInput": { "deleteRow": "Delete this row", "defaultPlaceholder": "Enter value", diff --git a/public/locales/fr/labelDataValidationPage.json b/public/locales/fr/labelDataValidationPage.json index 5c3f9a07..10137a25 100644 --- a/public/locales/fr/labelDataValidationPage.json +++ b/public/locales/fr/labelDataValidationPage.json @@ -1,7 +1,4 @@ { - "organizations": { - "stepTitle": "Organisations" - }, "baseInformation": { "stepTitle": "Informations de base sur l'engrais", "fields": { @@ -32,6 +29,12 @@ } } }, + "organizations": { + "stepTitle": "Organisations" + }, + "cautions": { + "stepTitle": "Mises en garde" + }, "verifiedQuantityMultiInput": { "deleteRow": "Supprimer cette ligne", "defaultPlaceholder": "Entrez une valeur", diff --git a/src/app/label-data-validation/__tests__/page.test.tsx b/src/app/label-data-validation/__tests__/page.test.tsx index db1c68a9..c33d5de4 100644 --- a/src/app/label-data-validation/__tests__/page.test.tsx +++ b/src/app/label-data-validation/__tests__/page.test.tsx @@ -55,7 +55,8 @@ describe("LabelDataValidationPage Functionality", () => { fireEvent.click(nextButton); fireEvent.click(nextButton); - expect(screen.getByTestId("organizations-form")).toBeInTheDocument(); + fireEvent.click(nextButton); + expect(screen.getByTestId("cautions-form")).toBeInTheDocument(); }); it("renders the mocked Image Viewer", () => { @@ -70,7 +71,9 @@ describe("LabelDataValidationPage and OrganizationsForm Integration", () => { it("marks the Organizations step as Completed or Incomplete when fields are Verified", () => { render(); - const spans = screen.getAllByText("organizations.stepTitle", { exact: true }); + const spans = screen.getAllByText("organizations.stepTitle", { + exact: true, + }); const targetSpan = spans.find((span) => span.classList.contains("MuiStepLabel-label"), ); @@ -94,7 +97,9 @@ describe("LabelDataValidationPage and BaseInformationForm Integration", () => { it("marks the Base Information step as Completed or Incomplete when fields are Verified", async () => { render(); - const spans = screen.getAllByText("baseInformation.stepTitle", { exact: true }); + const spans = screen.getAllByText("baseInformation.stepTitle", { + exact: true, + }); const targetSpan = spans.find((span) => span.classList.contains("MuiStepLabel-label"), ); diff --git a/src/app/label-data-validation/page.tsx b/src/app/label-data-validation/page.tsx index cbd48301..acc79141 100644 --- a/src/app/label-data-validation/page.tsx +++ b/src/app/label-data-validation/page.tsx @@ -1,5 +1,6 @@ "use client"; import BaseInformationForm from "@/components/BaseInformationForm"; +import CautionsForm from "@/components/CautionsForm"; import ImageViewer from "@/components/ImageViewer"; import OrganizationsForm from "@/components/OrganizationsForm"; import { @@ -31,6 +32,9 @@ function LabelDataValidationPage() { useState(StepStatus.Incomplete); const [baseInformationStepStatus, setBaseInformationStepStatus] = useState(StepStatus.Incomplete); + const [cautionsStepStatus, setCautionsStepStatus] = useState( + StepStatus.Incomplete, + ); const createStep = ( title: string, @@ -61,6 +65,12 @@ function LabelDataValidationPage() { organizationsStepStatus, setOrganizationsStepStatus, ), + createStep( + t("cautions.stepTitle"), + CautionsForm, + cautionsStepStatus, + setCautionsStepStatus, + ), ]; const handleFileChange = (event: React.ChangeEvent) => { diff --git a/src/components/CautionsForm.tsx b/src/components/CautionsForm.tsx new file mode 100644 index 00000000..42b9327b --- /dev/null +++ b/src/components/CautionsForm.tsx @@ -0,0 +1,12 @@ +import { FormComponentProps } from "@/types/types"; +import { Box } from "@mui/material"; + +function CautionsForm({ labelData, setLabelData }: FormComponentProps) { + return ( + + CautionsForm + + ); +} + +export default CautionsForm; From c2e370afb4a16f29a5ed18dff997a8f14fc779cd Mon Sep 17 00:00:00 2001 From: "K. Allagbe" Date: Mon, 25 Nov 2024 20:41:46 -0500 Subject: [PATCH 2/7] issue #326: bilingual input table --- src/components/VerifiedBilingualTable.tsx | 235 ++++++++++++++++++++++ src/types/types.ts | 14 ++ 2 files changed, 249 insertions(+) create mode 100644 src/components/VerifiedBilingualTable.tsx diff --git a/src/components/VerifiedBilingualTable.tsx b/src/components/VerifiedBilingualTable.tsx new file mode 100644 index 00000000..0cafd434 --- /dev/null +++ b/src/components/VerifiedBilingualTable.tsx @@ -0,0 +1,235 @@ +import { BilingualField, DEFAULT_BILINGUAL_FIELD } from "@/types/types"; +import AddIcon from "@mui/icons-material/Add"; +import CheckIcon from "@mui/icons-material/Check"; +import DeleteIcon from "@mui/icons-material/Delete"; +import DoneAllIcon from "@mui/icons-material/DoneAll"; +import RemoveDoneIcon from "@mui/icons-material/RemoveDone"; +import { + Box, + Button, + Divider, + IconButton, + InputBase, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + Tooltip, + Typography, +} from "@mui/material"; +import { Controller, useFieldArray, useFormContext } from "react-hook-form"; + +const VerifiedBilingualTable = ({ path }: { path: string }) => { + const { control, setValue, getValues } = useFormContext(); + + const { fields, append, remove } = useFieldArray({ + control, + name: path, + }); + + const setAllVerified = (verified: boolean) => { + const rows = getValues(path).map((row: BilingualField) => ({ + ...row, + verified, + })); + setValue(path, rows); + }; + + return ( + + + + {/* Table Head */} + + + + + English + + + + + French + + + + + Actions + + + + + + {/* Table Body */} + + {fields.map((field, index) => ( + + {/* English input field */} + + ( + + )} + /> + + + {/* French input field */} + + ( + + )} + /> + + + {/* Action buttons (Delete and Verify) */} + + + {/* Delete Button */} + + + remove(index)} + disabled={getValues(`${path}.${index}.verified`)} + data-testid={`delete-row-btn-${path}-${index}`} + > + + + + + + + + {/* Verify Button */} + ( + + + onChange(!value)} + data-testid={`verify-row-btn-${path}-${index}`} + > + + + + + )} + /> + + + + ))} + +
+
+ + {/* Buttons to add rows and bulk verify/unverify */} + + {/* Add Row Button */} + + + {/* Mark all as Verified Button */} + row.verified, + )} + > + + + + + + {/* Mark all as Unverified Button */} + !row.verified, + )} + > + + + + + +
+ ); +}; + +export default VerifiedBilingualTable; diff --git a/src/types/types.ts b/src/types/types.ts index e817b4dc..30998745 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -135,15 +135,29 @@ export const DEFAULT_BASE_INFORMATION: BaseInformation = { volume: DEFAULT_QUANTITY_FIELD(UNITS.volume[0]), }; +// Caution +export type BilingualField = VerifiedField & { + en: string; + fr: string; +}; + +export const DEFAULT_BILINGUAL_FIELD: BilingualField = { + en: "", + fr: "", + verified: false, +}; + // LabelData export type LabelData = { organizations: Organization[]; baseInformation: BaseInformation; + cautions: BilingualField[]; }; export const DEFAULT_LABEL_DATA: LabelData = { organizations: [DEFAULT_ORGANIZATION], baseInformation: DEFAULT_BASE_INFORMATION, + cautions: [DEFAULT_BILINGUAL_FIELD], }; // Form From 169cb3bdf09be3ce12c9a28685ace8a0efa902e3 Mon Sep 17 00:00:00 2001 From: "K. Allagbe" Date: Mon, 25 Nov 2024 20:42:06 -0500 Subject: [PATCH 3/7] issue #326: cautions form --- src/components/CautionsForm.tsx | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/components/CautionsForm.tsx b/src/components/CautionsForm.tsx index 42b9327b..0d67b863 100644 --- a/src/components/CautionsForm.tsx +++ b/src/components/CautionsForm.tsx @@ -1,11 +1,36 @@ -import { FormComponentProps } from "@/types/types"; +import { FormComponentProps, LabelData } from "@/types/types"; import { Box } from "@mui/material"; +import { useEffect } from "react"; +import { FormProvider, useForm, useWatch } from "react-hook-form"; +import VerifiedBilingualTable from "./VerifiedBilingualTable"; function CautionsForm({ labelData, setLabelData }: FormComponentProps) { + const methods = useForm({ + defaultValues: labelData, + }); + + const { control } = methods; + + const watchedCautions = useWatch({ + control, + name: "cautions", + }); + + useEffect(() => { + if (watchedCautions) { + setLabelData((prevLabelData) => ({ + ...prevLabelData, + cautions: watchedCautions, + })); + } + }, [watchedCautions, setLabelData]); + return ( - - CautionsForm - + + + + + ); } From 6b7acb58b8bc38ccfde4f6a28aaf07b34aa63005 Mon Sep 17 00:00:00 2001 From: "K. Allagbe" Date: Mon, 25 Nov 2024 20:42:06 -0500 Subject: [PATCH 4/7] issue #326: cautions form --- src/app/label-data-validation/page.tsx | 7 ++++++ src/components/CautionsForm.tsx | 33 ++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/app/label-data-validation/page.tsx b/src/app/label-data-validation/page.tsx index acc79141..bddca5da 100644 --- a/src/app/label-data-validation/page.tsx +++ b/src/app/label-data-validation/page.tsx @@ -97,6 +97,13 @@ function LabelDataValidationPage() { ); }, [labelData.baseInformation, setBaseInformationStepStatus]); + useEffect(() => { + const verified = labelData.cautions.every((caution) => caution.verified); + setCautionsStepStatus( + verified ? StepStatus.Completed : StepStatus.Incomplete, + ); + }, [labelData.cautions, setCautionsStepStatus]); + return ( ({ + defaultValues: labelData, + }); + + const { control } = methods; + + const watchedCautions = useWatch({ + control, + name: "cautions", + }); + + useEffect(() => { + if (watchedCautions) { + setLabelData((prevLabelData) => ({ + ...prevLabelData, + cautions: watchedCautions, + })); + } + }, [watchedCautions, setLabelData]); + return ( - - CautionsForm - + + + + + ); } From 6073e0376d9c14a5b93f74f3d9d63e563b3ea51f Mon Sep 17 00:00:00 2001 From: "K. Allagbe" Date: Mon, 25 Nov 2024 22:14:01 -0500 Subject: [PATCH 5/7] issue #326: accessibility --- src/components/VerifiedBilingualTable.tsx | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/components/VerifiedBilingualTable.tsx b/src/components/VerifiedBilingualTable.tsx index 0cafd434..cd0984f8 100644 --- a/src/components/VerifiedBilingualTable.tsx +++ b/src/components/VerifiedBilingualTable.tsx @@ -86,6 +86,8 @@ const VerifiedBilingualTable = ({ path }: { path: string }) => { multiline fullWidth disabled={getValues(`${path}.${index}.verified`)} + aria-label={`English text for row ${index + 1}`} + aria-disabled={getValues(`${path}.${index}.verified`)} data-testid={`input-english-${path}-${index}`} /> )} @@ -105,6 +107,8 @@ const VerifiedBilingualTable = ({ path }: { path: string }) => { multiline fullWidth disabled={getValues(`${path}.${index}.verified`)} + aria-label={`French text for row ${index + 1}`} + aria-disabled={getValues(`${path}.${index}.verified`)} data-testid={`input-french-${path}-${index}`} /> )} @@ -126,9 +130,10 @@ const VerifiedBilingualTable = ({ path }: { path: string }) => { remove(index)} disabled={getValues(`${path}.${index}.verified`)} + aria-label="Delete row" data-testid={`delete-row-btn-${path}-${index}`} > - + @@ -151,10 +156,16 @@ const VerifiedBilingualTable = ({ path }: { path: string }) => { onChange(!value)} + aria-label={ + value + ? "Mark as Unverified" + : "Mark as Verified" + } data-testid={`verify-row-btn-${path}-${index}`} > @@ -176,7 +187,8 @@ const VerifiedBilingualTable = ({ path }: { path: string }) => { onClick={() => append(DEFAULT_BILINGUAL_FIELD)} variant="outlined" color="secondary" - startIcon={} + startIcon={