From 068c883f4b2b30245d174e8ae1ac7d5cb75db30e Mon Sep 17 00:00:00 2001 From: SteveGT96 Date: Wed, 16 Oct 2024 17:55:53 +0100 Subject: [PATCH] update: Update exam form --- package.json | 3 + .../admin/exams/editExam/EditExam.tsx | 25 +++-- .../admin/exams/examForm/ExamForm.tsx | 93 ++++++++++++++++--- .../admin/exams/examForm/consts.ts | 14 ++- .../admin/exams/examForm/styles.scss | 29 ++++++ .../accessories/admin/exams/examForm/types.ts | 6 +- .../admin/exams/examsTable/ExamsTable.tsx | 6 +- .../admin/exams/newExam/NewExam.tsx | 9 +- .../accessories/admin/exams/types.ts | 5 +- src/libraries/formDataHandling/functions.ts | 6 +- src/libraries/formDataHandling/types.ts | 1 + src/resources/i18n/en.json | 5 + 12 files changed, 167 insertions(+), 35 deletions(-) diff --git a/package.json b/package.json index 46eef8123..1401ca5c3 100644 --- a/package.json +++ b/package.json @@ -148,5 +148,8 @@ }, "_moduleAliases": { "@": "./dist" + }, + "volta": { + "node": "20.18.0" } } diff --git a/src/components/accessories/admin/exams/editExam/EditExam.tsx b/src/components/accessories/admin/exams/editExam/EditExam.tsx index 0fba7ec73..16da0c526 100644 --- a/src/components/accessories/admin/exams/editExam/EditExam.tsx +++ b/src/components/accessories/admin/exams/editExam/EditExam.tsx @@ -1,10 +1,10 @@ import { useAppDispatch, useAppSelector } from "libraries/hooks/redux"; -import React from "react"; +import React, { useEffect } from "react"; import { useTranslation } from "react-i18next"; import { Navigate, useLocation, useParams } from "react-router"; import { PATHS } from "../../../../../consts"; import { ExamDTO } from "../../../../../generated"; -import { updateExam } from "../../../../../state/exams"; +import { getExamRows, updateExam } from "../../../../../state/exams"; import ExamForm from "../examForm/ExamForm"; import { getInitialFields } from "../examForm/consts"; @@ -13,13 +13,26 @@ export const EditExam = () => { const { t } = useTranslation(); const { state }: { state: ExamDTO | undefined } = useLocation(); const { id } = useParams(); - const update = useAppSelector((state) => state.operations.update); + const update = useAppSelector((state) => state.exams.examUpdate); - const handleSubmit = (examDTO: ExamDTO) => { + const examRows: string[] | undefined = useAppSelector((state) => + state.exams.examRowsByExamCode.data?.map((row) => row.description!) + ); + + useEffect(() => { + if (id) { + dispatch(getExamRows(id)); + } + }, [dispatch, id]); + + const handleSubmit = ({ + rows, + ...examDTO + }: ExamDTO & { rows: string[] | undefined }) => { dispatch( updateExam({ code: examDTO.code!!, - examWithRowsDTO: { exam: examDTO, rows: [] }, + examWithRowsDTO: { exam: examDTO, rows }, }) ); }; @@ -35,7 +48,7 @@ export const EditExam = () => { isLoading={!!update.isLoading} resetButtonLabel={t("common.cancel")} submitButtonLabel={t("exam.updateExam")} - fields={getInitialFields(state)} + fields={getInitialFields(state, examRows)} /> ); }; diff --git a/src/components/accessories/admin/exams/examForm/ExamForm.tsx b/src/components/accessories/admin/exams/examForm/ExamForm.tsx index 839d9b6d9..bf74c99aa 100644 --- a/src/components/accessories/admin/exams/examForm/ExamForm.tsx +++ b/src/components/accessories/admin/exams/examForm/ExamForm.tsx @@ -10,7 +10,7 @@ import React, { } from "react"; import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router"; -import { number, object, string } from "yup"; +import { array, number, object, string } from "yup"; import checkIcon from "../../../../../assets/check-icon.png"; import warningIcon from "../../../../../assets/warning-icon.png"; import { PATHS } from "../../../../../consts"; @@ -28,6 +28,8 @@ import TextField from "../../../textField/TextField"; import "./styles.scss"; import { IExamProps } from "./types"; +import { AddCircle } from "@mui/icons-material"; +import { IconButton } from "@mui/material"; import { useAppDispatch, useAppSelector } from "libraries/hooks/redux"; import AutocompleteField from "../../../autocompleteField/AutocompleteField"; import InfoBox from "../../../infoBox/InfoBox"; @@ -60,6 +62,15 @@ const ExamForm: FC = ({ [examTypeState.data] ); + const procedureOptions = useMemo( + () => [ + { value: "1", label: t("exam.procedures.1") }, + { value: "2", label: t("exam.procedures.2") }, + { value: "3", label: t("exam.procedures.3") }, + ], + [t] + ); + const errorMessage = useMemo( () => (creationMode @@ -79,6 +90,18 @@ const ExamForm: FC = ({ code: string().required(t("common.required")), description: string().required(t("common.required")), examtype: string().required(t("common.required")), + rows: array() + .of(string().required(t("common.required"))) + .test({ + name: "min", + exclusive: true, + test: function (value) { + return parseInt(this.parent.procedure) === 3 + ? true + : (value as string[]).length <= 2; + }, + message: t("exam.minLength"), + }), procedure: number() .test({ name: "onetwothree", @@ -119,11 +142,34 @@ const ExamForm: FC = ({ navigate(-1); }; + const addExamRow = useCallback(() => { + formik.setFieldValue("rows", [...formik.values.rows, ""]); + }, [formik]); + + const removeExamRow = useCallback( + (index: number) => () => { + formik.setFieldValue( + "rows", + (formik.values.rows as string[]).splice(index, 1) + ); + }, + [formik] + ); + const onBlurCallback = useCallback( (fieldName: string) => (e: React.FocusEvent, value: string) => { handleBlur(e); setFieldValue(fieldName, value); + if (fieldName === "procedure") { + const rows = formik.values.rows as string[]; + if (parseInt(value) === 3) { + setFieldValue("rows", []); + } else if (rows.length < 2) { + setFieldValue("rows", rows.length === 1 ? [rows[0], ""] : ["", ""]); + } + console.log(formik.values.rows); + } }, [handleBlur, setFieldValue] ); @@ -193,18 +239,7 @@ const ExamForm: FC = ({ fieldName="selectedType" fieldValue={formik.values.procedure} label={t("exam.procedure")} - options={[ - { - label: '1: a list of available "string" results', - value: "1", - }, - { label: '2: a list of all "boolean" results', value: "2" }, - { - label: - "3: exact value (it will be typed in by the laboratorist)", - value: "3", - }, - ]} + options={procedureOptions} errorText={getErrorText("procedure")} isValid={isValid("procedure")} onChange={(v) => formik.setFieldValue("procedure", v)} @@ -226,6 +261,38 @@ const ExamForm: FC = ({ + {["1", "2"].includes(formik.values.procedure) && ( +
+
+ Exam options + {isValid("rows") && ( + {getErrorText("rows")} + )} +
+ {(formik.values.rows as string[]).map((_, index) => ( +
+ +
+ ))} + + + +
+ )} +