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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add location filter for patients #6456

Merged
merged 5 commits into from
Oct 31, 2023
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
5 changes: 5 additions & 0 deletions src/Components/Common/LocationSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import AutocompleteFormField from "../Form/FormFields/Autocomplete";
import AutocompleteMultiSelectFormField from "../Form/FormFields/AutocompleteMultiselect";
interface LocationSelectProps {
name: string;
disabled?: boolean;
margin?: string;
errors: string;
className?: string;
Expand All @@ -26,6 +27,7 @@ export const LocationSelect = (props: LocationSelectProps) => {
errors,
className = "",
facilityId,
disabled = false,
} = props;
const [locations, setLocations] = useState<{ name: string; id: string }[]>(
[]
Expand All @@ -40,6 +42,7 @@ export const LocationSelect = (props: LocationSelectProps) => {
};

useEffect(() => {
if (!facilityId) return;
const params = {
limit: 14,
search_text: query,
Expand All @@ -56,6 +59,7 @@ export const LocationSelect = (props: LocationSelectProps) => {
return props.multiple ? (
<AutocompleteMultiSelectFormField
name={name}
disabled={disabled}
value={selected as unknown as string[]}
options={locations}
onChange={({ value }) => handleValueChange(value as unknown as string[])}
Expand All @@ -72,6 +76,7 @@ export const LocationSelect = (props: LocationSelectProps) => {
) : (
<AutocompleteFormField
name={name}
disabled={disabled}
value={selected as string}
options={locations}
onChange={({ value }) => handleValueChange([value])}
Expand Down
48 changes: 25 additions & 23 deletions src/Components/Form/AutoCompleteAsync.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,29 +100,31 @@ const AutoCompleteAsync = (props: Props) => {
}}
autoComplete="off"
/>
<Combobox.Button className="absolute inset-y-0 right-0 flex items-center pr-2">
<div className="absolute right-0 top-1 mr-2 flex items-center text-lg text-secondary-900">
{hasSelection && !loading && !required && (
<div className="tooltip">
<CareIcon
className="care-l-times-circle mb-[-5px] h-4 w-4 text-gray-800 transition-colors duration-200 ease-in-out hover:text-gray-500"
onClick={(e) => {
e.preventDefault();
onChange(null);
}}
/>
<span className="tooltip-text tooltip-bottom -translate-x-1/2 text-xs">
{t("clear_selection")}
</span>
</div>
)}
{loading ? (
<CareIcon className="care-l-spinner -mb-1.5 animate-spin" />
) : (
<CareIcon className="care-l-angle-down -mb-1.5" />
)}
</div>
</Combobox.Button>
{!disabled && (
<Combobox.Button className="absolute inset-y-0 right-0 flex items-center pr-2">
<div className="absolute right-0 top-1 mr-2 flex items-center text-lg text-secondary-900">
{hasSelection && !loading && !required && (
<div className="tooltip">
<CareIcon
className="care-l-times-circle mb-[-5px] h-4 w-4 text-gray-800 transition-colors duration-200 ease-in-out hover:text-gray-500"
onClick={(e) => {
e.preventDefault();
onChange(null);
}}
/>
<span className="tooltip-text tooltip-bottom -translate-x-1/2 text-xs">
{t("clear_selection")}
</span>
</div>
)}
{loading ? (
<CareIcon className="care-l-spinner -mb-1.5 animate-spin" />
) : (
<CareIcon className="care-l-angle-down -mb-1.5" />
)}
</div>
</Combobox.Button>
)}
</div>
<DropdownTransition>
<Combobox.Options className="cui-dropdown-base absolute top-12 z-10 text-sm">
Expand Down
54 changes: 28 additions & 26 deletions src/Components/Form/FormFields/Autocomplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,32 +160,34 @@ export const Autocomplete = <T, V>(props: AutocompleteProps<T, V>) => {
onBlur={() => value && setQuery("")}
autoComplete="off"
/>
<Combobox.Button className="absolute inset-y-0 right-0 flex items-center pr-2">
<div className="absolute right-0 top-1 mr-2 flex h-full items-center gap-1 pb-2 text-lg text-gray-900">
<span>{value?.icon}</span>

{value && !props.isLoading && !props.required && (
<div className="tooltip" id="clear-button">
<CareIcon
className="care-l-times-circle h-4 w-4 text-gray-800 transition-colors duration-200 ease-in-out hover:text-gray-500"
onClick={(e) => {
e.preventDefault();
props.onChange(undefined);
}}
/>
<span className="tooltip-text tooltip-bottom -translate-x-1/2 text-xs">
{t("clear_selection")}
</span>
</div>
)}

{props.isLoading ? (
<CareIcon className="care-l-spinner animate-spin" />
) : (
<CareIcon className="care-l-angle-down" />
)}
</div>
</Combobox.Button>
{!props.disabled && (
<Combobox.Button className="absolute inset-y-0 right-0 flex items-center pr-2">
<div className="absolute right-0 top-1 mr-2 flex h-full items-center gap-1 pb-2 text-lg text-gray-900">
<span>{value?.icon}</span>

{value && !props.isLoading && !props.required && (
<div className="tooltip" id="clear-button">
<CareIcon
className="care-l-times-circle h-4 w-4 text-gray-800 transition-colors duration-200 ease-in-out hover:text-gray-500"
onClick={(e) => {
e.preventDefault();
props.onChange(undefined);
}}
/>
<span className="tooltip-text tooltip-bottom -translate-x-1/2 text-xs">
{t("clear_selection")}
</span>
</div>
)}

{props.isLoading ? (
<CareIcon className="care-l-spinner animate-spin" />
) : (
<CareIcon className="care-l-angle-down" />
)}
</div>
</Combobox.Button>
)}
</div>

<DropdownTransition>
Expand Down
20 changes: 11 additions & 9 deletions src/Components/Form/FormFields/AutocompleteMultiselect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,17 @@ export const AutocompleteMutliSelect = <T, V>(
onChange={(event) => setQuery(event.target.value.toLowerCase())}
autoComplete="off"
/>
<Combobox.Button className="absolute inset-y-0 right-0 flex items-center pr-2">
<div className="absolute right-0 top-1 mr-2 flex items-center text-lg text-gray-900">
{props.isLoading ? (
<CareIcon className="care-l-spinner animate-spin" />
) : (
<CareIcon className="care-l-angle-down -mb-1.5" />
)}
</div>
</Combobox.Button>
{!props.disabled && (
<Combobox.Button className="absolute inset-y-0 right-0 flex items-center pr-2">
<div className="absolute right-0 top-1 mr-2 flex items-center text-lg text-gray-900">
{props.isLoading ? (
<CareIcon className="care-l-spinner animate-spin" />
) : (
<CareIcon className="care-l-angle-down -mb-1.5" />
)}
</div>
</Combobox.Button>
)}
</div>
{value.length !== 0 && (
<div className="flex flex-wrap gap-2 p-2">
Expand Down
39 changes: 36 additions & 3 deletions src/Components/Patient/ManagePatients.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,14 @@ import {
getAllPatient,
getAnyFacility,
getDistrict,
getFacilityAssetLocation,
getLocalBody,
} from "../../Redux/actions";
import { statusType, useAbortableEffect } from "../../Common/utils";
import {
statusType,
useAbortableEffect,
parseOptionId,
} from "../../Common/utils";

import { AdvancedFilterButton } from "../../CAREUI/interactive/FiltersSlideover";
import ButtonV2 from "../Common/components/ButtonV2";
Expand All @@ -36,7 +41,6 @@ import RecordMeta from "../../CAREUI/display/RecordMeta";
import SearchInput from "../Form/SearchInput";
import SortDropdownMenu from "../Common/SortDropdown";
import SwitchTabs from "../Common/components/SwitchTabs";
import { parseOptionId } from "../../Common/utils";
import { formatAge, parsePhoneNumber } from "../../Utils/utils.js";
import { useDispatch } from "react-redux";
import useFilters from "../../Common/hooks/useFilters";
Expand Down Expand Up @@ -104,6 +108,7 @@ export const PatientManager = () => {
const [districtName, setDistrictName] = useState("");
const [localbodyName, setLocalbodyName] = useState("");
const [facilityBadgeName, setFacilityBadge] = useState("");
const [locationBadgeName, setLocationBadge] = useState("");
const [phone_number, setPhoneNumber] = useState("");
const [phoneNumberError, setPhoneNumberError] = useState("");
const [emergency_phone_number, setEmergencyPhoneNumber] = useState("");
Expand Down Expand Up @@ -199,6 +204,8 @@ export const PatientManager = () => {
qParams.last_consultation_admitted_bed_type_list || undefined,
last_consultation_discharge_reason:
qParams.last_consultation_discharge_reason || undefined,
last_consultation_current_bed__location:
qParams.last_consultation_current_bed__location || undefined,
srf_id: qParams.srf_id || undefined,
number_of_doses: qParams.number_of_doses || undefined,
covin_id: qParams.covin_id || undefined,
Expand Down Expand Up @@ -344,6 +351,7 @@ export const PatientManager = () => {
qParams.age_min,
qParams.last_consultation_admitted_bed_type_list,
qParams.last_consultation_discharge_reason,
qParams.last_consultation_current_bed__location,
qParams.facility,
qParams.facility_type,
qParams.district,
Expand Down Expand Up @@ -443,12 +451,32 @@ export const PatientManager = () => {
[dispatch, qParams.facility]
);

const fetchLocationBadgeName = useCallback(
async (status: statusType) => {
const res =
qParams.last_consultation_current_bed__location &&
(await dispatch(
getFacilityAssetLocation(
qParams.facility,
qParams.last_consultation_current_bed__location
)
));

if (!status.aborted) {
setLocationBadge(res?.data?.name);
}
},
[dispatch, qParams.last_consultation_current_bed__location]
);

useAbortableEffect(
(status: statusType) => {
fetchFacilityBadgeName(status);
fetchLocationBadgeName(status);
},
[fetchFacilityBadgeName]
[fetchFacilityBadgeName, fetchLocationBadgeName]
);

const LastAdmittedToTypeBadges = () => {
const badge = (key: string, value: any, id: string) => {
return (
Expand Down Expand Up @@ -940,6 +968,11 @@ export const PatientManager = () => {
"last_consultation_medico_legal_case"
),
value("Facility", "facility", facilityBadgeName),
value(
"Location",
"last_consultation_current_bed__location",
locationBadgeName
),
badge("Facility Type", "facility_type"),
value("District", "district", districtName),
ordering(),
Expand Down
27 changes: 25 additions & 2 deletions src/Components/Patient/PatientFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import FiltersSlideover from "../../CAREUI/interactive/FiltersSlideover";
import AccordionV2 from "../Common/components/AccordionV2";
import { dateQueryString } from "../../Utils/utils";
import dayjs from "dayjs";
import { LocationSelect } from "../Common/LocationSelect";

const getDate = (value: any) =>
value && dayjs(value).isValid() && dayjs(value).toDate();
Expand Down Expand Up @@ -79,6 +80,8 @@ export default function PatientFilter(props: any) {
filter.last_consultation_admitted_bed_type_list
? filter.last_consultation_admitted_bed_type_list.split(",")
: [],
last_consultation_current_bed__location:
filter.last_consultation_current_bed__location || "",
last_consultation_discharge_reason:
filter.last_consultation_discharge_reason || null,
srf_id: filter.srf_id || null,
Expand Down Expand Up @@ -128,6 +131,7 @@ export default function PatientFilter(props: any) {
last_consultation_discharge_date_before: "",
last_consultation_discharge_date_after: "",
last_consultation_admitted_to_list: [],
last_consultation_current_bed__location: "",
srf_id: "",
number_of_doses: null,
covin_id: "",
Expand Down Expand Up @@ -239,6 +243,7 @@ export default function PatientFilter(props: any) {
last_consultation_discharge_date_after,
last_consultation_admitted_bed_type_list,
last_consultation_discharge_reason,
last_consultation_current_bed__location,
number_of_doses,
covin_id,
srf_id,
Expand All @@ -256,6 +261,8 @@ export default function PatientFilter(props: any) {
district: district || "",
lsgBody: lsgBody || "",
facility: facility || "",
last_consultation_current_bed__location:
last_consultation_current_bed__location || "",
facility_type: facility_type || "",
date_declared_positive_before: dateQueryString(
date_declared_positive_before
Expand Down Expand Up @@ -588,13 +595,29 @@ export default function PatientFilter(props: any) {
<FacilitySelect
multiple={false}
name="facility"
showAll={false}
selected={filterState.facility_ref}
showAll
setSelected={(obj) => setFacility(obj, "facility")}
/>
</div>

<div className="w-full flex-none">
<FieldLabel className="text-sm">Location</FieldLabel>
<LocationSelect
disabled={!filterState.facility}
name="facility"
selected={filterState.last_consultation_current_bed__location}
multiple={false}
errors=""
facilityId={filterState.facility}
setSelected={(selected) =>
setFilterState({
...filterState,
last_consultation_current_bed__location: selected,
})
}
/>
</div>
<div className="-mt-6 w-full flex-none">
<FieldLabel className="text-sm">Facility type</FieldLabel>
<SelectMenuV2
placeholder="Show all"
Expand Down
Loading