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

Issues/8607/review missed #9259

Closed
Closed
Show file tree
Hide file tree
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
258 changes: 143 additions & 115 deletions src/components/Patient/ManagePatients.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,40 @@
import dayjs from "dayjs";
import { Link, navigate } from "raviger";
import { ReactNode, useCallback, useEffect, useState } from "react";
import { ReactNode, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";

import Chip from "@/CAREUI/display/Chip";
import CountBlock from "@/CAREUI/display/Count";
import FilterBadge from "@/CAREUI/display/FilterBadge";
import RecordMeta from "@/CAREUI/display/RecordMeta";
import CareIcon from "@/CAREUI/icons/CareIcon";
import { AdvancedFilterButton } from "@/CAREUI/interactive/FiltersSlideover";

import { Badge } from "@/components/ui/badge";

import { Avatar } from "@/components/Common/Avatar";
import ButtonV2 from "@/components/Common/ButtonV2";
import { ExportMenu } from "@/components/Common/Export";
import Loading from "@/components/Common/Loading";
import Page from "@/components/Common/Page";
import SearchByMultipleFields from "@/components/Common/SearchByMultipleFields";
import SortDropdownMenu from "@/components/Common/SortDropdown";
import Tabs from "@/components/Common/Tabs";
import { ICD11DiagnosisModel } from "@/components/Diagnosis/types";
import { getDiagnosesByIds } from "@/components/Diagnosis/utils";
import FacilitiesSelectDialogue from "@/components/ExternalResult/FacilitiesSelectDialogue";
import DoctorVideoSlideover from "@/components/Facility/DoctorVideoSlideover";
import { FacilityModel, PatientCategory } from "@/components/Facility/models";
import { PhoneNumberValidator } from "@/components/Form/FieldValidators";
import PhoneNumberFormField from "@/components/Form/FormFields/PhoneNumberFormField";
import { FieldChangeEvent } from "@/components/Form/FormFields/Utils";
import SearchInput from "@/components/Form/SearchInput";
import {
DIAGNOSES_FILTER_LABELS,
DiagnosesFilterKey,
FILTER_BY_DIAGNOSES_KEYS,
} from "@/components/Patient/DiagnosesFilter";
import PatientFilter from "@/components/Patient/PatientFilter";
import { isPatientMandatoryDataFilled } from "@/components/Patient/Utils";

import useAuthUser from "@/hooks/useAuthUser";
import useFilters from "@/hooks/useFilters";
Expand All @@ -27,36 +51,17 @@ import {
} from "@/common/constants";
import { parseOptionId } from "@/common/utils";

import { triggerGoal } from "@/Integrations/Plausible";
import * as Notification from "@/Utils/Notifications";
import routes from "@/Utils/request/api";

import Chip from "../../CAREUI/display/Chip";
import CountBlock from "../../CAREUI/display/Count";
import FilterBadge from "../../CAREUI/display/FilterBadge";
import RecordMeta from "../../CAREUI/display/RecordMeta";
import CareIcon from "../../CAREUI/icons/CareIcon";
import { AdvancedFilterButton } from "../../CAREUI/interactive/FiltersSlideover";
import { triggerGoal } from "../../Integrations/Plausible";
import * as Notification from "../../Utils/Notifications";
import request from "../../Utils/request/request";
import useQuery from "../../Utils/request/useQuery";
import request from "@/Utils/request/request";
import useQuery from "@/Utils/request/useQuery";
import {
formatPatientAge,
humanizeStrings,
isAntenatal,
parsePhoneNumber,
} from "../../Utils/utils";
import { ICD11DiagnosisModel } from "../Diagnosis/types";
import { getDiagnosesByIds } from "../Diagnosis/utils";
import FacilitiesSelectDialogue from "../ExternalResult/FacilitiesSelectDialogue";
import DoctorVideoSlideover from "../Facility/DoctorVideoSlideover";
import { FacilityModel, PatientCategory } from "../Facility/models";
import {
DIAGNOSES_FILTER_LABELS,
DiagnosesFilterKey,
FILTER_BY_DIAGNOSES_KEYS,
} from "./DiagnosesFilter";
import PatientFilter from "./PatientFilter";
import { isPatientMandatoryDataFilled } from "./Utils";
} from "@/Utils/utils";

interface TabPanelProps {
children?: ReactNode;
Expand Down Expand Up @@ -90,7 +95,6 @@ export const PatientManager = () => {
Pagination,
FilterBadges,
resultsPerPage,
clearSearch,
} = useFilters({
limit: 12,
cacheBlacklist: [
Expand All @@ -107,6 +111,30 @@ export const PatientManager = () => {
const [diagnoses, setDiagnoses] = useState<ICD11DiagnosisModel[]>([]);
const [showDialog, setShowDialog] = useState<"create" | "list-discharged">();
const [showDoctors, setShowDoctors] = useState(false);
const [phoneNumber, _setPhoneNumber] = useState("");
const [emergencyPhoneNumber, _setEmergencyPhoneNumber] = useState("");

const setPhoneNumber = (value: string) => {
_setPhoneNumber(value);
const error = PhoneNumberValidator()(value);
if (!error) {
updateQuery({ phone_number: value });
}
if ((value === "+91" || value === "") && qParams.phone_number) {
updateQuery({ phone_number: null });
}
};

const setEmergencyPhoneNumber = (value: string) => {
_setEmergencyPhoneNumber(value);
const error = PhoneNumberValidator()(value);
if (!error) {
updateQuery({ emergency_phone_number: value });
}
if ((value === "+91" || value === "") && qParams.emergency_phone_number) {
updateQuery({ emergency_phone_number: null });
}
};

const tabValue =
qParams.last_consultation__new_discharge_reason ||
Expand Down Expand Up @@ -293,6 +321,14 @@ export const PatientManager = () => {

const { loading: isLoading, data } = useQuery(routes.patientList, {
query: params,
onResponse: () => {
if (!params.phone_number) {
_setPhoneNumber("+91");
}
if (!params.emergency_phone_number) {
_setEmergencyPhoneNumber("+91");
}
},
});

const getTheCategoryFromId = () => {
Expand Down Expand Up @@ -596,15 +632,26 @@ export const PatientManager = () => {
)}
{patient.review_time &&
!patient.last_consultation?.discharge_date &&
Number(patient.last_consultation?.review_interval) > 0 &&
dayjs().isAfter(patient.review_time) && (
<Chip
size="small"
variant="danger"
startIcon="l-clock"
text="Review Missed"
/>
Number(patient.last_consultation?.review_interval) > 0 && (
<Badge
variant={
dayjs().isAfter(patient.review_time)
? "purple"
: "success"
}
className="flex items-center gap-1"
>
<i className="icon-class l-clock"></i>
{dayjs().isAfter(patient.review_time)
? `Review Missed ${Math.abs(
dayjs().diff(dayjs(patient.review_time), "days"),
)} days ago`
: `Review Due in ${Math.abs(
dayjs(patient.review_time).diff(dayjs(), "days"),
)} days`}
</Badge>
)}

{patient.last_consultation?.is_readmission && (
<Chip
size="small"
Expand Down Expand Up @@ -745,74 +792,22 @@ export const PatientManager = () => {
);
}

const queryField = <T,>(name: string, defaultValue?: T) => {
return {
name,
value: qParams[name] || defaultValue,
onChange: (e: FieldChangeEvent<T>) => updateQuery({ [e.name]: e.value }),
};
};

const onlyAccessibleFacility =
permittedFacilities?.count === 1 ? permittedFacilities.results[0] : null;

const searchOptions = [
Copy link
Contributor

Choose a reason for hiding this comment

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

Merge error; Part of SearchByMultipleFields, and as such should be included.

{
key: "phone_number",
label: "Phone Number",
type: "phone" as const,
placeholder: "Search_by_phone_number",
value: qParams.phone_number || "",
shortcutKey: "p",
},
{
key: "name",
label: "Name",
type: "text" as const,
placeholder: "search_by_patient_name",
value: qParams.name || "",
shortcutKey: "n",
},
{
key: "patient_no",
label: "IP/OP No",
type: "text" as const,
placeholder: "search_by_patient_no",
value: qParams.patient_no || "",
shortcutKey: "u",
},
{
key: "emergency_contact_number",
label: "Emergency Contact Phone Number",
type: "phone" as const,
placeholder: "search_by_emergency_phone_number",
value: qParams.emergency_phone_number || "",
shortcutKey: "e",
},
];

const handleSearch = useCallback(
(key: string, value: string) => {
const updatedQuery = {
phone_number:
key === "phone_number"
? value.length >= 13 || value === ""
? value
: undefined
: undefined,
name: key === "name" ? value : undefined,
patient_no: key === "patient_no" ? value : undefined,
emergency_phone_number:
key === "emergency_contact_number"
? value.length >= 13 || value === ""
? value
: undefined
: undefined,
};

updateQuery(updatedQuery);
},
[updateQuery],
);

return (
<Page
title={t("patients")}
hideBack={true}
breadcrumbs={false}
className="px-4 md:px-6"
options={
<div className="flex w-full flex-col items-center justify-between lg:flex-row">
<div className="mb-2 flex w-full flex-col items-center lg:mb-0 lg:w-fit lg:flex-row lg:gap-5">
Expand Down Expand Up @@ -991,23 +986,59 @@ export const PatientManager = () => {
}}
/>

<div className="mt-4 gap-4 lg:gap-16 flex flex-col lg:flex-row lg:items-center">
<div id="total-patientcount">
<CountBlock
text={t("total_patients")}
count={data?.count || 0}
loading={isLoading}
icon="d-patient"
/>
<div className="manualGrid my-4 mb-[-12px] mt-5 grid-cols-1 gap-3 px-2 sm:grid-cols-4 md:px-0">
<div className="mt-2 flex h-full flex-col gap-3 xl:flex-row">
<div className="flex-1" id="total-patientcount">
<CountBlock
text="Total Patients"
count={data?.count || 0}
loading={isLoading}
icon="l-user-injured"
className="pb-12"
/>
</div>
</div>
<div className="col-span-3 w-full">
<div className="mt-2">
<div className="mb-4 mt-1 md:flex md:gap-4">
<SearchInput
label="Search by Patient"
placeholder="Enter patient name"
{...queryField("name")}
className="w-full grow"
/>
<SearchInput
label="Search by IP/OP Number"
placeholder="Enter IP/OP Number"
secondary
{...queryField("patient_no")}
className="w-full grow"
/>
</div>
<div className="mb-4 md:flex md:gap-4">
<PhoneNumberFormField
label="Search by Primary Number"
{...queryField("phone_number", "+91")}
value={phoneNumber}
onChange={(e) => setPhoneNumber(e.value)}
types={["mobile", "landline"]}
className="w-full grow"
error={((phoneNumber || "+91") === "+91" && "") || undefined}
/>
<PhoneNumberFormField
label="Search by Emergency Number"
{...queryField("emergency_phone_number", "+91")}
value={emergencyPhoneNumber}
onChange={(e) => setEmergencyPhoneNumber(e.value)}
types={["mobile", "landline"]}
className="w-full"
error={
((emergencyPhoneNumber || "+91") === "+91" && "") || undefined
}
/>
</div>
</div>
</div>

<SearchByMultipleFields
Copy link
Contributor

Choose a reason for hiding this comment

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

Merge error here; SearchByMultipleFields should be included instead of the individual search fields.

id="patient-search"
options={searchOptions}
onSearch={handleSearch}
clearSearch={clearSearch}
className="w-full"
/>
</div>
<div className="col-span-3 flex flex-wrap">
<FilterBadges
Expand Down Expand Up @@ -1125,10 +1156,7 @@ export const PatientManager = () => {
/>
</div>
<div>
<PatientFilter
{...advancedFilter}
key={JSON.stringify(advancedFilter.filter)}
/>
<PatientFilter {...advancedFilter} key={window.location.search} />
<TabPanel value={tabValue} index={0}>
<div className="mb-4">{managePatients}</div>
</TabPanel>
Expand Down
Loading
Loading