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

Added the CSV Export button In Discharged Patients #9142

Closed
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
914bbd9
Reverted all unwanted file chnages and handled errors with notifications
AnveshNalimela Dec 18, 2024
47c65ca
Merge branch 'ohcnetwork:develop' into issue/#8993/discharge-patients…
AnveshNalimela Dec 21, 2024
968a7f8
Merge branch 'ohcnetwork:develop' into issue/#8993/discharge-patients…
AnveshNalimela Dec 23, 2024
ac5d5a4
Merge branch 'develop' into issue/#8993/discharge-patients-export
nihal467 Dec 23, 2024
004776d
Removed some try-catch which realted to data constiency to make more …
AnveshNalimela Dec 23, 2024
25e035d
Merge branch 'issue/#8993/discharge-patients-export' of github.com:An…
AnveshNalimela Dec 23, 2024
23c4578
Chnaged Error to warn
AnveshNalimela Dec 23, 2024
6a5e6f2
Fixed the issue
AnveshNalimela Dec 23, 2024
044352d
Merge branch 'ohcnetwork:develop' into issue/#8993/discharge-patients…
AnveshNalimela Dec 23, 2024
169a0d2
Changed the warn msg to No patients found for export
AnveshNalimela Dec 23, 2024
4edd4cc
Merge branch 'issue/#8993/discharge-patients-export' of github.com:An…
AnveshNalimela Dec 23, 2024
a94ae47
Merge branch 'ohcnetwork:develop' into issue/#8993/discharge-patients…
AnveshNalimela Dec 23, 2024
6ed14f6
passed columns as args and Updated the function accordingly
AnveshNalimela Dec 24, 2024
dbaac65
changed the warn to error notification in case of any error
AnveshNalimela Dec 24, 2024
7c0ef26
Instead of Policy Id merge all columns having duplicates
AnveshNalimela Dec 24, 2024
9c5be7e
minor chnages and fixed all issues
AnveshNalimela Dec 24, 2024
468812f
removed patient ID as default parameter
AnveshNalimela Dec 24, 2024
e1613cb
Merge branch 'develop' into issue/#8993/discharge-patients-export
nihal467 Dec 24, 2024
06f122f
cahnged the calculateDataRange to calculateDaysBetween and changed to…
AnveshNalimela Dec 24, 2024
2980f72
Merge branch 'issue/#8993/discharge-patients-export' of github.com:An…
AnveshNalimela Dec 24, 2024
1e1b20b
Merge branch 'ohcnetwork:develop' into issue/#8993/discharge-patients…
AnveshNalimela Dec 24, 2024
588c7e3
Replaced buttonv2 with button,updated duration logic,dateRangeFields …
AnveshNalimela Dec 24, 2024
e96e46e
Merge branch 'develop' into issue/#8993/discharge-patients-export
AnveshNalimela Dec 26, 2024
843310b
removed >=0 and added translations for export and seven day period
AnveshNalimela Dec 26, 2024
6bf200b
Replaced with useQuery
AnveshNalimela Dec 26, 2024
0695dbb
Removed console logs
AnveshNalimela Dec 26, 2024
a1b68fc
simplified the useQuery implemnenation
AnveshNalimela Dec 26, 2024
ff2fab8
Added usePatientExport.ts
AnveshNalimela Dec 26, 2024
acfa579
Removed redudant logic in isExportAllowed
AnveshNalimela Dec 26, 2024
d4aad28
Merge branch 'ohcnetwork:develop' into issue/#8993/discharge-patients…
AnveshNalimela Dec 26, 2024
c435620
Merge branch 'ohcnetwork:develop' into issue/#8993/discharge-patients…
AnveshNalimela Dec 27, 2024
aa04ffe
Replaced all usetanstackqueryinstaed with useQuery
AnveshNalimela Dec 27, 2024
d40de85
Merge branch 'ohcnetwork:develop' into issue/#8993/discharge-patients…
AnveshNalimela Dec 28, 2024
a0af152
Merge branch 'ohcnetwork:develop' into issue/#8993/discharge-patients…
AnveshNalimela Dec 29, 2024
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
2 changes: 2 additions & 0 deletions public/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,7 @@
"expired": "Expired",
"expired_on": "Expired On",
"expires_on": "Expires On",
"export": "Export",
"facilities": "Facilities",
"facility": "Facility",
"facility_consent_requests_page_title": "Patient Consent List",
Expand Down Expand Up @@ -1327,6 +1328,7 @@
"select_local_body": "Select Local Body",
"select_policy": "Select an Insurance Policy",
"select_policy_to_add_items": "Select a Policy to Add Items",
"select_seven_day_period": "Please select a seven day period.",
"select_skills": "Select and add some skills",
"select_wards": "Select wards",
"send": "Send",
Expand Down
41 changes: 41 additions & 0 deletions src/Utils/csvUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
export const csvGroupByColumn = (
data: string,
groupByColumn: string,
delimiter = ";",
): string => {
AnveshNalimela marked this conversation as resolved.
Show resolved Hide resolved
const [header, ...datalines] = data.trim().split("\n");
const headerColumns = header.split(",");
const groupByColumnIndex = headerColumns.indexOf(groupByColumn);

const groupedData = datalines.reduce(
(groupMap, line) => {
const columns = line.split(",");
const groupByKey = columns[groupByColumnIndex]?.trim();

if (!groupMap[groupByKey]) {
groupMap[groupByKey] = [];
}
groupMap[groupByKey].push(columns);
return groupMap;
},
{} as Record<string, string[][]>,
);
AnveshNalimela marked this conversation as resolved.
Show resolved Hide resolved

const mergedLines = Object.values(groupedData).map((group) => {
if (!group.length) return "";

const mergedRow = [...group[0]];
headerColumns.forEach((column) => {
const index = headerColumns.indexOf(column);
const mergedValue = group
.map((columns) => columns[index]?.trim() || "")
.filter(Boolean)
.join(delimiter);

mergedRow[index] = mergedValue;
});
return mergedRow.join(",");
});

return header.concat(mergedLines.join("\n"));
};
11 changes: 11 additions & 0 deletions src/Utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -571,3 +571,14 @@ export const copyToClipboard = async (content: string) => {
Notification.Error({ msg: "Copying is not allowed" });
}
};

export const calculateDaysBetween = (
startDate: string,
endDate: string,
): number => {
if (!startDate && !endDate) return 0;
if (startDate && endDate) {
return Math.abs(dayjs(endDate).diff(dayjs(startDate), "days"));
}
return -1; // Invalid range when only one date is set
};
182 changes: 181 additions & 1 deletion src/components/Facility/DischargedPatientsList.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useQuery } from "@tanstack/react-query";
import { Link, navigate } from "raviger";
import { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
Expand All @@ -9,6 +10,9 @@ import CareIcon from "@/CAREUI/icons/CareIcon";
import { AdvancedFilterButton } from "@/CAREUI/interactive/FiltersSlideover";
import PaginatedList from "@/CAREUI/misc/PaginatedList";

import { Button } from "@/components/ui/button";

import ExportMenu from "@/components/Common/Export";
import Loading from "@/components/Common/Loading";
import Page from "@/components/Common/Page";
import SearchByMultipleFields from "@/components/Common/SearchByMultipleFields";
Expand Down Expand Up @@ -36,9 +40,17 @@ import {
} from "@/common/constants";
import { parseOptionId } from "@/common/utils";

import * as Notification from "@/Utils/Notifications";
import { csvGroupByColumn } from "@/Utils/csvUtils";
import routes from "@/Utils/request/api";
import query from "@/Utils/request/query";
import useTanStackQueryInstead from "@/Utils/request/useQuery";
import { formatPatientAge, humanizeStrings } from "@/Utils/utils";
import {
calculateDaysBetween,
formatPatientAge,
humanizeStrings,
parsePhoneNumber,
} from "@/Utils/utils";

const DischargedPatientsList = ({
facility_external_id,
Expand All @@ -55,6 +67,7 @@ const DischargedPatientsList = ({
updateQuery,
advancedFilter,
FilterBadges,
resultsPerPage,
updatePage,
clearSearch,
} = useFilters({
Expand Down Expand Up @@ -124,6 +137,71 @@ const DischargedPatientsList = ({
[updateQuery],
);

const params = {
page: qParams.page || 1,
limit: resultsPerPage,
name: qParams.name || undefined,
patient_no: qParams.patient_no || undefined,
phone_number: qParams.phone_number
? parsePhoneNumber(qParams.phone_number)
: undefined,
emergency_phone_number: qParams.emergency_phone_number
? parsePhoneNumber(qParams.emergency_phone_number)
: undefined,
offset: (qParams.page ? qParams.page - 1 : 0) * resultsPerPage,
ordering: qParams.ordering || undefined,

gender: qParams.gender || undefined,
category: qParams.category || undefined,
age_min: qParams.age_min || undefined,
age_max: qParams.age_max || undefined,
last_consultation_admitted_bed_type_list:
qParams.last_consultation_admitted_bed_type_list || undefined,
last_consultation__consent_types:
qParams.last_consultation__consent_types || undefined,
last_consultation__new_discharge_reason:
qParams.last_consultation__new_discharge_reason || undefined,
last_consultation_is_telemedicine:
qParams.last_consultation_is_telemedicine || undefined,
ventilator_interface: qParams.ventilator_interface || undefined,
last_consultation_medico_legal_case:
qParams.last_consultation_medico_legal_case || undefined,
ration_card_category: qParams.ration_card_category || undefined,

diagnoses: qParams.diagnoses || undefined,
diagnoses_confirmed: qParams.diagnoses_confirmed || undefined,
diagnoses_provisional: qParams.diagnoses_provisional || undefined,
diagnoses_unconfirmed: qParams.diagnoses_unconfirmed || undefined,
diagnoses_differential: qParams.diagnoses_differential || undefined,

created_date_before: qParams.created_date_before || undefined,
created_date_after: qParams.created_date_after || undefined,
modified_date_before: qParams.modified_date_before || undefined,
modified_date_after: qParams.modified_date_after || undefined,
last_consultation_encounter_date_before:
qParams.last_consultation_encounter_date_before || undefined,
last_consultation_encounter_date_after:
qParams.last_consultation_encounter_date_after || undefined,
last_consultation_discharge_date_before:
qParams.last_consultation_discharge_date_before || undefined,
last_consultation_discharge_date_after:
qParams.last_consultation_discharge_date_after || undefined,

local_body: qParams.lsgBody || undefined,
district: qParams.district || undefined,

number_of_doses: qParams.number_of_doses || undefined,
is_declared_positive: qParams.is_declared_positive || undefined,
covin_id: qParams.covin_id || undefined,
date_declared_positive_before:
qParams.date_declared_positive_before || undefined,
date_declared_positive_after:
qParams.date_declared_positive_after || undefined,
last_vaccinated_date_before:
qParams.last_vaccinated_date_before || undefined,
last_vaccinated_date_after: qParams.last_vaccinated_date_after || undefined,
};

useEffect(() => {
if (!qParams.phone_number && phone_number.length >= 13) {
setPhoneNumber("+91");
Expand All @@ -136,6 +214,44 @@ const DischargedPatientsList = ({
}
}, [qParams]);

const dateRangeFields = [
[params.created_date_before, params.created_date_after],
[params.modified_date_before, params.modified_date_after],
[params.date_declared_positive_before, params.date_declared_positive_after],
[params.last_vaccinated_date_before, params.last_vaccinated_date_after],
[
params.last_consultation_encounter_date_before,
params.last_consultation_encounter_date_after,
],
[
params.last_consultation_discharge_date_before,
params.last_consultation_discharge_date_after,
],
];

const isExportAllowed = dateRangeFields.some(([startDate, endDate]) => {
const days = calculateDaysBetween(startDate, endDate);
return days > 0 && days <= 7 && days !== 0;
});

const queryParams = {
...params,
csv: true,
};
const pathParams = { facility_external_id };

AnveshNalimela marked this conversation as resolved.
Show resolved Hide resolved
const { refetch: exportAsCSV } = useQuery({
queryKey: ["Discharged Patients", queryParams],
queryFn: async () => {
const data = await query(routes.listFacilityDischargedPatients, {
queryParams,
pathParams,
});
return data;
},
enabled: false,
});
AnveshNalimela marked this conversation as resolved.
Show resolved Hide resolved

const { data: districtData } = useTanStackQueryInstead(routes.getDistrict, {
AnveshNalimela marked this conversation as resolved.
Show resolved Hide resolved
pathParams: {
id: qParams.district,
Expand Down Expand Up @@ -293,6 +409,70 @@ const DischargedPatientsList = ({
selected={qParams.ordering}
onSelect={(e) => updateQuery({ ordering: e.ordering })}
/>
<div className="tooltip w-full md:w-auto" id="patient-export">
{!isExportAllowed ? (
<Button
variant="primary"
size="lg"
onClick={() => {
advancedFilter.setShow(true);
setTimeout(() => {
const element =
document.getElementById("bed-type-select");
if (element)
element.scrollIntoView({ behavior: "smooth" });
Notification.Warn({
msg: t("select_seven_day_period"),
});
}, 500);
}}
className="mr-5 w-full lg:w-fit"
>
<CareIcon icon="l-export" className="mr-2" />
<span className="lg:my-[3px]">{t("export")}</span>
</Button>
) : (
<ExportMenu
disabled={!isExportAllowed}
exportItems={[
{
label: "Export Discharged patients",
action: async () => {
const result = await exportAsCSV();
if (result.isError || !result.data) {
return null;
}
const data = await result.data({
signal: new AbortController().signal,
});
console.log(data);

return data || null;
AnveshNalimela marked this conversation as resolved.
Show resolved Hide resolved
},

parse: (data) => {
try {
return csvGroupByColumn(data, "Patient ID");
} catch (e) {
if (e instanceof Error) {
Notification.Error({
msg: e.message,
});
}
return "";
}
},
},
]}
/>
)}

{!isExportAllowed && (
<span className="tooltip-text tooltip-bottom -translate-x-1/2">
{t("select_seven_day_period")}
</span>
)}
</div>
</div>
</>
}
Expand Down
Loading
Loading