From 137d626b5e891340e162258df8e23d3001b14eba Mon Sep 17 00:00:00 2001 From: Khavin Shankar Date: Tue, 17 Mar 2026 09:49:40 +0530 Subject: [PATCH 1/3] fixed patient home path (#78) --- src/components/TokenSearchDialog.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/TokenSearchDialog.tsx b/src/components/TokenSearchDialog.tsx index 7c40b54..197dce9 100644 --- a/src/components/TokenSearchDialog.tsx +++ b/src/components/TokenSearchDialog.tsx @@ -8,7 +8,6 @@ import { } from "@/components/ui/dialog"; import { FC, useMemo, useState } from "react"; -import { ArrowRightIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Patient } from "@/types/patient"; @@ -124,14 +123,14 @@ const PatientCard: FC<{ patient: Patient }> = ({ patient }) => { return (
{ - navigate("patients/verify", { + navigate("patients/home", { query: { phone_number: patient.phone_number, year_of_birth: yearOfBirth, partial_id: patient.partial_id || patient.id.slice(0, 5), }, }); - }} + }} className="border rounded-md p-4 cursor-pointer" >
From e8a7dfea2c592940f85fc267b456c56a9d27f54c Mon Sep 17 00:00:00 2001 From: Khavin Shankar Date: Wed, 18 Mar 2026 17:06:27 +0530 Subject: [PATCH 2/3] Minor Improvements (#79) --- public/locale/en.json | 10 ++++- .../LinkAbhaNumber/CreateWithAadhaar.tsx | 42 ++++++++++++++----- src/components/LinkAbhaNumber/LinkWithOtp.tsx | 31 +++++++++++--- .../pluggables/PatientHomeActions.tsx | 7 +++- .../pluggables/PatientRegistrationForm.tsx | 7 +++- 5 files changed, 77 insertions(+), 20 deletions(-) diff --git a/public/locale/en.json b/public/locale/en.json index 121710b..0585099 100644 --- a/public/locale/en.json +++ b/public/locale/en.json @@ -145,5 +145,13 @@ "verify_bio": "Verify Biometrics", "capture_fingerprint": "Capture Fingerprint", "initiate_face_auth": "Initiate Face Authentication", - "retry_face_auth": "Retry Face Authentication" + "retry_face_auth": "Retry Face Authentication", + "error_verifying_aadhaar_demographics": "Error verifying Aadhaar demographics.", + "error_verifying_aadhaar_face": "Error verifying Aadhaar face.", + "error_capturing_pid_via_face": "Error capturing PID via face.", + "error_linking_abha_number": "Error linking ABHA number.", + "otp_sent_successfully": "OTP has been sent successfully.", + "otp_verified_successfully": "OTP has been verified successfully.", + "otp_resend_successfully": "OTP has been resend successfully.", + "abha_address_created_successfully": "ABHA Address has been created successfully." } diff --git a/src/components/LinkAbhaNumber/CreateWithAadhaar.tsx b/src/components/LinkAbhaNumber/CreateWithAadhaar.tsx index 7b46f78..b428e28 100644 --- a/src/components/LinkAbhaNumber/CreateWithAadhaar.tsx +++ b/src/components/LinkAbhaNumber/CreateWithAadhaar.tsx @@ -182,11 +182,18 @@ const EnterAadhaar: FC = ({ setMemory, goTo }) => { }, }); + const handleCheckAllDisclaimers = () => { + Array.from({ length: 6 }).forEach((_, index) => { + const fieldName = `disclaimer_${index + 1}` as keyof EnterAadhaarFormValues; + form.setValue(fieldName, true, { shouldValidate: true }); + }); + }; + const sendAadhaarOtpMutation = useMutation({ mutationFn: apis.healthId.abhaCreateSendAadhaarOtp, onSuccess: (data) => { if (data) { - toast.success(data.detail); + toast.success(data.detail || t("otp_sent_successfully")); setMemory((prev) => ({ ...prev, transactionId: data.transaction_id, @@ -293,6 +300,20 @@ const EnterAadhaar: FC = ({ setMemory, goTo }) => { )} /> ))} + +
+ +
+
+ !open && setShowAuthMethods(false)} @@ -339,7 +360,7 @@ const VerifyId: FC = ({ memory, setMemory, onSuccess }) => { mutationFn: apis.healthId.abhaLoginVerifyOtp, onSuccess: (data) => { if (data) { - toast.success(t("verify_otp_success")); + toast.success(t("otp_verified_successfully")); onSuccess(data.abha_number); } }, @@ -349,7 +370,7 @@ const VerifyId: FC = ({ memory, setMemory, onSuccess }) => { mutationFn: apis.healthId.abhaLoginSendOtp, onSuccess: (data) => { if (data) { - toast.success(data.detail); + toast.success(data.detail || t("otp_resend_successfully")); form.setValue("otp", ""); setMemory((prev) => ({ ...prev, diff --git a/src/components/pluggables/PatientHomeActions.tsx b/src/components/pluggables/PatientHomeActions.tsx index 51092eb..0b553c9 100644 --- a/src/components/pluggables/PatientHomeActions.tsx +++ b/src/components/pluggables/PatientHomeActions.tsx @@ -1,10 +1,12 @@ import { useMutation, useQuery } from "@tanstack/react-query"; import { FC } from "react"; +import { I18NNAMESPACE } from "@/lib/constants"; import { LinkAbhaNumber } from "@/components/LinkAbhaNumber"; import { Patient } from "@/types/patient"; import { apis } from "@/apis"; import { toast } from "@/lib/utils"; +import { useTranslation } from "react-i18next"; type PatientHomeActionsProps = { patient: Patient; @@ -17,6 +19,7 @@ const PatientHomeActions: FC = ({ facilityId, className, }) => { + const { t } = useTranslation(I18NNAMESPACE); const { data: abhaNumber, refetch } = useQuery({ queryKey: ["abhaNumber", patient.id], queryFn: () => apis.abhaNumber.get(patient.id), @@ -27,12 +30,12 @@ const PatientHomeActions: FC = ({ mutationFn: apis.healthId.linkAbhaNumberAndPatient, onSuccess: (data) => { if (data) { - toast.success(data.detail); + toast.success(data.detail || t("abha_number_linked_successfully")); refetch(); } }, onError: (error) => { - toast.error(error.message); + toast.error(error.message || t("error_linking_abha_number")); }, }); diff --git a/src/components/pluggables/PatientRegistrationForm.tsx b/src/components/pluggables/PatientRegistrationForm.tsx index 8bb707c..07a8765 100644 --- a/src/components/pluggables/PatientRegistrationForm.tsx +++ b/src/components/pluggables/PatientRegistrationForm.tsx @@ -1,6 +1,7 @@ import { FC, useEffect } from "react"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; +import { I18NNAMESPACE } from "@/lib/constants"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { LinkAbhaNumber } from "../LinkAbhaNumber"; @@ -9,6 +10,7 @@ import { UseFormReturn } from "react-hook-form"; import { apis } from "@/apis"; import { enforceAbhaNumberLinking } from "@/config"; import { toast } from "@/lib/utils"; +import { useTranslation } from "react-i18next"; type PatientRegistrationFormProps = { form: UseFormReturn; @@ -22,6 +24,7 @@ const PatientRegistrationForm: FC = ({ patientId, }) => { const queryClient = useQueryClient(); + const { t } = useTranslation(I18NNAMESPACE); const { data: abhaNumber, refetch } = useQuery({ queryKey: ["abhaNumber", patientId], @@ -41,12 +44,12 @@ const PatientRegistrationForm: FC = ({ mutationFn: apis.healthId.linkAbhaNumberAndPatient, onSuccess: (data) => { if (data) { - toast.success(data.detail); + toast.success(data.detail || t("abha_number_linked_successfully")); refetch(); } }, onError: (error) => { - toast.error(error.message); + toast.error(error.message || t("error_linking_abha_number")); }, }); From ad00424c9da8525e4bb5c8be3d2a2912b8c9ea86 Mon Sep 17 00:00:00 2001 From: Khavin Shankar Date: Wed, 18 Mar 2026 17:06:44 +0530 Subject: [PATCH 3/3] Use meta from props for handling config instead of envs (#68) --- .../ConfigureHealthFacilityForm.tsx | 15 +++++++--- src/components/GenerateScanAndShareQR.tsx | 7 +++-- .../LinkAbhaNumber/CreateWithAadhaar.tsx | 8 +++-- .../pluggables/EncounterActions.tsx | 3 +- .../pluggables/FacilityHomeActions.tsx | 20 ++++++++----- ...PatientDetailsTabDemographyGeneralInfo.tsx | 10 ++++--- .../pluggables/PatientHomeActions.tsx | 3 +- .../pluggables/PatientRegistrationForm.tsx | 9 +++--- .../pluggables/PatientSearchActions.tsx | 3 +- src/config.ts | 7 ----- src/types/meta.ts | 14 +++++++++ src/vite-env.d.ts | 29 +++++++++++++++---- 12 files changed, 88 insertions(+), 40 deletions(-) create mode 100644 src/types/meta.ts diff --git a/src/components/ConfigureHealthFacilityForm.tsx b/src/components/ConfigureHealthFacilityForm.tsx index dd436af..e58bedb 100644 --- a/src/components/ConfigureHealthFacilityForm.tsx +++ b/src/components/ConfigureHealthFacilityForm.tsx @@ -26,6 +26,7 @@ import { GenerateScanAndShareQR } from "./GenerateScanAndShareQR"; import { HealthFacility } from "@/types/healthFacility"; import { I18NNAMESPACE } from "@/lib/constants"; import { Input } from "@/components/ui/input"; +import { Meta } from "@/types/meta"; import { apis } from "@/apis"; import { toast } from "@/lib/utils"; import { useForm } from "react-hook-form"; @@ -34,6 +35,7 @@ import { zodResolver } from "@hookform/resolvers/zod"; type ConfigureHealthFacilityFormProps = { facilityId: string; onSuccess?: (data: HealthFacility) => void; + meta?: Meta; }; const configureHealthFacilityFormSchema = z.object({ @@ -44,9 +46,11 @@ type ConfigureHealthFacilityFormValues = z.infer< typeof configureHealthFacilityFormSchema >; -export const ConfigureHealthFacilityForm: FC< - ConfigureHealthFacilityFormProps -> = ({ facilityId, onSuccess }) => { +export const ConfigureHealthFacilityForm: FC = ({ + facilityId, + onSuccess, + meta, +}) => { const { t } = useTranslation(I18NNAMESPACE); const { data: healthFacility, refetch } = useQuery({ @@ -221,7 +225,10 @@ export const ConfigureHealthFacilityForm: FC< {healthFacility && ( - + )}
); diff --git a/src/components/GenerateScanAndShareQR.tsx b/src/components/GenerateScanAndShareQR.tsx index 9040ce7..8042b28 100644 --- a/src/components/GenerateScanAndShareQR.tsx +++ b/src/components/GenerateScanAndShareQR.tsx @@ -13,7 +13,6 @@ import { Button } from "./ui/button"; import { I18NNAMESPACE } from "@/lib/constants"; import { Input } from "@/components/ui/input"; import { QRCodeSVG } from "qrcode.react"; -import { scanAndShareUrl } from "@/config"; import { useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { z } from "zod"; @@ -21,6 +20,7 @@ import { zodResolver } from "@hookform/resolvers/zod"; type GenerateScanAndShareQRProps = { healthFacilityId: string; + scanAndShareUrl?: string; }; const scanAndShareQrFormSchema = z.object({ @@ -29,6 +29,7 @@ const scanAndShareQrFormSchema = z.object({ export const GenerateScanAndShareQR: FC = ({ healthFacilityId, + scanAndShareUrl, }) => { const { t } = useTranslation(I18NNAMESPACE); @@ -84,7 +85,7 @@ export const GenerateScanAndShareQR: FC = ({ document.body.removeChild(downloadLink); }; - function onSubmit(_values: z.infer) { + function onSubmit() { downloadQR(); } @@ -135,7 +136,7 @@ export const GenerateScanAndShareQR: FC = ({ /> - {!!scanAndShareQrForm.watch("counterName") && ( + {!!scanAndShareQrForm.watch("counterName") && scanAndShareQrValue && (
= ({ setMemory, goTo }) => { const { t } = useTranslation(I18NNAMESPACE); const { healthFacility, currentUser } = useLinkAbhaNumberContext(); + const faceAuthUrl = window.__CARE_PLUGIN_RUNTIME__?.meta?.care_abdm_fe?.config?.faceAuthUrl; + const form = useForm({ resolver: zodResolver(enterAadhaarFormSchema), defaultValues: { @@ -363,7 +364,7 @@ const EnterAadhaar: FC = ({ setMemory, goTo }) => { > {t("verify_with_bio")} - + }
@@ -915,6 +916,7 @@ const VerifyAadhaarWithFace: FC = ({ }) => { const { t } = useTranslation(I18NNAMESPACE); const [isPolling, setIsPolling] = useState(false); + const faceAuthUrl = window?.__CARE_PLUGIN_RUNTIME__?.meta?.care_abdm_fe?.config?.faceAuthUrl; const form = useForm({ resolver: zodResolver(verifyAadhaarWithFaceFormSchema), diff --git a/src/components/pluggables/EncounterActions.tsx b/src/components/pluggables/EncounterActions.tsx index 8018c3a..5d5048c 100644 --- a/src/components/pluggables/EncounterActions.tsx +++ b/src/components/pluggables/EncounterActions.tsx @@ -13,6 +13,7 @@ import { Button } from "@/components/ui/button"; import CreateConsentRequestForm from "../CreateConsentRequestForm"; import { Encounter } from "@/types/encounter"; import { I18NNAMESPACE } from "@/lib/constants"; +import { WithMeta } from "@/types/meta"; import { apis } from "@/apis"; import { cn } from "@/lib/utils"; import { useTranslation } from "react-i18next"; @@ -22,7 +23,7 @@ type EncounterActionsProps = { className?: string; }; -const EncounterActions: FC = ({ +const EncounterActions: FC> = ({ encounter, className, }) => { diff --git a/src/components/pluggables/FacilityHomeActions.tsx b/src/components/pluggables/FacilityHomeActions.tsx index 35e2acb..54928ac 100644 --- a/src/components/pluggables/FacilityHomeActions.tsx +++ b/src/components/pluggables/FacilityHomeActions.tsx @@ -1,9 +1,4 @@ import { FC, useState } from "react"; -import { useTranslation } from "react-i18next"; -import { Button } from "@/components/ui/button"; -import { Facility } from "@/types/facility"; -import { SettingsIcon } from "lucide-react"; -import { ConfigureHealthFacilityForm } from "../ConfigureHealthFacilityForm"; import { Sheet, SheetContent, @@ -12,15 +7,25 @@ import { SheetTitle, SheetTrigger, } from "@/components/ui/sheet"; -import { useQueryClient } from "@tanstack/react-query"; + +import { Button } from "@/components/ui/button"; +import { ConfigureHealthFacilityForm } from "../ConfigureHealthFacilityForm"; +import { Facility } from "@/types/facility"; import { I18NNAMESPACE } from "@/lib/constants"; +import { SettingsIcon } from "lucide-react"; +import { WithMeta } from "@/types/meta"; +import { useQueryClient } from "@tanstack/react-query"; +import { useTranslation } from "react-i18next"; type FacilityHomeActionsProps = { facility: Facility; className?: string; }; -const FacilityHomeActions: FC = ({ facility }) => { +const FacilityHomeActions: FC> = ({ + facility, + __meta, +}) => { const { t } = useTranslation(I18NNAMESPACE); const queryClient = useQueryClient(); @@ -59,6 +64,7 @@ const FacilityHomeActions: FC = ({ facility }) => { }); setOpen(false); }} + meta={__meta} />
diff --git a/src/components/pluggables/PatientDetailsTabDemographyGeneralInfo.tsx b/src/components/pluggables/PatientDetailsTabDemographyGeneralInfo.tsx index 712a30e..0709803 100644 --- a/src/components/pluggables/PatientDetailsTabDemographyGeneralInfo.tsx +++ b/src/components/pluggables/PatientDetailsTabDemographyGeneralInfo.tsx @@ -1,11 +1,13 @@ +import { FileDownIcon, ImageDownIcon } from "lucide-react"; +import { useMutation, useQuery } from "@tanstack/react-query"; + +import { Button } from "@/components/ui/button"; import { FC } from "react"; import { I18NNAMESPACE } from "@/lib/constants"; import { Patient } from "@/types/patient"; +import { WithMeta } from "@/types/meta"; import { apis } from "@/apis"; -import { useMutation, useQuery } from "@tanstack/react-query"; import { useTranslation } from "react-i18next"; -import { Button } from "@/components/ui/button"; -import { ImageDownIcon, FileDownIcon } from "lucide-react"; type PatientDetailsTabDemographyGeneralInfoProps = { patientData: Patient; @@ -14,7 +16,7 @@ type PatientDetailsTabDemographyGeneralInfoProps = { }; const PatientDetailsTabDemographyGeneralInfo: FC< - PatientDetailsTabDemographyGeneralInfoProps + WithMeta > = ({ patientId }) => { const { t } = useTranslation(I18NNAMESPACE); diff --git a/src/components/pluggables/PatientHomeActions.tsx b/src/components/pluggables/PatientHomeActions.tsx index 0b553c9..637a9fb 100644 --- a/src/components/pluggables/PatientHomeActions.tsx +++ b/src/components/pluggables/PatientHomeActions.tsx @@ -4,6 +4,7 @@ import { FC } from "react"; import { I18NNAMESPACE } from "@/lib/constants"; import { LinkAbhaNumber } from "@/components/LinkAbhaNumber"; import { Patient } from "@/types/patient"; +import { WithMeta } from "@/types/meta"; import { apis } from "@/apis"; import { toast } from "@/lib/utils"; import { useTranslation } from "react-i18next"; @@ -14,7 +15,7 @@ type PatientHomeActionsProps = { className?: string; }; -const PatientHomeActions: FC = ({ +const PatientHomeActions: FC> = ({ patient, facilityId, className, diff --git a/src/components/pluggables/PatientRegistrationForm.tsx b/src/components/pluggables/PatientRegistrationForm.tsx index 07a8765..0c499ca 100644 --- a/src/components/pluggables/PatientRegistrationForm.tsx +++ b/src/components/pluggables/PatientRegistrationForm.tsx @@ -7,8 +7,8 @@ import { Label } from "@/components/ui/label"; import { LinkAbhaNumber } from "../LinkAbhaNumber"; import { ShowAbhaProfile } from "../LinkAbhaNumber/ShowAbhaProfile"; import { UseFormReturn } from "react-hook-form"; +import { WithMeta } from "@/types/meta"; import { apis } from "@/apis"; -import { enforceAbhaNumberLinking } from "@/config"; import { toast } from "@/lib/utils"; import { useTranslation } from "react-i18next"; @@ -18,10 +18,11 @@ type PatientRegistrationFormProps = { patientId?: string; }; -const PatientRegistrationForm: FC = ({ +const PatientRegistrationForm: FC> = ({ form, facilityId, patientId, + __meta, }) => { const queryClient = useQueryClient(); const { t } = useTranslation(I18NNAMESPACE); @@ -92,9 +93,9 @@ const PatientRegistrationForm: FC = ({ return (
= ({ +const PatientSearchActions: FC> = ({ facilityId, className, }) => { diff --git a/src/config.ts b/src/config.ts index f0405c2..e69de29 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,7 +0,0 @@ -export const scanAndShareUrl = import.meta.env.REACT_SCAN_AND_SHARE_URL; - -export const faceAuthUrl = - import.meta.env.REACT_FACE_AUTH_URL || "https://phrsbx.abdm.gov.in/face-auth"; - -export const enforceAbhaNumberLinking = - import.meta.env.REACT_ENFORCE_ABHA_NUMBER_LINKING === "true"; \ No newline at end of file diff --git a/src/types/meta.ts b/src/types/meta.ts new file mode 100644 index 0000000..9429b2b --- /dev/null +++ b/src/types/meta.ts @@ -0,0 +1,14 @@ +export type MetaConfig = { + enforceAbhaNumberLinking?: boolean; + scanAndShareUrl?: string; +}; + +export type Meta = { + name?: string; + url?: string; + config?: MetaConfig; +}; + +export type WithMeta = T & { + __meta?: Meta; +}; diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts index 5af4fa2..a765633 100644 --- a/src/vite-env.d.ts +++ b/src/vite-env.d.ts @@ -1,14 +1,33 @@ /// /// -interface ImportMetaEnv { - readonly REACT_SCAN_AND_SHARE_URL: string; - readonly REACT_FACE_AUTH_URL: string; - readonly REACT_ENFORCE_ABHA_NUMBER_LINKING: string; +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +interface ImportMetaEnv {} + +interface CareAbdmFePluginConfig { + faceAuthUrl?: string; + enforceAbhaNumberLinking?: boolean; + scanAndShareUrl?: string; +} + +interface CarePluginRuntimeMeta { + care_abdm_fe?: { + config?: CareAbdmFePluginConfig; + }; +} + +interface CarePluginRuntime { + meta?: CarePluginRuntimeMeta; } declare global { - var __CORE_ENV__: { + const __CORE_ENV__: { readonly apiUrl: string; }; + + interface Window { + __CARE_PLUGIN_RUNTIME__?: CarePluginRuntime; + } } + +export {};