Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix state & district autofill & multiple other small issues in Patient Registration page #9711

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4dd0e93
Autofill the State & District
yash-learner Jan 3, 2025
645bd96
Merge branch 'develop' into issues/9668/fix-auto-fill
yash-learner Jan 3, 2025
9cb67df
Show asterisk properly and pass error message
yash-learner Jan 3, 2025
d1042e4
Merge branch 'develop' into issues/9668/fix-auto-fill
yash-learner Jan 3, 2025
c15621d
Remove console logs
yash-learner Jan 3, 2025
67073f8
Inform parent about deletion & handle it
yash-learner Jan 3, 2025
5ba881e
Add cursor style to address input when disabled
yash-learner Jan 3, 2025
3b77133
Use organization type instead of any
yash-learner Jan 3, 2025
f58e7b5
Merge branch 'develop' into issues/9668/fix-auto-fill
yash-learner Jan 3, 2025
bdd739f
Add custom hook for organization data fetching
yash-learner Jan 6, 2025
6905db3
Add custom hook to fetch state and district from pincode
yash-learner Jan 6, 2025
45a3d9f
Refactor pincode handling to use custom hook for state and district r…
yash-learner Jan 6, 2025
ca922bb
Merge branch 'develop' into issues/9668/fix-auto-fill
yash-learner Jan 6, 2025
0ca6b73
Add error handling messages for organization and pincode fetching
yash-learner Jan 6, 2025
c6b1783
Update condition for showing auto-filled pincode in PatientRegistrati…
yash-learner Jan 6, 2025
d3fb25d
Merge branch 'develop' into issues/9668/fix-auto-fill
Jacobjeevan Jan 14, 2025
8ee3d60
switch to query debounce for phone
Jacobjeevan Jan 14, 2025
1d3740e
minor fixes
Jacobjeevan Jan 14, 2025
e4b9514
coderabbit suggestions
Jacobjeevan Jan 14, 2025
22687f3
minor changes
Jacobjeevan Jan 15, 2025
5558a67
rm select
Jacobjeevan Jan 15, 2025
0b5a74d
added useEffect for error alerts
Jacobjeevan Jan 15, 2025
e150868
rm type from useQuery (redundant)
Jacobjeevan Jan 15, 2025
ebee745
Merge branch 'develop' into issues/9668/fix-auto-fill
nihal467 Jan 16, 2025
8d1f0c8
Merge branch 'develop' into issues/9668/fix-auto-fill
Jacobjeevan Jan 16, 2025
060f3e3
fixed the cypress failure
nihal467 Jan 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions cypress/e2e/patient_spec/patient_creation.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ describe("Patient Management", () => {
dateOfBirth: "01-01-1990",
address: generateAddress(),
pincode: "682001",
state: "Kerala",
district: "Ernakulam",
localBody: "Aluva",
ward: "4",
};
Expand Down
14 changes: 0 additions & 14 deletions cypress/pageObject/Patients/PatientCreation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ interface PatientFormData {
bloodGroup: string;
address: string;
pincode: string;
state: string;
district: string;
localBody: string;
ward: string;
}
Expand Down Expand Up @@ -106,22 +104,10 @@ export class PatientCreation {
.enterDateOfBirth(patient.dateOfBirth)
.enterAddress(patient.address)
.enterPincode(patient.pincode)
.selectState(patient.state)
.selectDistrict(patient.district)
.selectLocalBody(patient.localBody)
.selectWard(patient.ward);
}

selectState(state: string) {
cy.typeAndSelectOption('[data-cy="select-state"]', state);
return this;
}

selectDistrict(district: string) {
cy.typeAndSelectOption('[data-cy="select-district"]', district);
return this;
}

selectLocalBody(localBody: string) {
cy.typeAndSelectOption('[data-cy="select-local_body"]', localBody);
return this;
Expand Down
77 changes: 57 additions & 20 deletions src/components/Patient/PatientRegistration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useTranslation } from "react-i18next";
import { toast } from "sonner";
import { z } from "zod";

import CareIcon from "@/CAREUI/icons/CareIcon";
import SectionNavigator from "@/CAREUI/misc/SectionNavigator";

import { Button } from "@/components/ui/button";
Expand Down Expand Up @@ -37,6 +38,7 @@ import Page from "@/components/Common/Page";
import DuplicatePatientDialog from "@/components/Facility/DuplicatePatientDialog";

import useAppHistory from "@/hooks/useAppHistory";
import { useStateAndDistrictFromPincode } from "@/hooks/useStateAndDistrictFromPincode";

import {
BLOOD_GROUP_CHOICES, // DOMESTIC_HEALTHCARE_SUPPORT_CHOICES,
Expand Down Expand Up @@ -79,7 +81,8 @@ export default function PatientRegistration(

const [suppressDuplicateWarning, setSuppressDuplicateWarning] =
useState(!!patientId);
const [debouncedNumber, setDebouncedNumber] = useState<string>();
const [selectedLevels, setSelectedLevels] = useState<Organization[]>([]);
const [showAutoFilledPincode, setShowAutoFilledPincode] = useState(false);

const formSchema = useMemo(
() =>
Expand Down Expand Up @@ -192,6 +195,28 @@ export default function PatientRegistration(
},
});

const { stateOrg, districtOrg } = useStateAndDistrictFromPincode({
pincode: form.watch("pincode")?.toString() || "",
});

useEffect(() => {
// Fill by pincode for patient registration
if (patientId) return;
const levels: Organization[] = [];
if (stateOrg) levels.push(stateOrg);
if (districtOrg) levels.push(districtOrg);
setSelectedLevels(levels);

if (levels.length == 2) {
setShowAutoFilledPincode(true);
const timer = setTimeout(() => {
setShowAutoFilledPincode(false);
}, 5000);
return () => clearTimeout(timer);
}
return () => setShowAutoFilledPincode(false);
}, [stateOrg, districtOrg, patientId]);

function onSubmit(values: z.infer<typeof formSchema>) {
if (patientId) {
updatePatient({ ...values, ward_old: undefined });
Expand Down Expand Up @@ -226,13 +251,13 @@ export default function PatientRegistration(
};

const patientPhoneSearch = useQuery({
queryKey: ["patients", "phone-number", debouncedNumber],
queryFn: query(routes.searchPatient, {
queryKey: ["patients", "phone-number", form.watch("phone_number")],
queryFn: query.debounced(routes.searchPatient, {
body: {
phone_number: parsePhoneNumber(debouncedNumber || "") || "",
phone_number: parsePhoneNumber(form.watch("phone_number") || "") || "",
},
}),
enabled: !!parsePhoneNumber(debouncedNumber || ""),
enabled: !!parsePhoneNumber(form.watch("phone_number") || ""),
});

const duplicatePatients = useMemo(() => {
Expand All @@ -249,6 +274,9 @@ export default function PatientRegistration(

useEffect(() => {
if (patientQuery.data) {
setSelectedLevels([
patientQuery.data.geo_organization as unknown as Organization,
]);
form.reset({
...patientQuery.data,
same_phone_number:
Expand All @@ -257,27 +285,19 @@ export default function PatientRegistration(
same_address:
patientQuery.data.address === patientQuery.data.permanent_address,
age_or_dob: patientQuery.data.date_of_birth ? "dob" : "age",
age: !patientQuery.data.date_of_birth
? patientQuery.data.age
: undefined,
date_of_birth: patientQuery.data.date_of_birth
? patientQuery.data.date_of_birth
: undefined,
geo_organization: (
patientQuery.data.geo_organization as unknown as Organization
)?.id,
} as unknown as z.infer<typeof formSchema>);
}
}, [patientQuery.data]); // eslint-disable-line react-hooks/exhaustive-deps

useEffect(() => {
const handler = setTimeout(() => {
const phoneNumber = form.getValues("phone_number");
if (!patientId || patientQuery.data?.phone_number !== phoneNumber) {
setSuppressDuplicateWarning(false);
}
setDebouncedNumber(phoneNumber);
}, 500);

return () => {
clearTimeout(handler);
};
}, [form.watch("phone_number")]); // eslint-disable-line react-hooks/exhaustive-deps

if (patientId && patientQuery.isLoading) {
return <Loading />;
}
Expand Down Expand Up @@ -707,6 +727,22 @@ export default function PatientRegistration(
/>
</FormControl>
<FormMessage />
{showAutoFilledPincode && (
<div
role="status"
aria-live="polite"
className="flex items-center"
>
<CareIcon
icon="l-check-circle"
className="mr-2 text-sm text-green-500"
aria-hidden="true"
/>
<span className="text-sm text-primary-500">
{t("pincode_autofill")}
</span>
</div>
)}
</FormItem>
)}
/>
Expand Down Expand Up @@ -746,6 +782,7 @@ export default function PatientRegistration(
<OrganizationSelector
{...field}
required={true}
selected={selectedLevels}
value={form.watch("geo_organization")}
onChange={(value) =>
form.setValue("geo_organization", value)
Expand Down Expand Up @@ -781,7 +818,7 @@ export default function PatientRegistration(
</div>
{!patientPhoneSearch.isLoading &&
!!duplicatePatients?.length &&
!!parsePhoneNumber(debouncedNumber || "") &&
!!parsePhoneNumber(form.watch("phone_number") || "") &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Phone number parsing implementation needs improvement

The current implementation has several limitations that could affect robustness:

  • The minimum length check of 12 digits is too restrictive for valid international numbers
  • Special case handling of "+91" should be generalized
  • Limited validation of number format and country codes
🔗 Analysis chain

Verify phone number parsing edge cases.

The phone number parsing should be tested with various formats to ensure robust handling.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for phone number parsing usage and validation
rg -A 2 "parsePhoneNumber" 

Length of output: 4594


Script:

#!/bin/bash
# Get the implementation of parsePhoneNumber function
ast-grep --pattern 'export const parsePhoneNumber = $_'

Length of output: 944

!suppressDuplicateWarning && (
<DuplicatePatientDialog
patientList={duplicatePatients}
Expand Down
Loading