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: Pincode autofill in Patient Registration page in public page #10272

Closed
Closed
Changes from all commits
Commits
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
10 changes: 10 additions & 0 deletions src/hooks/useOrganization.ts
Original file line number Diff line number Diff line change
@@ -11,14 +11,23 @@ interface UseOrganizationParams {
parentId?: string;
name?: string;
enabled?: boolean;
authToken?: string;
}

export function useOrganization({
orgType = "",
parentId = "",
name = "",
enabled = true,
authToken,
}: UseOrganizationParams) {
const headers = authToken
? {
headers: {
Authorization: `Bearer ${authToken}`,
},
}
: {};
const { data, isLoading, isError } = useQuery({
queryKey: ["organization", orgType, name, parentId],
queryFn: query(organizationApi.list, {
@@ -27,6 +36,7 @@ export function useOrganization({
parent: parentId,
name,
},
...headers,
}),
enabled: enabled && !!name,
});
4 changes: 4 additions & 0 deletions src/hooks/useStateAndDistrictFromPincode.ts
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ import { getPincodeDetails } from "@/Utils/utils";

interface UseStateAndDistrictProps {
pincode: string;
authToken?: string;
}

interface PincodeResponse {
@@ -21,6 +22,7 @@ interface PincodeResponse {

export function useStateAndDistrictFromPincode({
pincode,
authToken,
}: UseStateAndDistrictProps) {
const {
data: pincodeDetails,
@@ -43,6 +45,7 @@ export function useStateAndDistrictFromPincode({
orgType: "govt",
parentId: "",
name: stateName,
authToken,
enabled: !!stateName,
});

@@ -56,6 +59,7 @@ export function useStateAndDistrictFromPincode({
orgType: "govt",
parentId: stateOrg?.id,
name: districtName,
authToken,
enabled: !!stateOrg?.id && !!districtName,
});

56 changes: 51 additions & 5 deletions src/pages/PublicAppointments/PatientRegistration.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { zodResolver } from "@hookform/resolvers/zod";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { navigate, useNavigationPrompt } from "raviger";
import { Fragment } from "react";
import { Fragment, useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
import { z } from "zod";

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

import { Button } from "@/components/ui/button";
import DateField from "@/components/ui/date-field";
import {
@@ -23,6 +25,7 @@ import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { Textarea } from "@/components/ui/textarea";

import { usePatientContext } from "@/hooks/usePatientUser";
import { useStateAndDistrictFromPincode } from "@/hooks/useStateAndDistrictFromPincode";

import { GENDER_TYPES } from "@/common/constants";
import { validateName, validatePincode } from "@/common/validation";
@@ -37,6 +40,7 @@ import {
AppointmentPatient,
AppointmentPatientRegister,
} from "@/pages/Patient/Utils";
import { Organization } from "@/types/organization/organization";
import PublicAppointmentApi from "@/types/scheduling/PublicAppointmentApi";
import {
Appointment,
@@ -79,6 +83,9 @@ export function PatientRegistration(props: PatientRegistrationProps) {
const patientUserContext = usePatientContext();
const tokenData = patientUserContext?.tokenData;

const [showAutoFilledPincode, setShowAutoFilledPincode] = useState(false);
const [selectedLevels, setSelectedLevels] = useState<Organization[]>([]);

const patientSchema = z
.object({
name: z
@@ -219,7 +226,27 @@ export function PatientRegistration(props: PatientRegistrationProps) {
t("unsaved_changes"),
);

// const [showAutoFilledPincode, setShowAutoFilledPincode] = useState(false);
const { stateOrg, districtOrg } = useStateAndDistrictFromPincode({
pincode: form.watch("pincode")?.toString() || "",
authToken: tokenData.token,
});

useEffect(() => {
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]);

return (
<>
@@ -391,6 +418,22 @@ export function PatientRegistration(props: PatientRegistrationProps) {
<FormControl>
<Input {...field} />
</FormControl>
{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>
)}
<FormMessage />
</FormItem>
)}
@@ -403,11 +446,14 @@ export function PatientRegistration(props: PatientRegistrationProps) {
<FormItem className="flex flex-col">
<FormControl>
<GovtOrganizationSelector
{...field}
value={form.watch("geo_organization")}
selected={selectedLevels}
required
authToken={tokenData.token}
onChange={(value) => {
field.onChange(value);
}}
onChange={(value) =>
form.setValue("geo_organization", value)
}
/>
</FormControl>
<FormMessage />

Unchanged files with check annotations Beta

if (queryCB) {
queryCB(query);
}
}, [query]);

Check warning on line 80 in src/CAREUI/misc/PaginatedList.tsx

GitHub Actions / cypress-run (1)

React Hook useEffect has a missing dependency: 'queryCB'. Either include it or remove the dependency array. If 'queryCB' changes too often, find the parent component that defines it and wrap that definition in useCallback
return (
<context.Provider
component: React.ComponentType<MicroPluginProps>;
routes: Array<{
path: string;
component: React.ComponentType<any>;

Check warning on line 13 in src/PluginRegistry.ts

GitHub Actions / cypress-run (1)

Unexpected any. Specify a different type
}>;
}
for (const config of configs) {
try {
// Provide React and ReactDOM to the plugin
(window as any).React = React;

Check warning on line 34 in src/PluginRegistry.ts

GitHub Actions / cypress-run (1)

Unexpected any. Specify a different type
(window as any).ReactDOM = ReactDOM;

Check warning on line 35 in src/PluginRegistry.ts

GitHub Actions / cypress-run (1)

Unexpected any. Specify a different type
await this.loadScript(config.url);
const pluginModule = (window as any)[config.name];

Check warning on line 38 in src/PluginRegistry.ts

GitHub Actions / cypress-run (1)

Unexpected any. Specify a different type
if (!pluginModule) {
throw new Error(
`Plugin ${config.name} not found after loading script`,
type Draft = {
timestamp: number;
draft: {
[key: string]: any;

Check warning on line 22 in src/Utils/AutoSave.tsx

GitHub Actions / cypress-run (1)

Unexpected any. Specify a different type
};
};
export function useAutoSaveReducer<T>(
reducer: any,

Check warning on line 27 in src/Utils/AutoSave.tsx

GitHub Actions / cypress-run (1)

Unexpected any. Specify a different type
initialState: any,

Check warning on line 28 in src/Utils/AutoSave.tsx

GitHub Actions / cypress-run (1)

Unexpected any. Specify a different type
): [FormState<T>, Dispatch<FormAction<T>>] {
const saveInterval = 1000;
const saveKey = useRef(`form_draft_${window.location.pathname}`);
return [state, dispatch];
}
export function useAutoSaveState(initialState: any) {

Check warning on line 81 in src/Utils/AutoSave.tsx

GitHub Actions / cypress-run (1)

Unexpected any. Specify a different type
const [state, dispatch] = useAutoSaveReducer((state: any, action: any) => {

Check warning on line 82 in src/Utils/AutoSave.tsx

GitHub Actions / cypress-run (1)

Unexpected any. Specify a different type
if (action.type === "set_state") {
return action.state;
}
#build-stage
FROM --platform=$BUILDPLATFORM node:22-bookworm-slim as build-stage

Check warning on line 2 in Dockerfile

GitHub Actions / Test

The 'as' keyword should match the case of the 'from' keyword

FromAsCasing: 'as' and 'FROM' keywords' casing do not match More info: https://docs.docker.com/go/dockerfile/rule/from-as-casing/
WORKDIR /app
#production-stage
FROM nginx:stable-alpine as production-stage

Check warning on line 24 in Dockerfile

GitHub Actions / Test

The 'as' keyword should match the case of the 'from' keyword

FromAsCasing: 'as' and 'FROM' keywords' casing do not match More info: https://docs.docker.com/go/dockerfile/rule/from-as-casing/
COPY --from=build-stage /app/build /usr/share/nginx/html