diff --git a/public/locale/en.json b/public/locale/en.json index 96f74cf9d81..c1222b52486 100644 --- a/public/locale/en.json +++ b/public/locale/en.json @@ -349,6 +349,7 @@ "additional_information": "Additional Information", "additional_instructions": "Additional Instructions", "address": "Address", + "address_is_required": "Address is required", "administer": "Administer", "administer_medicine": "Administer Medicine", "administer_medicines": "Administer Medicines", @@ -364,6 +365,9 @@ "age_input_warning": "While entering a patient's age is an option, please note that only the year of birth will be captured from this information.", "age_input_warning_bold": "Recommended only when the patient's date of birth is unknown", "age_less_than_0": "Age cannot be less than 0", + "age_must_be_below_120": "Age must be below 120", + "age_must_be_positive": "Age must be greater than 0", + "age_must_be_present": "Age must be present", "age_notice": "Only year of birth will be stored for age.", "ago": "ago", "all": "All", @@ -477,6 +481,7 @@ "beta": "beta", "bladder": "Bladder", "blood_group": "Blood Group", + "blood_group_is_required": "Blood group is required", "blood_pressure_error": { "missing": "Field is required. Either specify both or clear both.", "exceed": "Value cannot exceed 250 mmHg.", @@ -696,6 +701,8 @@ "date_of_admission": "Date of Admission", "date_of_birth": "Date of Birth", "date_of_birth_age": "Date of Birth/Age", + "date_of_birth_format": "Date of birth must be in YYYY-MM-DD format", + "date_of_birth_must_be_present": "Date of birth must be present", "date_of_birth_or_age": "Date of Birth or Age", "date_of_positive_covid_19_swab": "Date of Positive Covid 19 Swab", "date_of_result": "Covid confirmation date", @@ -1024,12 +1031,15 @@ "full_name": "Full Name", "full_screen": "Full Screen", "gender": "Gender", + "gender_is_required": "Gender is required", "general_info_detail": "Provide the patient's personal details, including name, date of birth, gender, and contact information for accurate identification and communication.", "generate_link_abha": "Generate/Link ABHA Number", "generate_report": "Generate Report", "generated_summary_caution": "This is a computer generated summary using the information captured in the CARE system.", "generating": "Generating", "generating_discharge_summary": "Generating discharge summary", + "geo_organization_is_required": "Geo organization is required when nationality is India", + "geo_organization_required": "Geo organization is required", "geolocation_is_not_supported_by_this_browser": "Geolocation is not supported by this browser", "get_auth_methods": "Get Available Authentication Methods", "get_auth_mode_error": "Could not find any supported authentication methods, Please try again with a different authentication method", @@ -1277,9 +1287,11 @@ "my_profile": "My Profile", "my_schedules": "My Schedules", "name": "Name", + "name_is_required": "Name is required", "name_of_hospital": "Name of Hospital", "name_of_shifting_approving_facility": "Name of shifting approving facility", "nationality": "Nationality", + "nationality_is_required": "Nationality is required", "nearby_facilities": "Nearby Facilities", "network_failure": "Network Failure. Please check your internet connectivity.", "never": "never", @@ -1489,6 +1501,7 @@ "patients": "Patients", "patients_per_slot": "Patients per Slot", "pending": "Pending", + "permanant_address_is_required": "Permanant address is required", "permanent_address": "Permanent Address", "permission_denied": "You do not have permission to perform this action", "personal_information": "Personal Information", @@ -1500,11 +1513,13 @@ "phone_number": "Phone Number", "phone_number_at_current_facility": "Phone Number of Contact person at current Facility", "phone_number_min_error": "Phone number must be at least 10 characters long", + "phone_number_must_be_10_digits": "Phone number must be a 10-digit mobile number", "phone_number_not_found": "Phone number not found", "phone_number_validation": "Phone number must start with +91 followed by 10 digits", "phone_number_verified": "Phone Number Verified", "pincode": "Pincode", "pincode_autofill": "State and District auto-filled from Pincode", + "pincode_must_be_6_digits": "Pincode must be a 6-digit number", "play": "Play", "play_audio": "Play Audio", "please_assign_bed_to_patient": "Please assign a bed to this patient", @@ -1517,6 +1532,7 @@ "please_enter_username": "Please enter the username", "please_fix_errors": "Please fix the errors in the highlighted fields and try submitting again.", "please_select_a_facility": "Please select a facility", + "please_select_blood_group": "Please select the blood group", "please_select_breathlessness_level": "Please select Breathlessness Level", "please_select_district": "Please select the district", "please_select_facility_type": "Please select Facility Type", @@ -2114,6 +2130,8 @@ "working_status": "Working Status", "year": "Year", "year_of_birth": "Year of Birth", + "year_of_birth_format": "Year of birth must be in YYYY format", + "year_of_birth_must_be_present": "Year of birth must be present", "years": "years", "years_of_experience": "Years of Experience", "years_of_experience_of_the_doctor": "Years of Experience of the Doctor", diff --git a/scripts/setup-care-apps.ts b/scripts/setup-care-apps.ts index f03c07f6cad..714d12f5a5a 100644 --- a/scripts/setup-care-apps.ts +++ b/scripts/setup-care-apps.ts @@ -92,6 +92,7 @@ const pluginMapContent = `// Use type assertion for the static import\n${plugins `// @ts-expect-error Remote module will be available at runtime\nimport ${plugin.camelCaseName}Manifest from "${plugin.repo}/manifest";`, ) .join("\n")} + import type { PluginManifest } from "./pluginTypes"; const pluginMap: PluginManifest[] = [${plugins.map((plugin) => `${plugin.camelCaseName}Manifest as PluginManifest`).join(",\n ")}]; diff --git a/src/components/Facility/ConsultationDetails/EncounterContext.tsx b/src/components/Facility/ConsultationDetails/EncounterContext.tsx index e0ba1d6228a..07d76a7f538 100644 --- a/src/components/Facility/ConsultationDetails/EncounterContext.tsx +++ b/src/components/Facility/ConsultationDetails/EncounterContext.tsx @@ -1,6 +1,5 @@ import { ReactNode, createContext, useContext, useState } from "react"; -import { PLUGIN_Component } from "@/PluginEngine"; import { Encounter } from "@/types/emr/encounter"; import { Patient } from "@/types/emr/newPatient"; @@ -65,7 +64,6 @@ export const EncounterProvider = ({ } as EncounterContextType } > - {children} ); diff --git a/src/components/Patient/PatientHome.tsx b/src/components/Patient/PatientHome.tsx index 1d4f942f900..f41137221fe 100644 --- a/src/components/Patient/PatientHome.tsx +++ b/src/components/Patient/PatientHome.tsx @@ -11,6 +11,7 @@ import Loading from "@/components/Common/Loading"; import Page from "@/components/Common/Page"; import { patientTabs } from "@/components/Patient/PatientDetailsTab"; +import { PLUGIN_Component } from "@/PluginEngine"; import routes from "@/Utils/request/api"; import query from "@/Utils/request/query"; import { formatDateTime, formatPatientAge, relativeDate } from "@/Utils/utils"; @@ -134,8 +135,8 @@ export const PatientHome = (props: { {t("actions")}
-
-
+
+
+ +
diff --git a/src/components/Patient/PatientInfoCard.tsx b/src/components/Patient/PatientInfoCard.tsx index 2c716095400..eeca3049a45 100644 --- a/src/components/Patient/PatientInfoCard.tsx +++ b/src/components/Patient/PatientInfoCard.tsx @@ -30,6 +30,7 @@ import { import { Avatar } from "@/components/Common/Avatar"; +import { PLUGIN_Component } from "@/PluginEngine"; import routes from "@/Utils/request/api"; import mutate from "@/Utils/request/mutate"; import { formatDateTime, formatPatientAge } from "@/Utils/utils"; @@ -342,6 +343,10 @@ export default function PatientInfoCard(props: PatientInfoCardProps) { {t("mark_as_complete")} +
diff --git a/src/components/Patient/PatientRegistration.tsx b/src/components/Patient/PatientRegistration.tsx index 2cfade10b39..cdecd959e5a 100644 --- a/src/components/Patient/PatientRegistration.tsx +++ b/src/components/Patient/PatientRegistration.tsx @@ -1,16 +1,26 @@ -import careConfig from "@careConfig"; +import { zodResolver } from "@hookform/resolvers/zod"; import { useMutation, useQuery } from "@tanstack/react-query"; import { navigate, useQueryParams } from "raviger"; -import { Fragment, useEffect, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; +import { useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { toast } from "sonner"; +import { z } from "zod"; import SectionNavigator from "@/CAREUI/misc/SectionNavigator"; import { Button } from "@/components/ui/button"; import { Checkbox } from "@/components/ui/checkbox"; +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form"; import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import { Select, @@ -34,18 +44,15 @@ import { //RATION_CARD_CATEGORY, // SOCIOECONOMIC_STATUS_CHOICES , } from "@/common/constants"; import countryList from "@/common/static/countries.json"; -import { validatePincode } from "@/common/validation"; +import { PLUGIN_Component } from "@/PluginEngine"; import routes from "@/Utils/request/api"; import mutate from "@/Utils/request/mutate"; import query from "@/Utils/request/query"; -import { - dateQueryString, - getPincodeDetails, - parsePhoneNumber, -} from "@/Utils/utils"; +import { parsePhoneNumber } from "@/Utils/utils"; import OrganizationSelector from "@/pages/Organization/components/OrganizationSelector"; -import { PatientModel, validatePatient } from "@/types/emr/patient"; +import { PatientModel } from "@/types/emr/patient"; +import { Organization } from "@/types/organization/organization"; import Autocomplete from "../ui/autocomplete"; @@ -54,6 +61,14 @@ interface PatientRegistrationPageProps { patientId?: string; } +export const GENDERS = GENDER_TYPES.map((gender) => gender.id) as [ + (typeof GENDER_TYPES)[number]["id"], +]; + +export const BLOOD_GROUPS = BLOOD_GROUP_CHOICES.map((bg) => bg.id) as [ + (typeof BLOOD_GROUP_CHOICES)[number]["id"], +]; + export default function PatientRegistration( props: PatientRegistrationPageProps, ) { @@ -62,65 +77,88 @@ export default function PatientRegistration( const { t } = useTranslation(); const { goBack } = useAppHistory(); - const [samePhoneNumber, setSamePhoneNumber] = useState(false); - const [sameAddress, setSameAddress] = useState(true); - const [ageDob, setAgeDob] = useState<"dob" | "age">("dob"); - const [_showAutoFilledPincode, setShowAutoFilledPincode] = useState(false); - const [form, setForm] = useState>({ - nationality: "India", - phone_number: phone_number || "+91", - emergency_phone_number: "+91", - }); - const [feErrors, setFeErrors] = useState< - Partial> - >({}); const [suppressDuplicateWarning, setSuppressDuplicateWarning] = useState(!!patientId); const [debouncedNumber, setDebouncedNumber] = useState(); - const sidebarItems = [ - { label: t("patient__general-info"), id: "general-info" }, - // { label: t("social_profile"), id: "social-profile" }, - //{ label: t("volunteer_contact"), id: "volunteer-contact" }, - //{ label: t("patient__insurance-details"), id: "insurance-details" }, - ]; - - const mutationFields: (keyof PatientModel)[] = [ - "name", - "phone_number", - "emergency_phone_number", - "geo_organization", - "gender", - "blood_group", - "date_of_birth", - "age", - "address", - "permanent_address", - "pincode", - "nationality", - "meta_info", - "ration_card_category", - ]; + const formSchema = useMemo( + () => + z + .object({ + name: z.string().nonempty(t("name_is_required")), + phone_number: z + .string() + .regex(/^\+\d{12}$/, t("phone_number_must_be_10_digits")), + same_phone_number: z.boolean(), + emergency_phone_number: z + .string() + .regex(/^\+\d{12}$/, t("phone_number_must_be_10_digits")), + gender: z.enum(GENDERS, { required_error: t("gender_is_required") }), + blood_group: z.enum(BLOOD_GROUPS, { + required_error: t("blood_group_is_required"), + }), + age_or_dob: z.enum(["dob", "age"]), + date_of_birth: z + .string() + .regex(/^\d{4}-\d{2}-\d{2}$/, t("date_of_birth_format")) + .optional(), + age: z + .number() + .int() + .positive() + .min(1, t("age_must_be_positive")) + .max(120, t("age_must_be_below_120")) + .optional(), + address: z.string().nonempty(t("address_is_required")), + same_address: z.boolean(), + permanent_address: z + .string() + .nonempty(t("permanent_address_is_required")), + pincode: z + .number() + .int() + .positive() + .min(100000, t("pincode_must_be_6_digits")) + .max(999999, t("pincode_must_be_6_digits")), + nationality: z.string().nonempty(t("nationality_is_required")), + geo_organization: z.string().uuid().optional(), + }) + .refine( + (data) => (data.age_or_dob === "dob" ? !!data.date_of_birth : true), + { + message: t("date_of_birth_must_be_present"), + path: ["date_of_birth"], + }, + ) + .refine((data) => (data.age_or_dob === "age" ? !!data.age : true), { + message: t("age_must_be_present"), + path: ["age"], + }) + .refine( + (data) => + data.nationality === "India" ? !!data.geo_organization : true, + { + message: t("geo_organization_required"), + path: ["geo_organization"], + }, + ), + [], // eslint-disable-line react-hooks/exhaustive-deps + ); - const mutationData: Partial = { - ...Object.fromEntries( - Object.entries(form).filter(([key]) => - mutationFields.includes(key as keyof PatientModel), - ), - ), - date_of_birth: - ageDob === "dob" ? dateQueryString(form.date_of_birth) : undefined, - age: ageDob === "age" ? form.age : undefined, - meta_info: { - ...(form.meta_info as any), - occupation: - form.meta_info?.occupation === "" - ? undefined - : form.meta_info?.occupation, + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + nationality: "India", + phone_number: phone_number || "+91", + emergency_phone_number: "+91", + age_or_dob: "dob", + same_phone_number: false, + same_address: true, }, - }; + }); - const createPatientMutation = useMutation({ + const { mutate: createPatient, isPending: isCreatingPatient } = useMutation({ + mutationKey: ["create_patient"], mutationFn: mutate(routes.addPatient), onSuccess: (resp: PatientModel) => { toast.success(t("patient_registration_success")); @@ -129,7 +167,7 @@ export default function PatientRegistration( query: { phone_number: resp.phone_number, year_of_birth: - ageDob === "dob" + form.getValues("age_or_dob") === "dob" ? new Date(resp.date_of_birth!).getFullYear() : new Date().getFullYear() - Number(resp.age!), partial_id: resp?.id?.slice(0, 5), @@ -141,7 +179,7 @@ export default function PatientRegistration( }, }); - const updatePatientMutation = useMutation({ + const { mutate: updatePatient, isPending: isUpdatingPatient } = useMutation({ mutationFn: mutate(routes.updatePatient, { pathParams: { id: patientId || "" }, }), @@ -154,86 +192,32 @@ export default function PatientRegistration( }, }); - const patientQuery = useQuery({ - queryKey: ["patient", patientId], - queryFn: query(routes.getPatient, { - pathParams: { id: patientId || "" }, - }), - enabled: !!patientId, - }); - - useEffect(() => { - if (patientQuery.data) { - setForm(patientQuery.data); - if (patientQuery.data.year_of_birth && !patientQuery.data.date_of_birth) { - setAgeDob("age"); - } - if ( - patientQuery.data.phone_number === - patientQuery.data.emergency_phone_number - ) - setSamePhoneNumber(true); - if (patientQuery.data.address === patientQuery.data.permanent_address) - setSameAddress(true); + function onSubmit(values: z.infer) { + if (patientId) { + updatePatient({ ...values, ward_old: undefined }); + return; } - }, [patientQuery.data]); - - const handlePincodeChange = async (value: string) => { - if (!validatePincode(value)) return; - if (form.state && form.district) return; - - const pincodeDetails = await getPincodeDetails( - value, - careConfig.govDataApiKey, - ); - if (!pincodeDetails) return; - - const { statename: _stateName, districtname: _districtName } = - pincodeDetails; - setShowAutoFilledPincode(true); - setTimeout(() => { - setShowAutoFilledPincode(false); - }, 2000); - }; + createPatient({ + ...values, + facility: facilityId, + ward_old: undefined, + }); + } - useEffect(() => { - const timeout = setTimeout( - () => handlePincodeChange(form.pincode?.toString() || ""), - 1000, - ); - return () => clearTimeout(timeout); - }, [form.pincode]); + const sidebarItems = [ + { label: t("patient__general-info"), id: "general-info" }, + ]; const title = !patientId ? t("add_details_of_patient") : t("update_patient_details"); - const errors = { - ...feErrors, - ...(createPatientMutation.error as unknown as string[]), - }; - - const fieldProps = (field: keyof typeof form) => ({ - value: form[field] as string, - onChange: (e: React.ChangeEvent) => - setForm((f) => ({ - ...f, - [field]: e.target.value === "" ? undefined : e.target.value, - })), - }); - - const selectProps = (field: keyof typeof form) => ({ - value: (form[field] as string)?.toString(), - onValueChange: (value: string) => - setForm((f) => ({ ...f, [field]: value })), - }); - const handleDialogClose = (action: string) => { if (action === "transfer") { navigate(`/facility/${facilityId}/patients`, { query: { - phone_number: form.phone_number, + phone_number: form.getValues("phone_number"), }, }); } else { @@ -241,53 +225,59 @@ export default function PatientRegistration( } }; - const handleFormSubmit = (e: React.FormEvent) => { - e.preventDefault(); - const validate = validatePatient(form, ageDob === "dob"); - if (typeof validate !== "object") { - patientId - ? updatePatientMutation.mutate({ ...mutationData, ward_old: undefined }) - : createPatientMutation.mutate({ - ...mutationData, - facility: facilityId, - ward_old: undefined, - }); - } else { - const firstErrorField = document.querySelector("[data-input-error]"); - if (firstErrorField) { - firstErrorField.scrollIntoView({ behavior: "smooth", block: "center" }); - } - toast.error(t("please_fix_errors")); - setFeErrors(validate); + const patientPhoneSearch = useQuery({ + queryKey: ["patients", "phone-number", debouncedNumber], + queryFn: query(routes.searchPatient, { + body: { + phone_number: parsePhoneNumber(debouncedNumber || "") || "", + }, + }), + enabled: !!parsePhoneNumber(debouncedNumber || ""), + }); + + const duplicatePatients = useMemo(() => { + return patientPhoneSearch.data?.results.filter((p) => p.id !== patientId); + }, [patientPhoneSearch.data, patientId]); + + const patientQuery = useQuery({ + queryKey: ["patient", patientId], + queryFn: query(routes.getPatient, { + pathParams: { id: patientId || "" }, + }), + enabled: !!patientId, + }); + + useEffect(() => { + if (patientQuery.data) { + form.reset({ + ...patientQuery.data, + same_phone_number: + patientQuery.data.phone_number === + patientQuery.data.emergency_phone_number, + same_address: + patientQuery.data.address === patientQuery.data.permanent_address, + age_or_dob: patientQuery.data.date_of_birth ? "dob" : "age", + geo_organization: ( + patientQuery.data.geo_organization as unknown as Organization + )?.id, + } as unknown as z.infer); } - }; + }, [patientQuery.data]); // eslint-disable-line react-hooks/exhaustive-deps useEffect(() => { const handler = setTimeout(() => { - if (!patientId || patientQuery.data?.phone_number !== form.phone_number) { + const phoneNumber = form.getValues("phone_number"); + if (!patientId || patientQuery.data?.phone_number !== phoneNumber) { setSuppressDuplicateWarning(false); } - setDebouncedNumber(form.phone_number); + setDebouncedNumber(phoneNumber); }, 500); return () => { clearTimeout(handler); }; - }, [form.phone_number]); + }, [form.watch("phone_number")]); // eslint-disable-line react-hooks/exhaustive-deps - const patientPhoneSearch = useQuery({ - queryKey: ["patients", "phone-number", debouncedNumber], - queryFn: query(routes.searchPatient, { - body: { - phone_number: parsePhoneNumber(debouncedNumber || "") || "", - }, - }), - enabled: !!parsePhoneNumber(debouncedNumber || ""), - }); - - const duplicatePatients = patientPhoneSearch.data?.results.filter( - (p) => p.id !== patientId, - ); if (patientId && patientQuery.isLoading) { return ; } @@ -297,571 +287,473 @@ export default function PatientRegistration(
-
-
-

- {t("patient__general-info")} -

-
{t("general_info_detail")}
-
- - -
- {errors["name"] && - errors["name"].map((error, i) => ( -
- {error} -
- ))} -
-
- - { - if (e.target.value.length > 13) return; - setForm((f) => ({ - ...f, - phone_number: e.target.value, - emergency_phone_number: samePhoneNumber - ? e.target.value - : f.emergency_phone_number, - })); - }} - data-cy="patient-phone-input" + + + + -
- {errors["phone_number"] && - errors["phone_number"]?.map((error, i) => ( -
- {error} -
- ))} -
-
- { - const newValue = !samePhoneNumber; - setSamePhoneNumber(newValue); - if (newValue) { - setForm((f) => ({ - ...f, - emergency_phone_number: f.phone_number, - })); - } - }} - id="same-phone-number" - data-cy="same-phone-number-checkbox" +
+
+

+ {t("patient__general-info")} +

+
{t("general_info_detail")}
+
+ + ( + + {t("name")} + + + + + + )} /> - -
-
- - - { - if (e.target.value.length > 13) return; - setForm((f) => ({ - ...f, - emergency_phone_number: e.target.value, - })); - }} - disabled={samePhoneNumber} - /> -
- {errors["emergency_phone_number"] && - errors["emergency_phone_number"]?.map((error, i) => ( -
- {error} -
- ))} -
- {/*
- */} -
- - - - setForm((f) => ({ ...f, gender: value })) - } - className="flex items-center gap-4" - > - {GENDER_TYPES.map((g) => ( - - - - - ))} - -
- {errors["gender"] && - errors["gender"]?.map((error, i) => ( -
- {error} -
- ))} -
-
- - - -
- {errors["blood_group"] && - errors["blood_group"]?.map((error, i) => ( -
- {error} -
- ))} -
+ ( + + {t("phone_number")} + + { + form.setValue("phone_number", e.target.value); + if (form.watch("same_phone_number")) { + form.setValue( + "emergency_phone_number", + e.target.value, + ); + } + }} + data-cy="patient-phone-input" + /> + + + ( + + + { + field.onChange(v); + if (v) { + form.setValue( + "emergency_phone_number", + form.watch("phone_number"), + ); + } + }} + data-cy="same-phone-number-checkbox" + /> + + + {t("use_phone_number_for_emergency")} + + + )} + /> + + + + )} + /> -
- - setAgeDob(value as typeof ageDob) - } - > - - {[ - ["dob", t("date_of_birth")], - ["age", t("age")], - ].map(([key, label]) => ( - {label} - ))} - - -
-
- - - setForm((f) => ({ - ...f, - date_of_birth: `${form.date_of_birth?.split("-")[0] || ""}-${form.date_of_birth?.split("-")[1] || ""}-${e.target.value}`, - })) - } - /> -
-
- - - setForm((f) => ({ - ...f, - date_of_birth: `${form.date_of_birth?.split("-")[0] || ""}-${e.target.value}-${form.date_of_birth?.split("-")[2] || ""}`, - })) - } - /> -
-
- - - setForm((f) => ({ - ...f, - date_of_birth: `${e.target.value}-${form.date_of_birth?.split("-")[1] || ""}-${form.date_of_birth?.split("-")[2] || ""}`, - })) - } - /> -
-
- {errors["date_of_birth"] && ( -
- {errors["date_of_birth"].map((error, i) => ( -
- {error} -
- ))} -
+ ( + + + {t("emergency_phone_number")} + + + + + + + )} + /> + + ( + + {t("sex")} + + + {GENDER_TYPES.map((g) => ( + + + + + + {t(`GENDER__${g.id}`)} + + + ))} + + + + )} -
- -
- {t("age_input_warning")} -
- {t("age_input_warning_bold")} -
-
- - - setForm((f) => ({ - ...f, - age: e.target.value, - year_of_birth: e.target.value - ? new Date().getFullYear() - Number(e.target.value) - : undefined, - })) - } - type="number" + /> + + ( + + {t("blood_group")} + + + + )} + /> + + { + form.setValue("age_or_dob", v as "dob" | "age"); + if (v === "age") { + form.setValue("date_of_birth", undefined); + } else { + form.setValue("age", undefined); + } + }} + > + + {t("date_of_birth")} + {t("age")} + + + ( + + +
+
+ {t("day")} + + + form.setValue( + "date_of_birth", + `${form.watch("date_of_birth")?.split("-")[0]}-${form.watch("date_of_birth")?.split("-")[1]}-${e.target.value}`, + ) + } + data-cy="dob-day-input" + /> +
+ +
+ {t("month")} + + + form.setValue( + "date_of_birth", + `${form.watch("date_of_birth")?.split("-")[0]}-${e.target.value}-${form.watch("date_of_birth")?.split("-")[2]}`, + ) + } + data-cy="dob-month-input" + /> +
+ +
+ {t("year")} + + + form.setValue( + "date_of_birth", + `${e.target.value}-${form.watch("date_of_birth")?.split("-")[1]}-${form.watch("date_of_birth")?.split("-")[2]}`, + ) + } + data-cy="dob-year-input" + /> +
+
+
+ +
+ )} /> -
- {errors["year_of_birth"] && - errors["year_of_birth"]?.map((error, i) => ( -
- {error} -
- ))} + + +
+ {t("age_input_warning")} +
+ {t("age_input_warning_bold")}
- {form.year_of_birth && ( -
- {t("year_of_birth")} : {form.year_of_birth} -
- )} -
-
-
-
- - -