Skip to content

Commit

Permalink
Fixing the estimated dob changes
Browse files Browse the repository at this point in the history
  • Loading branch information
vasharma05 committed Oct 11, 2024
1 parent 10d0381 commit 0bd67cf
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 77 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React, { type ChangeEvent, useCallback, useContext } from 'react';
import { ContentSwitcher, Layer, Switch, TextInput } from '@carbon/react';
import React, { useCallback } from 'react';
import { ContentSwitcher, Layer, Switch } from '@carbon/react';
import { useTranslation } from 'react-i18next';
import { PatientRegistrationContext } from '../../patient-registration-context';
import { OpenmrsDatePicker, useConfig } from '@openmrs/esm-framework';
import { type RegistrationConfig } from '../../../config-schema';
import styles from '../field.scss';
import { usePatientRegistrationContext } from '../../patient-registration-hooks';
import { Controller } from 'react-hook-form';
import { Controller, useFormContext } from 'react-hook-form';
import useZodSchema from '../../useZodSchema';
import { NumberInput } from '@carbon/react';

const calcBirthdate = (yearDelta, monthDelta, dateOfBirth) => {
const { enabled, month, dayOfMonth } = dateOfBirth.useEstimatedDateOfBirth;
Expand All @@ -27,62 +27,67 @@ export const DobField: React.FC = () => {
fieldConfigurations: { dateOfBirth },
} = useConfig<RegistrationConfig>();
const allowEstimatedBirthDate = dateOfBirth?.allowEstimatedDateOfBirth;
const { watch, control, setValue } = usePatientRegistrationContext();
const { watch, control, setValue } = useFormContext();
const dobUnknown = watch('birthdateEstimated');
const today = new Date();
const monthsEstimated = watch('monthsEstimated');
const yearsEstimated = watch('yearsEstimated');

const { updateZodSchema } = useZodSchema();

// useEffect(() => {
// const yearsEstimatedSchema = z
// .number({
// invalid_type_error: t('yearsEstimatedTypeError', 'Years estimated must be a number'),
// })
// .min(0)
// .max(140, {
// message: t('maxError', 'Max error'),
// });
// updateZodSchema('yearsEstimated', dobUnknown ? yearsEstimatedSchema : yearsEstimatedSchema.optional());
// }, [t, dobUnknown]);

const onToggle = useCallback(
(e: { name?: string | number }) => {
setValue('birthdateEstimated', e.name === 'unknown');
setValue('birthdate', '');
setValue('yearsEstimated', 0);
setValue('yearsEstimated', undefined);
setValue('monthsEstimated', undefined);
// setFieldTouched('birthdateEstimated', true, false);
},
[setValue],
);

const onDateChange = useCallback(
(birthdate: Date) => {
setValue('birthdate', birthdate);
// setFieldTouched('birthdate', true, false);
},
[setValue],
);
// TODO: Make this validated as different fields
// const onEstimatedYearsChange = useCallback(
// (ev: ChangeEvent<HTMLInputElement>) => {
// const years = +ev.target.value;

const onEstimatedYearsChange = useCallback(
(ev: ChangeEvent<HTMLInputElement>) => {
const years = +ev.target.value;
// if (!isNaN(years) && years < 140 && years >= 0) {
// setValue('yearsEstimated', years);
// setValue('birthdate', calcBirthdate(years, monthsEstimated, dateOfBirth));
// }
// },
// [setValue, dateOfBirth, monthsEstimated],
// );

if (!isNaN(years) && years < 140 && years >= 0) {
setValue('yearsEstimated', years);
setValue('birthdate', calcBirthdate(years, monthsEstimated, dateOfBirth));
}
},
[setValue, dateOfBirth, monthsEstimated],
);
// const onEstimatedMonthsChange = useCallback(
// (ev: ChangeEvent<HTMLInputElement>) => {
// const months = +ev.target.value;

const onEstimatedMonthsChange = useCallback(
(ev: ChangeEvent<HTMLInputElement>) => {
const months = +ev.target.value;

if (!isNaN(months)) {
setValue('monthsEstimated', months);
setValue('birthdate', calcBirthdate(yearsEstimated, months, dateOfBirth));
}
},
[setValue, dateOfBirth, yearsEstimated],
);
// if (!isNaN(months)) {
// setValue('monthsEstimated', months);
// setValue('birthdate', calcBirthdate(yearsEstimated, months, dateOfBirth));
// }
// },
// [setValue, dateOfBirth, yearsEstimated],
// );

const updateBirthdate = useCallback(() => {
const months = +monthsEstimated % 12;
const years = +yearsEstimated + Math.floor(monthsEstimated / 12);
setValue('yearsEstimated', years);
setValue('monthsEstimated', months > 0 ? months : undefined);
setValue('birthdate', calcBirthdate(years, months, dateOfBirth));
}, [setValue, monthsEstimated, yearsEstimated, dateOfBirth]);
// const updateBirthdate = useCallback(() => {
// const months = +monthsEstimated % 12;
// const years = +yearsEstimated + Math.floor(monthsEstimated / 12);
// setValue('yearsEstimated', years);
// setValue('monthsEstimated', months > 0 ? months : undefined);
// setValue('birthdate', calcBirthdate(years, months, dateOfBirth));
// }, [setValue, monthsEstimated, yearsEstimated, dateOfBirth]);

return (
<div className={styles.halfWidthInDesktopView}>
Expand All @@ -108,10 +113,10 @@ export const DobField: React.FC = () => {
<OpenmrsDatePicker
id="birthdate"
{...field}
onChange={onDateChange}
// onChange={onDateChange}
maxDate={today}
labelText={t('dateOfBirthLabelText', 'Date of birth')}
isInvalid={!!(isTouched && error?.message)}
isInvalid={Boolean(isTouched && error?.message)}
invalidText={error?.message}
/>
)}
Expand All @@ -123,38 +128,34 @@ export const DobField: React.FC = () => {
<Controller
control={control}
name="yearsEstimated"
render={({ field, fieldState: { isTouched, error } }) => (
<TextInput
{...field}
id="yearsEstimated"
type="number"
onChange={onEstimatedYearsChange}
labelText={t('estimatedAgeInYearsLabelText', 'Estimated age in years')}
invalid={Boolean(isTouched && error?.message)}
invalidText={error?.message}
min={0}
required
onBlur={updateBirthdate}
/>
)}
render={({ field, fieldState: { isTouched, error } }) => {
return (
<NumberInput
{...field}
id="yearsEstimated"
type="number"
labelText={t('estimatedAgeInYearsLabelText', 'Estimated age in years')}
invalid={Boolean(isTouched && error?.message)}
invalidText={error?.message}
min={0}
/>
);
}}
/>
</div>
<div className={styles.dobField}>
<Controller
control={control}
name="monthsEstimated"
render={({ field, fieldState: { isTouched, error } }) => (
<TextInput
<NumberInput
{...field}
id="monthsEstimated"
type="number"
onChange={onEstimatedMonthsChange}
labelText={t('estimatedAgeInMonthsLabelText', 'Estimated age in months')}
invalid={Boolean(isTouched && error?.message)}
invalidText={error?.message}
min={0}
required={!yearsEstimated}
onBlur={updateBirthdate}
/>
)}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ interface InputProps extends TextInputProps {

export const Input: React.FC<InputProps> = ({ checkWarning, ...props }) => {
const { t } = useTranslation();
const { formState, getFieldState, control } = useContext(PatientRegistrationContext);
const { getFieldState, control, watch } = useContext(PatientRegistrationContext);
const { error } = getFieldState(props.name);

/*
Expand All @@ -155,7 +155,7 @@ export const Input: React.FC<InputProps> = ({ checkWarning, ...props }) => {
t('nonCodedCauseOfDeathRequired', 'Non-coded cause of death is required')
*/

const value = props.value || '';
const value = watch(props.name) as string;
const invalidText = error?.message;
const warnText = useMemo(() => {
if (!invalidText && typeof checkWarning === 'function') {
Expand Down Expand Up @@ -183,7 +183,6 @@ export const Input: React.FC<InputProps> = ({ checkWarning, ...props }) => {
invalidText={invalidText}
warn={!!warnText}
warnText={warnText}
value={value}
/>
</Layer>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
.filter((s) => s);
}, [config.sections, config.sectionDefinitions]);

const zodSchema = useZodSchema();
const { zodSchema } = useZodSchema();

const methods = useForm<FormValues>({
defaultValues: initialFormValues,
Expand All @@ -85,12 +85,6 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
reset,
} = methods;

useEffect(() => {
reset(initialFormValues, {
keepDirtyValues: true,
});
}, [initialFormValues]);

const onFormSubmit = async (values: FormValues) => {
const abortController = new AbortController();
// helpers.setSubmitting(true);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
import { getGlobalStore } from '@openmrs/esm-framework';
import { useEffect, useState } from 'react';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { z } from 'zod';
import type { FormValues } from './patient-registration.types';
import { useTranslation } from 'react-i18next';

export function getZodSchemaStore() {
return getGlobalStore<z.ZodSchema>('patient-registration-zod-schema', z.object({ firstName: z.string() }));
return getGlobalStore<z.ZodSchema<Partial<FormValues>>>(
'patient-registration-zod-schema',
z.object({
firstName: z.string({
required_error: 'First name is required',
}),
yearsEstimated: z
.number({
invalid_type_error: 'Years estimated must be a number',
})
.min(0)
.max(140, {
message: 'Max error',
}),
}),
);
}

export function addFieldSchemaToZod(fieldName: string, schema: z.ZodSchema) {
Expand All @@ -14,13 +31,28 @@ export function addFieldSchemaToZod(fieldName: string, schema: z.ZodSchema) {
}));
}

type T = keyof FormValues;

export default function useZodSchema() {
const { t } = useTranslation();
const [zodSchema, setZodSchema] = useState<z.ZodSchema>(getZodSchemaStore().getState());
const updateZodSchema = useCallback((key: T, value: z.ZodSchema) => {
getZodSchemaStore().setState({
[key]: value,
});
}, []);
useEffect(() => {
const unsubscribe = getZodSchemaStore().subscribe(setZodSchema);
return () => {
unsubscribe();
};
}, [setZodSchema]);
return zodSchema;
const results = useMemo(
() => ({
zodSchema,
updateZodSchema,
}),
[zodSchema, updateZodSchema],
);
return results;
}

0 comments on commit 0bd67cf

Please sign in to comment.