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

Updated discharged patients page #7744

Merged
merged 7 commits into from
May 15, 2024
Merged
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
12 changes: 11 additions & 1 deletion src/CAREUI/misc/PaginatedList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createContext, useContext, useState } from "react";
import { createContext, useContext, useEffect, useState } from "react";
import { PaginatedResponse, QueryRoute } from "../../Utils/request/types";
import useQuery, { QueryOptions } from "../../Utils/request/useQuery";
import ButtonV2, {
Expand Down Expand Up @@ -33,6 +33,9 @@ function useContextualized<TItem>() {
interface Props<TItem> extends QueryOptions<PaginatedResponse<TItem>> {
route: QueryRoute<PaginatedResponse<TItem>>;
perPage?: number;
queryCB?: (
query: ReturnType<typeof useQuery<PaginatedResponse<TItem>>>,
) => void;
children: (
ctx: PaginatedListContext<TItem>,
query: ReturnType<typeof useQuery<PaginatedResponse<TItem>>>,
Expand All @@ -43,6 +46,7 @@ export default function PaginatedList<TItem extends object>({
children,
route,
perPage = DEFAULT_PER_PAGE_LIMIT,
queryCB,
...queryOptions
}: Props<TItem>) {
const [currentPage, setPage] = useState(1);
Expand All @@ -57,6 +61,12 @@ export default function PaginatedList<TItem extends object>({

const items = query.data?.results ?? [];

useEffect(() => {
if (queryCB) {
queryCB(query);
}
}, [query]);

return (
<context.Provider
value={{ ...query, items, perPage, currentPage, setPage }}
Expand Down
184 changes: 172 additions & 12 deletions src/Components/Facility/DischargedPatientsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import PaginatedList from "../../CAREUI/misc/PaginatedList";
import Loading from "../Common/Loading";
import { PatientModel } from "../Patient/models";
import useQuery from "../../Utils/request/useQuery";
import { debounce } from "lodash-es";
import SearchInput from "../Form/SearchInput";
import {
DISCHARGED_PATIENT_SORT_OPTIONS,
Expand All @@ -18,6 +17,13 @@ import { useTranslation } from "react-i18next";
import SwitchTabs from "../Common/components/SwitchTabs";
import SortDropdownMenu from "../Common/SortDropdown";
import useFilters from "../../Common/hooks/useFilters";
import PatientFilter from "../Patient/PatientFilter";
import { AdvancedFilterButton } from "../../CAREUI/interactive/FiltersSlideover";
import CountBlock from "../../CAREUI/display/Count";
import { FieldChangeEvent } from "../Form/FormFields/Utils";
import PhoneNumberFormField from "../Form/FormFields/PhoneNumberFormField";
import { useState } from "react";
import { parseOptionId } from "../../Common/utils";

const DischargedPatientsList = ({
facility_external_id,
Expand All @@ -29,7 +35,66 @@ const DischargedPatientsList = ({
pathParams: { id: facility_external_id },
});

const { qParams, updateQuery, FilterBadges } = useFilters({});
const { qParams, updateQuery, advancedFilter, FilterBadges } = useFilters({
limit: 12,
cacheBlacklist: [
"name",
"patient_no",
"phone_number",
"emergency_phone_number",
],
});

const queryField = <T,>(name: string, defaultValue?: T) => {
return {
name,
value: qParams[name] || defaultValue,
onChange: (e: FieldChangeEvent<T>) => updateQuery({ [e.name]: e.value }),
className: "grow w-full mb-2",
};
};

const [phone_number, setPhoneNumber] = useState("");
const [phoneNumberError, setPhoneNumberError] = useState("");
const [emergency_phone_number, setEmergencyPhoneNumber] = useState("");
const [emergencyPhoneNumberError, setEmergencyPhoneNumberError] =
useState("");
const [count, setCount] = useState(0);

const setPhoneNum = (phone_number: string) => {
setPhoneNumber(phone_number);
if (phone_number.length >= 13) {
setPhoneNumberError("");
updateQuery({ phone_number });
return;
}

if (phone_number === "+91" || phone_number === "") {
setPhoneNumberError("");
qParams.phone_number && updateQuery({ phone_number: null });
return;
}

setPhoneNumberError("Enter a valid number");
};

const setEmergencyPhoneNum = (emergency_phone_number: string) => {
setEmergencyPhoneNumber(emergency_phone_number);
if (emergency_phone_number.length >= 13) {
setEmergencyPhoneNumberError("");
updateQuery({ emergency_phone_number });
return;
}

if (emergency_phone_number === "+91" || emergency_phone_number === "") {
setEmergencyPhoneNumberError("");
qParams.emergency_phone_number &&
updateQuery({ emergency_phone_number: null });
return;
}

setEmergencyPhoneNumberError("Enter a valid number");
};

return (
<Page
Expand All @@ -39,21 +104,17 @@ const DischargedPatientsList = ({
}}
options={
<>
<SearchInput
className="mr-4 w-full max-w-sm"
placeholder="Search by patient name"
name="name"
value={qParams.name}
onChange={debounce((e) => updateQuery({ name: e.value }))}
/>
<div className="flex flex-col gap-4 md:flex-row">
<div className="flex flex-col gap-4 lg:flex-row">
<SwitchTabs
tab1="Live"
tab2="Discharged"
className="mr-4"
onClickTab1={() => navigate("/patients")}
isTab2Active
/>
<AdvancedFilterButton
onClick={() => advancedFilter.setShow(true)}
/>
<SortDropdownMenu
options={DISCHARGED_PATIENT_SORT_OPTIONS}
selected={qParams.ordering}
Expand All @@ -63,16 +124,110 @@ const DischargedPatientsList = ({
</>
}
>
<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">
<CountBlock
text="Discharged Patients"
count={count}
loading={facilityQuery.loading}
icon="l-user-injured"
className="pb-12"
/>
</div>
</div>
<div className="col-span-3 w-full">
<div className="col-span-2 mt-2">
<div className="mt-1 md:flex md:gap-4">
<SearchInput
label="Search by Patient"
placeholder="Enter patient name"
{...queryField("name")}
/>
<SearchInput
label="Search by IP/OP Number"
placeholder="Enter IP/OP Number"
secondary
{...queryField("patient_no")}
/>
</div>
<div className="md:flex md:gap-4">
<PhoneNumberFormField
label="Search by Primary Number"
{...queryField("phone_number", "+91")}
value={phone_number}
onChange={(e) => setPhoneNum(e.value)}
error={phoneNumberError}
types={["mobile", "landline"]}
/>
<PhoneNumberFormField
label="Search by Emergency Number"
{...queryField("emergency_phone_number", "+91")}
value={emergency_phone_number}
onChange={(e) => setEmergencyPhoneNum(e.value)}
error={emergencyPhoneNumberError}
types={["mobile", "landline"]}
/>
</div>
</div>
</div>
</div>
<div className="col-span-3 mt-6 flex flex-wrap">
<FilterBadges badges={({ ordering }) => [ordering()]} />
<FilterBadges
badges={({
badge,
value,
kasp,
phoneNumber,
dateRange,
range,
ordering,
}) => [
phoneNumber("Primary number", "phone_number"),
phoneNumber("Emergency number", "emergency_phone_number"),
badge("Patient name", "name"),
badge("IP/OP number", "patient_no"),
...dateRange("Modified", "modified_date"),
...dateRange("Created", "created_date"),
badge("No. of vaccination doses", "number_of_doses"),
kasp(),
badge("COWIN ID", "covin_id"),
badge("Is Antenatal", "is_antenatal"),
badge("Review Missed", "review_missed"),
badge("Facility Type", "facility_type"),
ordering(),
badge("Disease Status", "disease_status"),
value(
"Respiratory Support",
"ventilator_interface",
qParams.ventilator_interface &&
t(`RESPIRATORY_SUPPORT_${qParams.ventilator_interface}`),
),
value(
"Gender",
"gender",
parseOptionId(GENDER_TYPES, qParams.gender) || "",
),
...range("Age", "age"),
badge("SRF ID", "srf_id"),
badge("Declared Status", "is_declared_positive"),
...dateRange("Result", "date_of_result"),
...dateRange("Declared positive", "date_declared_positive"),
...dateRange("Last vaccinated", "last_vaccinated_date"),
]}
/>
</div>
<PaginatedList
perPage={12}
route={routes.listFacilityDischargedPatients}
pathParams={{ facility_external_id }}
query={{ ordering: "-modified_date", ...qParams }}
queryCB={(query) => {
setCount(query.data?.count || 0);
}}
>
{() => (
<div className="flex flex-col gap-4 py-4 lg:px-4 lg:py-8">
<div className="flex flex-col gap-4">
<PaginatedList.WhenEmpty className="flex w-full justify-center border-b border-gray-200 bg-white p-5 text-center text-2xl font-bold text-gray-500">
<span>{t("discharged_patients_empty")}</span>
</PaginatedList.WhenEmpty>
Expand All @@ -99,6 +254,11 @@ const DischargedPatientsList = ({
</div>
)}
</PaginatedList>
<PatientFilter
{...advancedFilter}
key={window.location.search}
dischargePage
/>
</Page>
);
};
Expand Down
63 changes: 34 additions & 29 deletions src/Components/Patient/PatientFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -379,9 +379,10 @@ export default function PatientFilter(props: any) {
}
/>
</div>
{["StateAdmin", "StateReadOnlyAdmin"].includes(
authUser.user_type,
) && (
{(props.dischargePage ||
["StateAdmin", "StateReadOnlyAdmin"].includes(
authUser.user_type,
)) && (
<div className="w-full flex-none" id="discharge-reason-select">
<FieldLabel className="text-sm">Discharge Reason</FieldLabel>
<SelectMenuV2
Expand Down Expand Up @@ -580,16 +581,18 @@ export default function PatientFilter(props: any) {
className="rounded-md"
>
<div className="space-y-4">
<div>
<FieldLabel className="text-sm">Facility</FieldLabel>
<FacilitySelect
multiple={false}
name="facility"
showAll={false}
selected={filterState.facility_ref}
setSelected={(obj) => setFilterWithRef("facility", obj)}
/>
</div>
{!props.dischargePage && (
<div>
<FieldLabel className="text-sm">Facility</FieldLabel>
<FacilitySelect
multiple={false}
name="facility"
showAll={false}
selected={filterState.facility_ref}
setSelected={(obj) => setFilterWithRef("facility", obj)}
/>
</div>
)}
{filterState.facility && (
<div>
<FieldLabel className="text-sm">Location</FieldLabel>
Expand All @@ -608,22 +611,24 @@ export default function PatientFilter(props: any) {
/>
</div>
)}
<div>
<FieldLabel className="text-sm">Facility type</FieldLabel>
<SelectMenuV2
placeholder="Show all"
options={FACILITY_TYPES}
optionLabel={(o) => o.text}
optionValue={(o) => o.text}
value={filterState.facility_type}
onChange={(v) =>
setFilterState({ ...filterState, facility_type: v })
}
optionIcon={() => (
<CareIcon icon="l-hospital" className="text-lg" />
)}
/>
</div>
{!props.dischargePage && (
<div>
<FieldLabel className="text-sm">Facility type</FieldLabel>
<SelectMenuV2
placeholder="Show all"
options={FACILITY_TYPES}
optionLabel={(o) => o.text}
optionValue={(o) => o.text}
value={filterState.facility_type}
onChange={(v) =>
setFilterState({ ...filterState, facility_type: v })
}
optionIcon={() => (
<CareIcon icon="l-hospital" className="text-lg" />
)}
/>
</div>
)}
<div>
<FieldLabel className="text-sm">LSG Body</FieldLabel>
<div className="">
Expand Down
Loading