From aacfccbe2bd5d522e7da1a4b3869a6f470524a5a Mon Sep 17 00:00:00 2001 From: Jacobjohnjeevan Date: Mon, 27 May 2024 19:18:42 +0530 Subject: [PATCH 1/9] Added custom no results label for AutocompleteFormField - Added "no home facility doctors" as text for no results in User autocomplete field in Consultation Form. --- src/Components/Common/UserAutocompleteFormField.tsx | 2 ++ src/Components/Facility/ConsultationForm.tsx | 1 + src/Components/Form/FormFields/Autocomplete.tsx | 3 ++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Components/Common/UserAutocompleteFormField.tsx b/src/Components/Common/UserAutocompleteFormField.tsx index 11f0df6c52a..ecf0167cc11 100644 --- a/src/Components/Common/UserAutocompleteFormField.tsx +++ b/src/Components/Common/UserAutocompleteFormField.tsx @@ -16,6 +16,7 @@ type Props = FormFieldBaseProps & { homeFacility?: string; userType?: UserRole; showActiveStatus?: boolean; + noResultsLabel?: string; }; export default function UserAutocompleteFormField(props: Props) { @@ -83,6 +84,7 @@ export default function UserAutocompleteFormField(props: Props) { : getUserList({ ...search_filter, search_text: query }), ) } + noResultsLabel={props.noResultsLabel ?? "No options found"} isLoading={isLoading} /> diff --git a/src/Components/Facility/ConsultationForm.tsx b/src/Components/Facility/ConsultationForm.tsx index 8a9a19db2bc..6b4dac398f4 100644 --- a/src/Components/Facility/ConsultationForm.tsx +++ b/src/Components/Facility/ConsultationForm.tsx @@ -1414,6 +1414,7 @@ export const ConsultationForm = ({ facilityId, patientId, id }: Props) => { userType={"Doctor"} homeFacility={facilityId} error={state.errors.treating_physician} + noResultsLabel="No home facility doctors available" /> diff --git a/src/Components/Form/FormFields/Autocomplete.tsx b/src/Components/Form/FormFields/Autocomplete.tsx index e414fda233a..448c678667b 100644 --- a/src/Components/Form/FormFields/Autocomplete.tsx +++ b/src/Components/Form/FormFields/Autocomplete.tsx @@ -71,6 +71,7 @@ type AutocompleteProps = { isLoading?: boolean; allowRawInput?: boolean; error?: string; + noResultsLabel?: string; } & ( | { required?: false; @@ -195,7 +196,7 @@ export const Autocomplete = (props: AutocompleteProps) => { {filteredOptions.length === 0 && (
- No options found + {props.noResultsLabel ?? "No options found"}
)} {filteredOptions.map((option, index) => ( From 099e84c06cec4b40166a6994f023c532f7e3db42 Mon Sep 17 00:00:00 2001 From: Jacobjohnjeevan Date: Mon, 27 May 2024 19:20:49 +0530 Subject: [PATCH 2/9] Added notification for autocomplete - Display extra notification when there are no results for Assigned docs field (Consultation Form) - Only applicable to ConsultationForm --- .../Form/FormFields/Autocomplete.tsx | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/Components/Form/FormFields/Autocomplete.tsx b/src/Components/Form/FormFields/Autocomplete.tsx index 448c678667b..654a88f50b3 100644 --- a/src/Components/Form/FormFields/Autocomplete.tsx +++ b/src/Components/Form/FormFields/Autocomplete.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import { Combobox } from "@headlessui/react"; import { DropdownTransition } from "../../Common/components/HelperComponents"; import CareIcon from "../../../CAREUI/icons/CareIcon"; @@ -7,6 +7,7 @@ import { FormFieldBaseProps, useFormFieldPropsResolver } from "./Utils"; import FormField from "./FormField"; import { classNames } from "../../../Utils/utils"; import { useTranslation } from "react-i18next"; +import * as Notifications from "../../../Utils/Notifications.js"; type OptionCallback = (option: T) => R; @@ -137,6 +138,21 @@ export const Autocomplete = (props: AutocompleteProps) => { ? options.filter((o) => o.search.includes(query)) : options; + const prevQuery = useRef(""); + useEffect(() => { + if ( + query && + prevQuery.current !== query && + filteredOptions.length === 0 && + props.noResultsLabel + ) { + Notifications.Error({ + msg: props.noResultsLabel, + }); + } + prevQuery.current = query; + }, [query, filteredOptions, props.noResultsLabel]); + return (
Date: Mon, 29 Jul 2024 11:35:29 +0530 Subject: [PATCH 3/9] improve how no user error notification is dispatched --- src/Common/hooks/useAsyncOptions.ts | 2 +- .../Common/UserAutocompleteFormField.tsx | 19 ++++++++++++++--- .../Form/FormFields/Autocomplete.tsx | 21 ++----------------- 3 files changed, 19 insertions(+), 23 deletions(-) diff --git a/src/Common/hooks/useAsyncOptions.ts b/src/Common/hooks/useAsyncOptions.ts index 1a632dc366e..a81209f34f0 100644 --- a/src/Common/hooks/useAsyncOptions.ts +++ b/src/Common/hooks/useAsyncOptions.ts @@ -38,7 +38,7 @@ export function useAsyncOptions>( ) { const dispatch = useDispatch(); const [queryOptions, setQueryOptions] = useState([]); - const [isLoading, setIsLoading] = useState(false); + const [isLoading, setIsLoading] = useState(true); const fetchOptions = useMemo( () => diff --git a/src/Components/Common/UserAutocompleteFormField.tsx b/src/Components/Common/UserAutocompleteFormField.tsx index ecf0167cc11..3020df3a84b 100644 --- a/src/Components/Common/UserAutocompleteFormField.tsx +++ b/src/Components/Common/UserAutocompleteFormField.tsx @@ -9,6 +9,8 @@ import { import { UserModel } from "../Users/models"; import { isUserOnline } from "../../Utils/utils"; import { UserRole } from "../../Common/constants"; +import { useEffect } from "react"; +import { Error } from "../../Utils/Notifications"; type Props = FormFieldBaseProps & { placeholder?: string; @@ -60,16 +62,28 @@ export default function UserAutocompleteFormField(props: Props) { ); }; + const items = options(field.value && [field.value]); + + useEffect(() => { + if (props.required && !isLoading && !items.length && props.noResultsLabel) { + Error({ msg: props.noResultsLabel }); + } + }, [isLoading, items, props.required]); + return (
`${option.user_type}`} @@ -84,7 +98,6 @@ export default function UserAutocompleteFormField(props: Props) { : getUserList({ ...search_filter, search_text: query }), ) } - noResultsLabel={props.noResultsLabel ?? "No options found"} isLoading={isLoading} />
diff --git a/src/Components/Form/FormFields/Autocomplete.tsx b/src/Components/Form/FormFields/Autocomplete.tsx index 654a88f50b3..e414fda233a 100644 --- a/src/Components/Form/FormFields/Autocomplete.tsx +++ b/src/Components/Form/FormFields/Autocomplete.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from "react"; +import { useEffect, useState } from "react"; import { Combobox } from "@headlessui/react"; import { DropdownTransition } from "../../Common/components/HelperComponents"; import CareIcon from "../../../CAREUI/icons/CareIcon"; @@ -7,7 +7,6 @@ import { FormFieldBaseProps, useFormFieldPropsResolver } from "./Utils"; import FormField from "./FormField"; import { classNames } from "../../../Utils/utils"; import { useTranslation } from "react-i18next"; -import * as Notifications from "../../../Utils/Notifications.js"; type OptionCallback = (option: T) => R; @@ -72,7 +71,6 @@ type AutocompleteProps = { isLoading?: boolean; allowRawInput?: boolean; error?: string; - noResultsLabel?: string; } & ( | { required?: false; @@ -138,21 +136,6 @@ export const Autocomplete = (props: AutocompleteProps) => { ? options.filter((o) => o.search.includes(query)) : options; - const prevQuery = useRef(""); - useEffect(() => { - if ( - query && - prevQuery.current !== query && - filteredOptions.length === 0 && - props.noResultsLabel - ) { - Notifications.Error({ - msg: props.noResultsLabel, - }); - } - prevQuery.current = query; - }, [query, filteredOptions, props.noResultsLabel]); - return (
(props: AutocompleteProps) => { {filteredOptions.length === 0 && (
- {props.noResultsLabel ?? "No options found"} + No options found
)} {filteredOptions.map((option, index) => ( From 20c36ec0606f5c9fd1b4769fb199c4cb87a4894f Mon Sep 17 00:00:00 2001 From: rithviknishad Date: Mon, 29 Jul 2024 11:40:14 +0530 Subject: [PATCH 4/9] use translations --- src/Components/Facility/ConsultationForm.tsx | 2 +- src/Locale/en/Consultation.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Components/Facility/ConsultationForm.tsx b/src/Components/Facility/ConsultationForm.tsx index 6b4dac398f4..4624a7022fa 100644 --- a/src/Components/Facility/ConsultationForm.tsx +++ b/src/Components/Facility/ConsultationForm.tsx @@ -1414,7 +1414,7 @@ export const ConsultationForm = ({ facilityId, patientId, id }: Props) => { userType={"Doctor"} homeFacility={facilityId} error={state.errors.treating_physician} - noResultsLabel="No home facility doctors available" + noResultsLabel={t("no_treating_physicians_available")} />
diff --git a/src/Locale/en/Consultation.json b/src/Locale/en/Consultation.json index 42f31433495..5419e1e1d03 100644 --- a/src/Locale/en/Consultation.json +++ b/src/Locale/en/Consultation.json @@ -34,5 +34,6 @@ "generate_report": "Generate Report", "prev_sessions": "Prev Sessions", "next_sessions": "Next Sessions", - "no_changes": "No changes" + "no_changes": "No changes", + "no_treating_physicians_available": "This facility does not have any home facility doctors." } \ No newline at end of file From 1ac77520dc3e039161d2b43ba27ae6c0e947e135 Mon Sep 17 00:00:00 2001 From: rithviknishad Date: Wed, 31 Jul 2024 11:25:41 +0530 Subject: [PATCH 5/9] Show error and disable field instead of notification --- .../Common/UserAutocompleteFormField.tsx | 22 ++++++------------- src/Components/Facility/ConsultationForm.tsx | 6 ++--- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/Components/Common/UserAutocompleteFormField.tsx b/src/Components/Common/UserAutocompleteFormField.tsx index 3a566ca1f34..36e34e1e86b 100644 --- a/src/Components/Common/UserAutocompleteFormField.tsx +++ b/src/Components/Common/UserAutocompleteFormField.tsx @@ -9,8 +9,6 @@ import { import { UserModel } from "../Users/models"; import { isUserOnline } from "../../Utils/utils"; import { UserRole } from "../../Common/constants"; -import { useEffect } from "react"; -import { Error } from "../../Utils/Notifications"; type Props = FormFieldBaseProps & { placeholder?: string; @@ -18,7 +16,7 @@ type Props = FormFieldBaseProps & { homeFacility?: string; userType?: UserRole; showActiveStatus?: boolean; - noResultsLabel?: string; + noResultsError?: string; }; export default function UserAutocompleteFormField(props: Props) { @@ -64,25 +62,19 @@ export default function UserAutocompleteFormField(props: Props) { const items = options(field.value && [field.value]); - useEffect(() => { - if (props.required && !isLoading && !items.length && props.noResultsLabel) { - Error({ msg: props.noResultsLabel }); - } - }, [isLoading, items, props.required]); + const noResultError = + (props.required && !isLoading && !items.length && props.noResultsError) || + undefined; return ( - +
{ admitted: data.admitted ? String(data.admitted) : "false", admitted_to: data.admitted_to ? data.admitted_to : "", category: data.category - ? PATIENT_CATEGORIES.find((i) => i.text === data.category)?.id ?? - "" + ? (PATIENT_CATEGORIES.find((i) => i.text === data.category)?.id ?? + "") : "", patient_no: data.patient_no ?? "", OPconsultation: data.consultation_notes, @@ -1437,7 +1437,7 @@ export const ConsultationForm = ({ facilityId, patientId, id }: Props) => { userType={"Doctor"} homeFacility={facilityId} error={state.errors.treating_physician} - noResultsLabel={t("no_treating_physicians_available")} + noResultsError={t("no_treating_physicians_available")} />
From 03d5f1f5bf055e640e015d6b4f6852ec5f38f8c0 Mon Sep 17 00:00:00 2001 From: rithviknishad Date: Wed, 31 Jul 2024 19:14:03 +0530 Subject: [PATCH 6/9] Skip showing error instead validate on submit --- src/Components/Common/UserAutocompleteFormField.tsx | 9 ++++++++- src/Components/Facility/ConsultationForm.tsx | 2 +- src/Locale/en/Consultation.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Components/Common/UserAutocompleteFormField.tsx b/src/Components/Common/UserAutocompleteFormField.tsx index 36e34e1e86b..442eb0ae4fe 100644 --- a/src/Components/Common/UserAutocompleteFormField.tsx +++ b/src/Components/Common/UserAutocompleteFormField.tsx @@ -9,6 +9,7 @@ import { import { UserModel } from "../Users/models"; import { isUserOnline } from "../../Utils/utils"; import { UserRole } from "../../Common/constants"; +import { useEffect } from "react"; type Props = FormFieldBaseProps & { placeholder?: string; @@ -62,12 +63,18 @@ export default function UserAutocompleteFormField(props: Props) { const items = options(field.value && [field.value]); + useEffect(() => { + if (props.required && !isLoading && !items.length && props.noResultsError) { + field.handleChange(undefined as unknown as UserModel); + } + }, [isLoading, items, props.required]); + const noResultError = (props.required && !isLoading && !items.length && props.noResultsError) || undefined; return ( - +
{ case "treating_physician": { if (state.form.suggestion !== "DD" && !state.form[field]) { - errors[field] = "Please fill treating physician"; + errors[field] = "Field is required"; invalidForm = true; break; } diff --git a/src/Locale/en/Consultation.json b/src/Locale/en/Consultation.json index 31e11fc8721..6e3846fb983 100644 --- a/src/Locale/en/Consultation.json +++ b/src/Locale/en/Consultation.json @@ -36,7 +36,7 @@ "prev_sessions": "Prev Sessions", "next_sessions": "Next Sessions", "no_changes": "No changes", - "no_treating_physicians_available": "This facility does not have any home facility doctors.", + "no_treating_physicians_available": "This facility does not have any home facility doctors. Please contact your admin.", "encounter_suggestion_edit_disallowed": "Not allowed to switch to this option in edit consultation", "encounter_date_field_label__A": "Date & Time of Admission to the Facility", "encounter_date_field_label__DC": "Date & Time of Domiciliary Care commencement", From 782530c82531e457a1dd52f1a3367c58462ea5aa Mon Sep 17 00:00:00 2001 From: rithviknishad Date: Wed, 31 Jul 2024 20:05:25 +0530 Subject: [PATCH 7/9] add translations for field_required --- src/Components/ExternalResult/ResultUpdate.tsx | 4 +++- src/Components/Facility/AssetCreate.tsx | 7 ++++--- src/Components/Facility/BedCapacity.tsx | 4 +++- src/Components/Facility/ConsultationForm.tsx | 8 ++++---- src/Components/Facility/DischargeModal.tsx | 2 +- src/Components/Facility/StaffCapacity.tsx | 4 +++- src/Components/Facility/TransferPatientDialog.tsx | 4 +++- src/Components/Facility/TriageForm.tsx | 4 +++- src/Components/Form/FieldValidators.tsx | 4 +++- src/Components/Medicine/validators.ts | 3 ++- src/Components/Users/UserAdd.tsx | 6 ++++-- src/Components/Users/UserProfile.tsx | 10 ++++++---- src/Locale/en/Common.json | 3 ++- 13 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/Components/ExternalResult/ResultUpdate.tsx b/src/Components/ExternalResult/ResultUpdate.tsx index 09dc41aaca7..482c320457e 100644 --- a/src/Components/ExternalResult/ResultUpdate.tsx +++ b/src/Components/ExternalResult/ResultUpdate.tsx @@ -12,6 +12,7 @@ import useQuery from "../../Utils/request/useQuery.js"; import routes from "../../Redux/api.js"; import request from "../../Utils/request/request.js"; import { compareBy } from "../../Utils/utils.js"; +import { useTranslation } from "react-i18next"; const Loading = lazy(() => import("../Common/Loading")); @@ -57,6 +58,7 @@ const initialWard = [{ id: 0, name: "Choose Ward", number: 0 }]; export default function UpdateResult(props: any) { const { id } = props; const { goBack } = useAppHistory(); + const { t } = useTranslation(); const [state, dispatch] = useReducer(FormReducer, initialState); const [isLoading, setIsLoading] = useState(true); @@ -132,7 +134,7 @@ export default function UpdateResult(props: any) { switch (field) { case "address": if (!state.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } return; diff --git a/src/Components/Facility/AssetCreate.tsx b/src/Components/Facility/AssetCreate.tsx index 6867857c5c6..5b1493de242 100644 --- a/src/Components/Facility/AssetCreate.tsx +++ b/src/Components/Facility/AssetCreate.tsx @@ -32,10 +32,10 @@ import { validateEmailAddress } from "../../Common/validation"; import { dateQueryString, parsePhoneNumber } from "../../Utils/utils.js"; import dayjs from "../../Utils/dayjs"; import DateFormField from "../Form/FormFields/DateFormField.js"; -import { t } from "i18next"; import useQuery from "../../Utils/request/useQuery.js"; import routes from "../../Redux/api.js"; import request from "../../Utils/request/request.js"; +import { useTranslation } from "react-i18next"; const Loading = lazy(() => import("../Common/Loading")); @@ -101,6 +101,7 @@ type AssetFormSection = const AssetCreate = (props: AssetProps) => { const { goBack } = useAppHistory(); + const { t } = useTranslation(); const { facilityId, assetId } = props; let assetClassInitial: AssetClass; @@ -212,7 +213,7 @@ const AssetCreate = (props: AssetProps) => { return; case "is_working": if (is_working === undefined) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } return; @@ -224,7 +225,7 @@ const AssetCreate = (props: AssetProps) => { return; case "support_phone": { if (!support_phone) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } // eslint-disable-next-line no-case-declarations diff --git a/src/Components/Facility/BedCapacity.tsx b/src/Components/Facility/BedCapacity.tsx index ff0ec111496..c0f239203d5 100644 --- a/src/Components/Facility/BedCapacity.tsx +++ b/src/Components/Facility/BedCapacity.tsx @@ -9,6 +9,7 @@ import useConfig from "../../Common/hooks/useConfig"; import { getBedTypes } from "../../Common/constants"; import routes from "../../Redux/api"; import request from "../../Utils/request/request"; +import { useTranslation } from "react-i18next"; interface BedCapacityProps extends CapacityModal { facilityId: string; @@ -49,6 +50,7 @@ const bedCountReducer = (state = initialState, action: any) => { }; export const BedCapacity = (props: BedCapacityProps) => { + const { t } = useTranslation(); const config = useConfig(); const { facilityId, handleClose, handleUpdate, className, id } = props; const [state, dispatch] = useReducer(bedCountReducer, initialState); @@ -127,7 +129,7 @@ export const BedCapacity = (props: BedCapacityProps) => { let invalidForm = false; Object.keys(state.form).forEach((field) => { if (!state.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } else if ( field === "currentOccupancy" && diff --git a/src/Components/Facility/ConsultationForm.tsx b/src/Components/Facility/ConsultationForm.tsx index a70b956a2cb..dc496d599f7 100644 --- a/src/Components/Facility/ConsultationForm.tsx +++ b/src/Components/Facility/ConsultationForm.tsx @@ -453,7 +453,7 @@ export const ConsultationForm = ({ facilityId, patientId, id }: Props) => { return; case "route_to_facility": if (!state.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } return; @@ -469,7 +469,7 @@ export const ConsultationForm = ({ facilityId, patientId, id }: Props) => { return; case "encounter_date": if (!state.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } if ( @@ -540,7 +540,7 @@ export const ConsultationForm = ({ facilityId, patientId, id }: Props) => { return; case "consultation_notes": if (!state.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } else if (!state.form[field].replace(/\s/g, "").length) { errors[field] = "Consultation notes can not be empty"; @@ -608,7 +608,7 @@ export const ConsultationForm = ({ facilityId, patientId, id }: Props) => { case "treating_physician": { if (state.form.suggestion !== "DD" && !state.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; break; } diff --git a/src/Components/Facility/DischargeModal.tsx b/src/Components/Facility/DischargeModal.tsx index 567c21dfbb6..fe99b4ddd53 100644 --- a/src/Components/Facility/DischargeModal.tsx +++ b/src/Components/Facility/DischargeModal.tsx @@ -151,7 +151,7 @@ const DischargeModal = ({ newErrors["discharge_notes"] = "Please enter the cause of death"; } if (!preDischargeForm.death_confirmed_doctor?.trim()) { - newErrors["death_confirmed_doctor"] = "Field is required"; + newErrors["death_confirmed_doctor"] = t("field_required"); } if (Object.entries(newErrors).length) { diff --git a/src/Components/Facility/StaffCapacity.tsx b/src/Components/Facility/StaffCapacity.tsx index fc54dfcbb2d..8326ed6a323 100644 --- a/src/Components/Facility/StaffCapacity.tsx +++ b/src/Components/Facility/StaffCapacity.tsx @@ -10,6 +10,7 @@ import { DoctorModal } from "./models.js"; import useQuery from "../../Utils/request/useQuery.js"; import routes from "../../Redux/api.js"; import request from "../../Utils/request/request.js"; +import { useTranslation } from "react-i18next"; interface DoctorCapacityProps extends DoctorModal { facilityId: string; @@ -58,6 +59,7 @@ const getAllowedDoctorTypes = (existing?: DoctorModal[]) => { }; export const StaffCapacity = (props: DoctorCapacityProps) => { + const { t } = useTranslation(); const { facilityId, handleClose, handleUpdate, className, id } = props; const [state, dispatch] = useReducer(doctorCapacityReducer, initialState); const [isLoading, setIsLoading] = useState(false); @@ -94,7 +96,7 @@ export const StaffCapacity = (props: DoctorCapacityProps) => { let invalidForm = false; Object.keys(state.form).forEach((field) => { if (!state.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } if (field === "count" && state.form[field] < 0) { diff --git a/src/Components/Facility/TransferPatientDialog.tsx b/src/Components/Facility/TransferPatientDialog.tsx index 3ead082c610..0c4af6c5d0c 100644 --- a/src/Components/Facility/TransferPatientDialog.tsx +++ b/src/Components/Facility/TransferPatientDialog.tsx @@ -9,6 +9,7 @@ import request from "../../Utils/request/request.js"; import routes from "../../Redux/api.js"; import TextFormField from "../Form/FormFields/TextFormField.js"; import { FieldChangeEvent } from "../Form/FormFields/Utils.js"; +import { useTranslation } from "react-i18next"; interface Props { patientList: Array; @@ -53,6 +54,7 @@ const patientFormReducer = (state = initialState, action: any) => { const TransferPatientDialog = (props: Props) => { const { patientList, handleOk, handleCancel, facilityId } = props; + const { t } = useTranslation(); const [isLoading, setIsLoading] = useState(false); const [state, dispatch] = useReducer(patientFormReducer, initialState); const patientOptions: Array = patientList.map((patient) => { @@ -102,7 +104,7 @@ const TransferPatientDialog = (props: Props) => { return; case "year_of_birth": if (!state.form[field]) { - errors[field] = "This field is required"; + errors[field] = t("field_required"); invalidForm = true; } diff --git a/src/Components/Facility/TriageForm.tsx b/src/Components/Facility/TriageForm.tsx index 6ad9fdd0e08..1aa0537b53c 100644 --- a/src/Components/Facility/TriageForm.tsx +++ b/src/Components/Facility/TriageForm.tsx @@ -17,6 +17,7 @@ import { dateQueryString, scrollTo } from "../../Utils/utils"; import useQuery from "../../Utils/request/useQuery"; import routes from "../../Redux/api"; import request from "../../Utils/request/request"; +import { useTranslation } from "react-i18next"; interface Props extends PatientStatsModel { facilityId: string; @@ -57,6 +58,7 @@ const triageFormReducer = (state = initialState, action: any) => { }; export const TriageForm = ({ facilityId, id }: Props) => { + const { t } = useTranslation(); const { goBack } = useAppHistory(); const [state, dispatch] = useReducer(triageFormReducer, initialState); const [isLoading, setIsLoading] = useState(false); @@ -98,7 +100,7 @@ export const TriageForm = ({ facilityId, id }: Props) => { switch (field) { case "entry_date": if (!state.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } return; diff --git a/src/Components/Form/FieldValidators.tsx b/src/Components/Form/FieldValidators.tsx index 4933b685171..3159c6814f1 100644 --- a/src/Components/Form/FieldValidators.tsx +++ b/src/Components/Form/FieldValidators.tsx @@ -1,3 +1,5 @@ +import { t } from "i18next"; + export type FieldError = string | undefined; export type FieldValidator = (value: T, ...args: any) => FieldError; @@ -42,7 +44,7 @@ export const AnyValidator = ( return validator; }; -export const RequiredFieldValidator = (message = "Field is required") => { +export const RequiredFieldValidator = (message = t("field_required")) => { return (value: T): FieldError => { if (!value) return message; if (Array.isArray(value) && value.length === 0) return message; diff --git a/src/Components/Medicine/validators.ts b/src/Components/Medicine/validators.ts index 13460230737..a0103d11241 100644 --- a/src/Components/Medicine/validators.ts +++ b/src/Components/Medicine/validators.ts @@ -1,3 +1,4 @@ +import { t } from "i18next"; import { FieldError, RequiredFieldValidator } from "../Form/FieldValidators"; import { FormErrors } from "../Form/Utils"; import { Prescription } from "./models"; @@ -73,7 +74,7 @@ export const AdministrationDosageValidator = ( const baseDosage = getDosageValue(base_dosage); const targetDosage = getDosageValue(target_dosage); - if (!valueDosage) return "This field is required"; + if (!valueDosage) return t("field_required"); if (value?.split(" ")[1] !== base_dosage?.split(" ")[1]) return "Unit must be the same as start and target dosage's unit"; diff --git a/src/Components/Users/UserAdd.tsx b/src/Components/Users/UserAdd.tsx index ba218226490..8d33533f67a 100644 --- a/src/Components/Users/UserAdd.tsx +++ b/src/Components/Users/UserAdd.tsx @@ -41,6 +41,7 @@ import routes from "../../Redux/api"; import request from "../../Utils/request/request"; import useQuery from "../../Utils/request/useQuery"; import CareIcon from "../../CAREUI/icons/CareIcon"; +import { useTranslation } from "react-i18next"; const Loading = lazy(() => import("../Common/Loading")); @@ -163,6 +164,7 @@ export const validateRule = ( }; export const UserAdd = (props: UserProps) => { + const { t } = useTranslation(); const { goBack } = useAppHistory(); const { userId } = props; @@ -355,7 +357,7 @@ export const UserAdd = (props: UserProps) => { return; case "doctor_experience_commenced_on": if (state.form.user_type === "Doctor" && !state.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } else if ( state.form.user_type === "Doctor" && @@ -368,7 +370,7 @@ export const UserAdd = (props: UserProps) => { case "doctor_qualification": case "doctor_medical_council_registration": if (state.form.user_type === "Doctor" && !state.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } return; diff --git a/src/Components/Users/UserProfile.tsx b/src/Components/Users/UserProfile.tsx index 8a456be9bcd..dd8dadf2fb7 100644 --- a/src/Components/Users/UserProfile.tsx +++ b/src/Components/Users/UserProfile.tsx @@ -26,6 +26,7 @@ import routes from "../../Redux/api"; import request from "../../Utils/request/request"; import DateFormField from "../Form/FormFields/DateFormField"; import { validateRule } from "./UserAdd"; +import { useTranslation } from "react-i18next"; const Loading = lazy(() => import("../Common/Loading")); type EditForm = { @@ -110,6 +111,7 @@ const editFormReducer = (state: State, action: Action) => { }; export default function UserProfile() { + const { t } = useTranslation(); const { signOut } = useAuthContext(); const [states, dispatch] = useReducer(editFormReducer, initialState); const [updateStatus, setUpdateStatus] = useState({ @@ -201,7 +203,7 @@ export default function UserProfile() { case "lastName": case "gender": if (!states.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } return; @@ -254,7 +256,7 @@ export default function UserProfile() { return; case "email": if (!states.form[field]) { - errors[field] = "This field is required"; + errors[field] = t("field_required"); invalidForm = true; } else if (!validateEmailAddress(states.form[field])) { errors[field] = "Enter a valid email address"; @@ -263,7 +265,7 @@ export default function UserProfile() { return; case "doctor_experience_commenced_on": if (states.form.user_type === "Doctor" && !states.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } else if ( (states.form.user_type === "Doctor" && @@ -278,7 +280,7 @@ export default function UserProfile() { case "doctor_qualification": case "doctor_medical_council_registration": if (states.form.user_type === "Doctor" && !states.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } return; diff --git a/src/Locale/en/Common.json b/src/Locale/en/Common.json index 89faf842586..0bd26305b86 100644 --- a/src/Locale/en/Common.json +++ b/src/Locale/en/Common.json @@ -110,6 +110,7 @@ "features": "Features", "pincode": "Pincode", "required": "Required", + "field_required": "This field is required", "litres": "Litres", "litres_per_day": "Litres/day", "invalid_pincode": "Invalid Pincode", @@ -177,4 +178,4 @@ "feed_optimal_experience_for_phones": "For optimal viewing experience, consider rotating your device.", "feed_optimal_experience_for_apple_phones": "For optimal viewing experience, consider rotating your device. Ensure auto-rotate is enabled in your device settings.", "action_irreversible": "This action is irreversible" -} +} \ No newline at end of file From c763c6c1dee7133e5a8c4e89634f44b56c7a27b5 Mon Sep 17 00:00:00 2001 From: rithviknishad Date: Wed, 31 Jul 2024 20:06:23 +0530 Subject: [PATCH 8/9] remove duplicate i18n key from auth.json --- src/Locale/en/Auth.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Locale/en/Auth.json b/src/Locale/en/Auth.json index 8075ca839cd..58fdef42612 100644 --- a/src/Locale/en/Auth.json +++ b/src/Locale/en/Auth.json @@ -11,7 +11,6 @@ "gender": "Gender", "age": "Age", "login": "Login", - "field_required": "This field is required", "password_mismatch": "Password and confirm password must be same.", "enter_valid_age": "Please Enter Valid Age", "invalid_username": "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.", @@ -37,4 +36,4 @@ "req_atleast_one_uppercase": "Require at least one upper case", "req_atleast_one_lowercase": "Require at least one lower case letter", "req_atleast_one_symbol": "Require at least one symbol" -} +} \ No newline at end of file From 45e16ff857fc0c29e713ee5a19a06c73e065276d Mon Sep 17 00:00:00 2001 From: rithviknishad Date: Wed, 31 Jul 2024 20:36:15 +0530 Subject: [PATCH 9/9] update cypress --- cypress/e2e/facility_spec/facility_creation.cy.ts | 11 +++++++---- cypress/e2e/users_spec/user_creation.cy.ts | 4 ++-- cypress/pageobject/Asset/AssetCreation.ts | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/cypress/e2e/facility_spec/facility_creation.cy.ts b/cypress/e2e/facility_spec/facility_creation.cy.ts index 83f666995ff..6401ba7bbbe 100644 --- a/cypress/e2e/facility_spec/facility_creation.cy.ts +++ b/cypress/e2e/facility_spec/facility_creation.cy.ts @@ -58,12 +58,15 @@ describe("Facility Creation", () => { "Invalid Phone Number", ]; const bedErrorMessage = [ - "Field is required", + "This field is required", "Total capacity cannot be 0", - "Field is required", + "This field is required", ]; - const doctorErrorMessage = ["Field is required", "Field is required"]; - const triageErrorMessage = ["Field is required"]; + const doctorErrorMessage = [ + "This field is required", + "This field is required", + ]; + const triageErrorMessage = ["This field is required"]; before(() => { loginPage.loginAsDisctrictAdmin(); diff --git a/cypress/e2e/users_spec/user_creation.cy.ts b/cypress/e2e/users_spec/user_creation.cy.ts index 572b0cb95c4..91efb3aee31 100644 --- a/cypress/e2e/users_spec/user_creation.cy.ts +++ b/cypress/e2e/users_spec/user_creation.cy.ts @@ -50,8 +50,8 @@ describe("User Creation", () => { ]; const EXPECTED_PROFILE_ERROR_MESSAGES = [ - "Field is required", - "Field is required", + "This field is required", + "This field is required", "Please enter valid phone number", ]; diff --git a/cypress/pageobject/Asset/AssetCreation.ts b/cypress/pageobject/Asset/AssetCreation.ts index 9232c5966c1..331a4588c6f 100644 --- a/cypress/pageobject/Asset/AssetCreation.ts +++ b/cypress/pageobject/Asset/AssetCreation.ts @@ -200,7 +200,7 @@ export class AssetPage { verifyEmptyStatusError() { cy.get("[data-testid=asset-working-status-input] span").should( "contain", - "Field is required", + "This field is required", ); }