Skip to content

Commit

Permalink
Updated discharged patients page (#7744)
Browse files Browse the repository at this point in the history
* updated discharged patients page

* fixed filter badges

* updated filters

* fixed responsiveness and removed geo filters

* changed per page limit

* switched to 12
  • Loading branch information
skks1212 committed May 15, 2024
1 parent c8a1549 commit 245c811
Show file tree
Hide file tree
Showing 3 changed files with 217 additions and 42 deletions.
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 @@ -585,16 +586,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 @@ -613,22 +616,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

0 comments on commit 245c811

Please sign in to comment.