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

Enhance Patient Search: User-Friendly Error Message and Accessibility Improvements #9858

Merged
Show file tree
Hide file tree
Changes from 2 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
13 changes: 13 additions & 0 deletions public/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@
"action_irreversible": "This action is irreversible",
"actions": "Actions",
"active": "Active",
"active_encounter": "Active Encounters",
"active_files": "Active Files",
"active_prescriptions": "Active Prescriptions",
"add": "Add",
Expand Down Expand Up @@ -471,6 +472,7 @@
"board_view": "Board View",
"book_an_appointment_with": "Book an appointment with",
"book_appointment": "Book Appointment",
"book_new_appoitment": "Book a new appointment",
"booked": "Booked",
"booked_by": "Booked by",
"bradycardia": "Bradycardia",
Expand Down Expand Up @@ -639,10 +641,12 @@
"create_add_more": "Create & Add More",
"create_asset": "Create Asset",
"create_consultation": "Create Consultation",
"create_encounter": "Create Encounter",
"create_facility": "Create a new facility",
"create_new_abha_address": "Create New ABHA Address",
"create_new_abha_profile": "Don't have an ABHA Number",
"create_new_asset": "Create New Asset",
"create_new_encounter": "Create a new encounter to get started",
"create_position_preset": "Create a new position preset",
"create_position_preset_description": "Creates a new position preset in Care from the current position of the camera for the given name",
"create_preset_prerequisite": "To create presets for this bed, you'll need to link the camera to the bed first.",
Expand Down Expand Up @@ -986,6 +990,7 @@
"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",
"get_tests": "Get Tests",
"go_back": "Go Back",
"goal": "Our goal is to continuously improve the quality and accessibility of public healthcare services using digital tools.",
"granted_on": "Granted On",
"has_allergies": "Has Allergies",
Expand Down Expand Up @@ -1198,6 +1203,7 @@
"min_password_len_8": "Minimum password length 8",
"min_time_bw_doses": "Min. time b/w doses",
"minimize": "Minimize",
"missing_required_param_for_patient_verify": "Missing required parameters for patient verification",
"mobile": "Mobile",
"mobile_number": "Mobile Number",
"mobile_number_different_from_aadhaar_mobile_number": "We have noticed that you have entered a mobile number that is different from the one linked to your Aadhaar. We will send an OTP to this number to link it with your Abha number.",
Expand Down Expand Up @@ -1245,6 +1251,7 @@
"no_data_found": "No data found",
"no_doctors_found": "No Doctors Found",
"no_duplicate_facility": "You should not create duplicate facilities",
"no_encounter_found": "No encounters found",
"no_facilities": "No Facilities found",
"no_facilities_found": "No facilities found",
"no_files_found": "No {{type}} files found",
Expand Down Expand Up @@ -1425,6 +1432,7 @@
"please_check_your_messages": "Please check your messages",
"please_confirm_password": "Please confirm your new password.",
"please_enter_a_reason_for_the_shift": "Please enter a reason for the shift.",
"please_enter_correct_bith_year": "Please enter the correct birth year to verify the patient details.",
"please_enter_current_password": "Please enter your current password.",
"please_enter_new_password": "Please enter your new password.",
"please_enter_username": "Please enter the username",
Expand Down Expand Up @@ -1502,6 +1510,7 @@
"questionnaire": "Questionnaire",
"questionnaire_error_loading": "Error loading questionnaire",
"questionnaire_not_exist": "The questionnaire you tried to access does not exist.",
"quick_action": "Quick Actions",
"raise_consent_request": "Raise a consent request to fetch patient records over ABDM",
"ration_card__APL": "APL",
"ration_card__BPL": "BPL",
Expand Down Expand Up @@ -1606,6 +1615,7 @@
"scan_asset_qr": "Scan Asset QR!",
"schedule": "Schedule",
"schedule_appointment": "Schedule Appointment",
"schedule_appoitment_or_create_new_encounter": "Schedule an appointment or create a new encounter",
"schedule_calendar": "Schedule Calendar",
"schedule_information": "Schedule Information",
"scheduled": "Scheduled",
Expand Down Expand Up @@ -1710,6 +1720,7 @@
"start_consultation": "Start Consultation",
"start_datetime": "Start Date/Time",
"start_dosage": "Start Dosage",
"start_new_clinical_encounter": "Start a new clinical encounter",
"start_review": "Start Review",
"state": "State",
"status": "Status",
Expand Down Expand Up @@ -1878,6 +1889,7 @@
"ventilator_oxygen_modality": "Oxygen Modality",
"ventilator_oxygen_modality_oxygen_rate": "Oxygen Flow Rate",
"ventilator_spo2": "SpO₂",
"verification_failed": "Verification Failed",
"verify_and_link": "Verify and Link",
"verify_otp": "Verify OTP",
"verify_otp_error": "Failed to verify OTP. Please try again later.",
Expand All @@ -1891,6 +1903,7 @@
"view": "View",
"view_abdm_records": "View ABDM Records",
"view_all_details": "View All Details",
"view_and_manage_encounter": "View and manage patient encounters",
"view_asset": "View Assets",
"view_cns": "View CNS",
"view_consultation": "View Latest Encounter",
Expand Down
21 changes: 16 additions & 5 deletions src/components/Form/FormFields/TextFormField.tsx
Copy link
Member

Choose a reason for hiding this comment

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

let's not edit anything in this component. this is deprecated. use newer components instead

Copy link
Contributor Author

@JavidSumra JavidSumra Jan 9, 2025

Choose a reason for hiding this comment

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

@rithviknishad Shall I replace it with SearchByMultipleFields on Users and Resource Page?

Copy link
Member

Choose a reason for hiding this comment

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

yup

Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const TextFormField = forwardRef((props: TextFormFieldProps, ref) => {
const hasTrailing = !!(trailing || trailingFocused);
const hasIcon = hasLeading || hasTrailing;
const [showPassword, setShowPassword] = useState(false);
const [isFocused, setIsFocused] = useState(false);

const getPasswordFieldType = () => {
return showPassword ? "text" : "password";
Expand Down Expand Up @@ -72,7 +73,7 @@ const TextFormField = forwardRef((props: TextFormFieldProps, ref) => {
ref={ref as React.Ref<HTMLInputElement>}
id={field.id}
className={classNames(
"cui-input-base peer",
"cui-input-base",
hasLeading && (props.leadingPadding || "pl-10"),
hasTrailing && (props.trailingPadding || "pr-10"),
field.error && "border-danger-500",
Expand All @@ -84,6 +85,8 @@ const TextFormField = forwardRef((props: TextFormFieldProps, ref) => {
value={field.value}
required={field.required}
onChange={(e) => field.handleChange(e.target.value)}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
/>
{props.clearable && field.value && (
<button
Expand Down Expand Up @@ -121,10 +124,14 @@ const TextFormField = forwardRef((props: TextFormFieldProps, ref) => {
</div>
) : (
<>
<div className="absolute inset-y-0 left-0 flex translate-y-0 items-center pl-3 opacity-100 transition-all delay-300 duration-500 ease-in-out peer-focus:translate-y-1 peer-focus:opacity-0">
<div
className={`absolute inset-y-0 left-0 flex items-center pl-3 transition-all delay-300 duration-500 ease-in-out ${isFocused ? "translate-y-1 opacity-0" : "translate-y-0 opacity-100"}`}
>
{leading}
</div>
<div className="absolute inset-y-0 left-0 flex -translate-y-1 items-center pl-3 opacity-0 transition-all delay-300 duration-500 ease-in-out peer-focus:translate-y-0 peer-focus:opacity-100">
<div
className={`absolute inset-y-0 left-0 flex items-center pl-3 transition-all delay-300 duration-500 ease-in-out ${isFocused ? "translate-y-0 opacity-100" : "-translate-y-1 opacity-0"}`}
>
{leadingFocused}
</div>
</>
Expand All @@ -136,10 +143,14 @@ const TextFormField = forwardRef((props: TextFormFieldProps, ref) => {
</div>
) : (
<>
<div className="absolute inset-y-0 right-0 flex translate-y-0 items-center pr-3 opacity-100 transition-all delay-300 duration-500 ease-in-out peer-focus:translate-y-1 peer-focus:opacity-0">
<div
className={`absolute inset-y-0 right-0 flex items-center pr-3 transition-all delay-300 duration-500 ease-in-out ${isFocused ? "translate-y-1 opacity-0" : "translate-y-0 opacity-100"}`}
>
{trailing}
</div>
<div className="absolute inset-y-0 right-0 flex -translate-y-1 items-center pr-3 opacity-0 transition-all delay-300 duration-500 ease-in-out peer-focus:translate-y-0 peer-focus:opacity-100">
<div
className={`absolute inset-y-0 right-0 flex items-center pr-3 transition-all delay-300 duration-500 ease-in-out ${isFocused ? "translate-y-0 opacity-100" : "-translate-y-1 opacity-0"}`}
>
{trailingFocused}
</div>
</>
Expand Down
55 changes: 42 additions & 13 deletions src/pages/Patients/VerifyPatient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useMutation, useQuery } from "@tanstack/react-query";
import { AlertCircle, CalendarIcon } from "lucide-react";
import { Link, useQueryParams } from "raviger";
import { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";

import CareIcon from "@/CAREUI/icons/CareIcon";
Expand All @@ -20,6 +21,8 @@ import { Avatar } from "@/components/Common/Avatar";
import CreateEncounterForm from "@/components/Encounter/CreateEncounterForm";
import { EncounterCard } from "@/components/Facility/EncounterCard";

import useAppHistory from "@/hooks/useAppHistory";

import routes from "@/Utils/request/api";
import mutate from "@/Utils/request/mutate";
import query from "@/Utils/request/query";
Expand All @@ -30,8 +33,14 @@ import { Encounter } from "@/types/emr/encounter";
export default function VerifyPatient(props: { facilityId: string }) {
const [qParams] = useQueryParams();
const { phone_number, year_of_birth, partial_id } = qParams;
const { goBack } = useAppHistory();
const { t } = useTranslation();

const { mutate: verifyPatient, data: patientData } = useMutation({
const {
mutate: verifyPatient,
data: patientData,
isError,
} = useMutation({
mutationFn: mutate(routes.patient.search_retrieve),
onError: (error) => {
const errorData = error.cause as { errors: { msg: string[] } };
Expand Down Expand Up @@ -69,7 +78,7 @@ export default function VerifyPatient(props: { facilityId: string }) {
<Alert variant="destructive">
<AlertCircle className="h-4 w-4" />
<AlertDescription>
Missing required parameters for patient verification
{t("missing_required_param_for_patient_verify")}
</AlertDescription>
</Alert>
) : patientData ? (
Expand Down Expand Up @@ -109,9 +118,9 @@ export default function VerifyPatient(props: { facilityId: string }) {

<Card>
<CardHeader>
<CardTitle>Quick Actions</CardTitle>
<CardTitle>{t("quick_action")}</CardTitle>
<CardDescription>
Schedule an appointment or create a new encounter
{t("schedule_appoitment_or_create_new_encounter")}
</CardDescription>
</CardHeader>
<CardContent className="grid gap-4 sm:grid-cols-1 md:grid-cols-2">
Expand All @@ -131,10 +140,10 @@ export default function VerifyPatient(props: { facilityId: string }) {
</div>
<div className="flex flex-col items-start gap-0.5">
<span className="text-base md:text-lg font-semibold text-gray-800 group-hover:text-primary transition-colors line-clamp-1">
Schedule Appointment
{t("schedule_appointment")}
</span>
<span className="text-xs md:text-sm text-gray-500 line-clamp-1">
Book a new appointment
{t("book_new_appoitment")}
</span>
</div>
<CareIcon
Expand Down Expand Up @@ -165,10 +174,10 @@ export default function VerifyPatient(props: { facilityId: string }) {
</div>
<div className="flex flex-col items-start gap-0.5">
<span className="text-base md:text-lg font-semibold text-gray-800 group-hover:text-primary transition-colors line-clamp-1">
Create Encounter
{t("create_encounter")}
</span>
<span className="text-xs md:text-sm text-gray-500 line-clamp-1">
Start a new clinical encounter
{t("start_new_clinical_encounter")}
</span>
</div>
<CareIcon
Expand All @@ -185,9 +194,9 @@ export default function VerifyPatient(props: { facilityId: string }) {

<Card>
<CardHeader className="pb-2">
<CardTitle>Active Encounters</CardTitle>
<CardTitle>{t("active_encounter")}</CardTitle>
<CardDescription>
View and manage patient encounters
{t("view_and_manage_encounter")}
</CardDescription>
</CardHeader>
<CardContent className="flex flex-col gap-3 pt-2">
Expand All @@ -206,17 +215,37 @@ export default function VerifyPatient(props: { facilityId: string }) {
/>
</div>
<h3 className="text-base md:text-lg font-semibold mb-1">
No encounters found
{t("no_encounter_found")}
</h3>
<p className="text-xs md:text-sm text-muted-foreground">
Create a new encounter to get started
{t("create_new_encounter")}
</p>
</div>
)}
</CardContent>
</Card>
</div>
) : null}
) : (
isError && (
<div className="h-screen w-full flex items-center justify-center">
<div className="flex flex-col items-center justify-center text-center">
<h3 className="text-xl font-semibold mb-1">
{t("verification_failed")}
</h3>
<p className="text-sm text-muted-foreground mb-6">
{t("please_enter_correct_bith_year")}
</p>
<Button
variant={"primary_gradient"}
className="gap-3 group"
onClick={() => goBack()}
>
{t("go_back")}
</Button>
</div>
</div>
)
JavidSumra marked this conversation as resolved.
Show resolved Hide resolved
)}
</div>
);
}
Loading