Skip to content

Commit

Permalink
issue #231: record keeping
Browse files Browse the repository at this point in the history
  • Loading branch information
k-allagbe committed Feb 7, 2025
1 parent f73522b commit c65190c
Show file tree
Hide file tree
Showing 15 changed files with 250 additions and 156 deletions.
6 changes: 3 additions & 3 deletions public/locales/en/confirmationPage.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
},
"ingredients": {
"sectionTitle": "Ingredients",
"nutrients": "Nutrients"
"nutrients": "Nutrients",
"recordKeeping": "Record Keeping"
},
"bilingualTable": {
"tableHeaders": {
Expand All @@ -56,9 +57,8 @@
"confirmingButton": "Confirming",
"editButton": "Edit Details"
},
"expandRetractButton":{
"expandRetractButton": {
"expandButton": "Hide image and show only label information.",
"retractButton": "Show image and label information."
}

}
17 changes: 9 additions & 8 deletions public/locales/en/labelDataValidator.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,14 @@
"stepTitle": "Instructions"
},
"ingredients": {
"stepTitle": "Ingredients"
"stepTitle": "Ingredients",
"recordKeeping": "Record Keeping",
"helpIcon": "Help Icon",
"labellingOptions": "Labelling Options",
"helpMessage": {
"recordKeeping": "Indicate whether a statement is used to specify that the product contains only registered or exempted ingredients, instead of detailing each individual ingredient."
},
"nutrients": "Nutrients"
},
"guaranteedAnalysis": {
"stepTitle": "Guaranteed Analysis",
Expand All @@ -49,13 +56,7 @@
"labelEn": "English",
"placeholderEn": "Enter English title",
"isMinimal": "The analysis is minimal",
"recordKeeping": "Record Keeping",
"labellingOptions": "Labelling Options",
"nutrients": "Nutrients",
"helpIcon": "Help Icon",
"helpMessage": {
"recordKeeping": "Indicate whether a statement is used to specify that the product contains only registered or exempted ingredients, instead of detailing each individual ingredient."
}
"nutrients": "Nutrients"
},
"verifiedInput": {
"verify": "Mark {{label}} as Verified",
Expand Down
5 changes: 3 additions & 2 deletions public/locales/fr/confirmationPage.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
},
"ingredients": {
"sectionTitle": "Ingrédients",
"nutrients": "Nutriments"
"nutrients": "Nutriments",
"recordKeeping": "Tenue de registres"
},
"bilingualTable": {
"tableHeaders": {
Expand All @@ -56,7 +57,7 @@
"confirmingButton": "Confirmation en cours",
"editButton": "Modifier les détails"
},
"expandRetractButton":{
"expandRetractButton": {
"expandButton": "Masquer l'image et afficher uniquement les informations de l'étiquette.",
"retractButton": "Afficher l'image et les informations de l'étiquette."
},
Expand Down
17 changes: 9 additions & 8 deletions public/locales/fr/labelDataValidator.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,14 @@
"stepTitle": "Instructions"
},
"ingredients": {
"stepTitle": "Ingrédients"
"stepTitle": "Ingrédients",
"recordKeeping": "Tenue de registres",
"labellingOptions": "Options d'étiquetage",
"helpIcon": "Icône d'aide",
"helpMessage": {
"recordKeeping": "Indiquez si une déclaration est utilisée pour préciser que le produit contient uniquement des ingrédients enregistrés ou exemptés, au lieu de détailler chaque ingrédient individuellement."
},
"nutrients": "Nutriments"
},
"guaranteedAnalysis": {
"stepTitle": "Analyse Garantie",
Expand All @@ -49,13 +56,7 @@
"labelEn": "Anglais",
"placeholderEn": "Entrez le titre en anglais",
"isMinimal": "L'analyse est minimale",
"recordKeeping": "Tenue de registres",
"labellingOptions": "Options d'étiquetage",
"nutrients": "Nutriments",
"helpIcon": "Icône d'aide",
"helpMessage":{
"recordKeeping":"Indiquez si une déclaration est utilisée pour préciser que le produit contient uniquement des ingrédients enregistrés ou exemptés, au lieu de détailler chaque ingrédient individuellement."
}
"nutrients": "Nutriments"
},
"verifiedInput": {
"verify": "Marquer {{label}} comme vérifié",
Expand Down
35 changes: 20 additions & 15 deletions src/app/label-data-confirmation/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,7 @@ import { useTranslation } from "react-i18next";
const LabelDataConfirmationPage = () => {
const labelData = useLabelDataStore((state) => state.labelData);
const setLabelData = useLabelDataStore((state) => state.setLabelData);
const resetLabelData = useLabelDataStore((state) => state.resetLabelData);
const uploadedFiles = useUploadedFilesStore((state) => state.uploadedFiles);
const clearUploadedFiles = useUploadedFilesStore(
(state) => state.clearUploadedFiles,
);
const imageFiles = uploadedFiles.map((file) => file.getFile());
const router = useRouter();
const [loading, setLoading] = useState(false);
Expand All @@ -68,8 +64,6 @@ const LabelDataConfirmationPage = () => {
)
.then(() => {
showAlert("Label data saved successfully.", "success");
resetLabelData();
clearUploadedFiles();
router.push("/");
})
.catch((error) => {
Expand Down Expand Up @@ -100,8 +94,9 @@ const LabelDataConfirmationPage = () => {
if (!response.data.inspectionId) {
throw new Error("ID missing in initial label data saving response.");
}
setLabelData(response.data);
putLabelData(response.data, signal);
const _labelData = { ...labelData, inspectionId: response.data.inspectionId };
setLabelData(_labelData);
putLabelData(_labelData, signal);
})
.catch((error) => {
showAlert(
Expand Down Expand Up @@ -162,6 +157,10 @@ const LabelDataConfirmationPage = () => {
}
}, [imageFiles, labelData, router, showAlert]);

useEffect(() => {
console.debug("Label data:", labelData);
}, [labelData, confirmed]);

const { isDownXs, isBetweenXsSm, isBetweenSmMd, isBetweenMdLg } =
useBreakpoints();
const isLgOrBelow =
Expand Down Expand Up @@ -539,15 +538,21 @@ const LabelDataConfirmationPage = () => {
>
{t("ingredients.sectionTitle")}
</Typography>
<Box>
{!labelData?.ingredients?.recordKeeping?.value ? (
<Box>
<Typography className="!font-bold mb-2 text-left">
{t("ingredients.nutrients")}
</Typography>
<BilingualTable
data={labelData?.ingredients.nutrients ?? []}
data-testid="ingredients-nutrients-table"
/>
</Box>
) : (
<Typography className="!font-bold mb-2 text-left">
{t("ingredients.nutrients")}
{t("ingredients.recordKeeping")}
</Typography>
<BilingualTable
data={labelData?.ingredients ?? []}
data-testid="ingredients-nutrients-table"
/>
</Box>
)}
</Box>
</Box>

Expand Down
57 changes: 34 additions & 23 deletions src/components/IngredientsForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,8 @@ function IngredientsForm({
defaultValues: labelData,
});
const sectionName = "ingredients";

const { control } = methods;

const watchedIngredients = useWatch({
control,
name: sectionName,
});

const watchedIngredients = useWatch({ control, name: sectionName });
const save = useDebouncedSave(setLabelData);

useEffect(() => {
Expand All @@ -35,6 +29,7 @@ function IngredientsForm({
}, [labelData, methods]);

useEffect(() => {
console.log("watchedIngredients", watchedIngredients);
save(sectionName, watchedIngredients);
}, [watchedIngredients, save]);

Expand All @@ -46,24 +41,40 @@ function IngredientsForm({
fontWeight="bold"
data-testid="guaranteed-analysis-title"
>
{t("guaranteedAnalysis.labellingOptions")}
{t("ingredients.labellingOptions")}
</Typography>
<Box className="flex flex-shrink-0 mb-4">
<VerifiedRadio
label={t("guaranteedAnalysis.recordKeeping")}
path="ingredients.recordKeeping"
loading={loading}
isHelpActive={true}
helpText={t("guaranteedAnalysis.helpMessage.recordKeeping")}
data-testid="guaranteed-analysis-record-keeping"
/>
<Box className="grid grid-cols-1 items-start sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-1 xxl:grid-cols-2 gap-4 p-4">
<Box className="flex flex-shrink-0">
<VerifiedRadio
label={t("ingredients.recordKeeping")}
path="ingredients.recordKeeping"
loading={loading}
isHelpActive={true}
helpText={t("ingredients.helpMessage.recordKeeping")}
data-testid="guaranteed-analysis-record-keeping"
/>
</Box>
</Box>
<VerifiedBilingualTable
path={sectionName}
unitOptions={UNITS.ingredients}
valueColumn
loading={loading}
/>
{!watchedIngredients?.recordKeeping.value && (
<>
<Typography
variant="subtitle1"
fontWeight="bold"
className="!mt-16"
data-testid="guaranteed-analysis-nutrients-title"
>
{t("ingredients.nutrients")}
</Typography>
<Box className="px-4">
<VerifiedBilingualTable
path={"ingredients.nutrients"}
unitOptions={UNITS.ingredients}
valueColumn
loading={loading}
/>
</Box>
</>
)}
</Box>
</FormProvider>
);
Expand Down
5 changes: 4 additions & 1 deletion src/components/LabelDataValidator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,10 @@ function LabelDataValidator({
}, [labelData.guaranteedAnalysis, setGuaranteedAnalysisStepStatus]);

useEffect(() => {
const verified = checkFieldArray(labelData.ingredients);
const verified =
checkFieldRecord({
recordKeeping: labelData.ingredients.recordKeeping,
}) && checkFieldArray(labelData.ingredients.nutrients);
setIngredientsStepStatus(
verified ? StepStatus.Completed : StepStatus.Incomplete,
);
Expand Down
42 changes: 23 additions & 19 deletions src/components/VerifiedFieldComponents.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import CheckIcon from "@mui/icons-material/Check";
import HelpIcon from "@mui/icons-material/Help";
import HelpOutlineIcon from "@mui/icons-material/HelpOutline";
import {
Box,
Divider,
Expand All @@ -15,8 +17,6 @@ import { Control, Controller, useFormContext, useWatch } from "react-hook-form";
import { useTranslation } from "react-i18next";
import StyledSkeleton from "./StyledSkeleton";
import StyledTextField from "./StyledTextField";
import HelpOutlineIcon from "@mui/icons-material/HelpOutline";
import HelpIcon from "@mui/icons-material/Help";

interface VerifiedFieldWrapperProps {
label: ReactNode;
Expand Down Expand Up @@ -52,13 +52,7 @@ export const VerifiedFieldWrapper: React.FC<VerifiedFieldWrapperProps> = ({

return (
<Box>
<Typography
className="px-2 !font-bold select-none text-left"
data-testid={`field-label-${path}`}
>
{label}
</Typography>

<>{label}</>
{loading ? (
<StyledSkeleton />
) : (
Expand Down Expand Up @@ -147,7 +141,10 @@ export const VerifiedRadio: React.FC<VerifiedRadioProps> = ({
<VerifiedFieldWrapper
label={
<Box className="flex items-start">
<Typography className="!font-bold select-none text-left">
<Typography
className="!font-bold select-none text-left pl-2"
data-testid={`field-label-${path}`}
>
{label}
</Typography>
{isHelpActive && (
Expand All @@ -160,9 +157,15 @@ export const VerifiedRadio: React.FC<VerifiedRadioProps> = ({
className="!bg-transparent p-0"
>
{hoverHelp ? (
<HelpIcon className="-mt-2 -mb-4" style={{fontSize:"20"}}/>
<HelpIcon
className="-mt-2 -mb-4"
style={{ fontSize: "20" }}
/>
) : (
<HelpOutlineIcon className="-mt-2 -mb-4" style={{fontSize:"20"}}/>
<HelpOutlineIcon
className="-mt-2 -mb-4"
style={{ fontSize: "20" }}
/>
)}
</IconButton>
</Tooltip>
Expand All @@ -183,12 +186,6 @@ export const VerifiedRadio: React.FC<VerifiedRadioProps> = ({
onChange={(e) => field.onChange(e.target.value === "yes")}
className="flex-1 !flex-row px-2 "
onFocus={() => setIsFocused(true)}
onBlur={(e) => {
setIsFocused(false);
if (field.value.trim() !== (e.target as HTMLInputElement).value.trim()) {
field.onChange((e.target as HTMLInputElement).value.trim());
}
}}
data-testid={`radio-group-field-${valuePath}`}
aria-label={`${t("verifiedInput.accessibility.radioGroup", { label })}`}
>
Expand Down Expand Up @@ -241,7 +238,14 @@ export const VerifiedInput: React.FC<VerifiedInputProps> = ({

return (
<VerifiedFieldWrapper
label={label}
label={
<Typography
className="!font-bold select-none text-left px-2"
data-testid={`field-label-${path}`}
>
{label}
</Typography>
}
path={path}
className={className}
loading={loading}
Expand Down
6 changes: 4 additions & 2 deletions src/components/__tests__/IngredientsForm.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@ const Wrapper = ({
describe("IngredientsForm Rendering", () => {
it("should render the title input fields and nutrients table", () => {
render(<Wrapper initialData={DEFAULT_LABEL_DATA} />);

expect(
screen.getByTestId("verified-field-ingredients.recordKeeping"),
).toBeInTheDocument();
expect(screen.getByTestId("ingredients-form")).toBeInTheDocument();
expect(
screen.getByTestId("table-container-ingredients"),
screen.getByTestId("table-container-ingredients.nutrients"),
).toBeInTheDocument();
});
});
15 changes: 10 additions & 5 deletions src/components/__tests__/LabelDataValidator.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -433,15 +433,20 @@ describe("LabelDataValidator and Forms Integration", () => {
});

const verifyButtons = screen.getAllByTestId(
/verify-row-btn-ingredients-\d+/,
/verify-row-btn-ingredients.nutrients-\d+/,
);
expect(verifyButtons.length).toBeGreaterThanOrEqual(1);

for (const button of verifyButtons) {
await act(async () => {
await act(async () => {
fireEvent.click(
screen.getByTestId(
"toggle-verified-btn-ingredients.recordKeeping.verified",
),
);
for (const button of verifyButtons) {
fireEvent.click(button);
});
}
}
});

await act(async () => {
await new Promise((resolve) => setTimeout(resolve, 350));
Expand Down
Loading

0 comments on commit c65190c

Please sign in to comment.