diff --git a/src/Components/Facility/ConsultationDetails/ConsultationNursingTab.tsx b/src/Components/Facility/ConsultationDetails/ConsultationNursingTab.tsx index 63e3330bffd..0a8ee625ba6 100644 --- a/src/Components/Facility/ConsultationDetails/ConsultationNursingTab.tsx +++ b/src/Components/Facility/ConsultationDetails/ConsultationNursingTab.tsx @@ -1,41 +1,24 @@ import { useEffect, useState } from "react"; -import { ConsultationTabProps } from "./index"; -import { NursingPlot } from "../Consultations/NursingPlot"; import { useTranslation } from "react-i18next"; import request from "../../../Utils/request/request"; import routes from "../../../Redux/api"; -import { RoutineAnalysisRes, RoutineFields } from "../models"; +import { + RoutineAnalysisRes, + RoutineFields, + NursingPlotFields, +} from "../models"; import Loading from "../../Common/Loading"; -import { classNames, formatDate, formatTime } from "../../../Utils/utils"; import Pagination from "../../Common/Pagination"; -import { PAGINATION_LIMIT } from "../../../Common/constants"; +import { + PAGINATION_LIMIT, + NURSING_CARE_PROCEDURES, +} from "../../../Common/constants"; +import LogUpdateAnalayseTable from "../Consultations/LogUpdateAnalayseTable"; +import { formatDateTime } from "../../../Utils/utils"; import PageTitle from "@/Components/Common/PageTitle"; - -export default function ConsultationNursingTab(props: ConsultationTabProps) { - const { t } = useTranslation(); - return ( -
- -
-

{t("routine")}

- -
-
-

{t("nursing_care")}

- -
-
- ); -} +import { ConsultationTabProps } from "."; +import { ProcedureType } from "@/Components/Common/prescription-builder/ProcedureBuilder"; const REVERSE_CHOICES = { appetite: { @@ -109,6 +92,105 @@ const ROUTINE_ROWS = [ { subField: true, field: "appetite" } as const, ]; +const NursingPlot = ({ consultationId }: ConsultationTabProps) => { + const { t } = useTranslation(); + const [results, setResults] = useState({}); + const [currentPage, setCurrentPage] = useState(1); + const [totalCount, setTotalCount] = useState(0); + + useEffect(() => { + const fetchDailyRounds = async ( + currentPage: number, + consultationId: string, + ) => { + const { res, data } = await request(routes.dailyRoundsAnalyse, { + body: { page: currentPage, fields: NursingPlotFields }, + pathParams: { consultationId }, + }); + if (res && res.ok && data) { + setResults(data.results); + setTotalCount(data.count); + } + }; + + fetchDailyRounds(currentPage, consultationId); + }, [consultationId, currentPage]); + + const handlePagination = (page: number) => setCurrentPage(page); + + const data = Object.entries(results).map((key: any) => ({ + date: formatDateTime(key[0]), + nursing: key[1]["nursing"], + })); + + const dataToDisplay = data + .map((x) => + x.nursing.map((f: any) => { + f["date"] = x.date; + return f; + }), + ) + .reduce((accumulator, value) => accumulator.concat(value), []); + + const filterEmpty = (field: (typeof NURSING_CARE_PROCEDURES)[number]) => { + const filtered = dataToDisplay.filter( + (i: ProcedureType) => i.procedure === field, + ); + return filtered.length > 0; + }; + + const areFieldsEmpty = () => { + let emptyFieldCount = 0; + for (const field of NURSING_CARE_PROCEDURES) { + if (!filterEmpty(field)) emptyFieldCount++; + } + return emptyFieldCount === NURSING_CARE_PROCEDURES.length; + }; + + const rows = NURSING_CARE_PROCEDURES.filter((f) => filterEmpty(f)).map( + (procedure) => ({ + field: procedure, + title: t(`NURSING_CARE_PROCEDURE__${procedure}`), + }), + ); + + const mappedData = dataToDisplay.reduce( + (acc: Record, item: any) => { + if (!acc[item.date]) acc[item.date] = {}; + acc[item.date][item.procedure] = item.description; + return acc; + }, + {}, + ); + + return ( +
+
+ {areFieldsEmpty() ? ( +
+
+ {t("no_data_found")} +
+
+ ) : ( + + )} +
+ + {totalCount > PAGINATION_LIMIT && !areFieldsEmpty() && ( +
+ +
+ )} +
+ ); +}; + const RoutineSection = ({ consultationId }: ConsultationTabProps) => { const { t } = useTranslation(); const [page, setPage] = useState(1); @@ -153,65 +235,11 @@ const RoutineSection = ({ consultationId }: ConsultationTabProps) => { return (
-
- - - - - ))} - - - - {ROUTINE_ROWS.map((row) => ( - - - {row.field && - Object.values(results).map((obj, idx) => ( - - ))} - - ))} - -
- {Object.keys(results).map((date) => ( - -

{formatDate(date)}

-

{formatTime(date)}

-
- {row.title ?? t(`LOG_UPDATE_FIELD_LABEL__${row.field!}`)} - - {(() => { - const value = obj[row.field]; - if (value == null) { - return "-"; - } - if (typeof value === "boolean") { - return t(value ? "yes" : "no"); - } - const choices = REVERSE_CHOICES[row.field]; - const choice = `${row.field.toUpperCase()}__${choices[value as keyof typeof choices]}`; - return t(choice); - })()} -
-
+ {totalCount != null && totalCount > PAGINATION_LIMIT && (
@@ -226,3 +254,24 @@ const RoutineSection = ({ consultationId }: ConsultationTabProps) => {
); }; + +export default function ConsultationNursingTab(props: ConsultationTabProps) { + const { t } = useTranslation(); + return ( +
+ +
+

{t("routine")}

+ +
+
+

{t("nursing_care")}

+ +
+
+ ); +} diff --git a/src/Components/Facility/Consultations/LogUpdateAnalayseTable.tsx b/src/Components/Facility/Consultations/LogUpdateAnalayseTable.tsx new file mode 100644 index 00000000000..6a8708d14b6 --- /dev/null +++ b/src/Components/Facility/Consultations/LogUpdateAnalayseTable.tsx @@ -0,0 +1,127 @@ +import React from "react"; +import { formatDate, formatTime } from "../../../Utils/utils"; +import { classNames } from "../../../Utils/utils"; +import { useTranslation } from "react-i18next"; + +interface SharedSectionTableProps { + data: Record; + rows: Array<{ title?: string; field?: string; subField?: boolean }>; + choices?: Record>; +} + +const LogUpdateAnalayseTable: React.FC = ({ + data, + rows, + choices = {}, +}) => { + const { t } = useTranslation(); + + // Helper function to get the display value + const getDisplayValue = ( + value: string | boolean | null | undefined, + field?: string, + ): string => { + if (value == null) { + return " "; + } + + if (typeof value === "boolean") { + return t(value ? "yes" : "no"); + } + if (field && choices[field]) { + const choice = + choices[field][value as keyof (typeof choices)[typeof field]]; + return choice ? t(`${field.toUpperCase()}__${choice}`) : "-"; + } + if (value && typeof value == "string") return value; + + return "-"; + }; + + const isValidDate = (str: string) => { + let ct = 0; + for (let i = 0; i < str.length; i++) { + if (str[i] == "/") ct++; + } + + if (ct == 2) return true; + return false; + }; + + const dateConversion = (str: string) => { + const time = str.split(";")[0].trim(); + + const date = str.split(";")[1].trim(); + + const dd = date.split("/")[0]; + const mm = date.split("/")[1]; + + const yyyy = date.split("/")[2]; + + return time + ";" + mm + "/" + dd + "/" + yyyy; + }; + + return ( +
+ + + + + {Object.keys(data).map((date) => ( + <> + + + ))} + + + + {rows.map((row) => ( + + + {Object.values(data).map((obj, idx) => { + const value = obj[row.field!]; + return ( + + ); + })} + + ))} + +
+ {/* DD/MM/YYYY -> MM/DD/YYYY */} +

+ {isValidDate(date) + ? formatDate(dateConversion(date)) + : formatDate(date)} +

+

+ {isValidDate(date) + ? formatTime(dateConversion(date)) + : formatTime(date)} +

+
+ {row.title ?? t(`LOG_UPDATE_FIELD_LABEL__${row.field!}`)} + + {getDisplayValue(value, row.field)} +
+
+ ); +}; + +export default LogUpdateAnalayseTable; diff --git a/src/Components/Facility/Consultations/NursingPlot.tsx b/src/Components/Facility/Consultations/NursingPlot.tsx deleted file mode 100644 index c747ec60d26..00000000000 --- a/src/Components/Facility/Consultations/NursingPlot.tsx +++ /dev/null @@ -1,133 +0,0 @@ -import { useEffect, useState } from "react"; -import routes from "../../../Redux/api"; -import request from "../../../Utils/request/request"; -import { - NURSING_CARE_PROCEDURES, - PAGINATION_LIMIT, -} from "../../../Common/constants"; - -import Pagination from "../../Common/Pagination"; -import { formatDateTime } from "../../../Utils/utils"; -import { useTranslation } from "react-i18next"; -import { NursingPlotFields } from "../models"; - -export const NursingPlot = ({ consultationId }: any) => { - const { t } = useTranslation(); - const [results, setResults] = useState({}); - const [currentPage, setCurrentPage] = useState(1); - const [totalCount, setTotalCount] = useState(0); - - useEffect(() => { - const fetchDailyRounds = async ( - currentPage: number, - consultationId: string, - ) => { - const { res, data } = await request(routes.dailyRoundsAnalyse, { - body: { page: currentPage, fields: NursingPlotFields }, - pathParams: { - consultationId, - }, - }); - if (res && res.ok && data) { - setResults(data.results); - setTotalCount(data.count); - } - }; - - fetchDailyRounds(currentPage, consultationId); - }, [consultationId, currentPage]); - - const handlePagination = (page: number) => { - setCurrentPage(page); - }; - - const data = Object.entries(results).map((key: any) => { - return { - date: formatDateTime(key[0]), - nursing: key[1]["nursing"], - }; - }); - - const dataToDisplay = data - .map((x) => - x.nursing.map((f: any) => { - f["date"] = x.date; - return f; - }), - ) - .reduce((accumulator, value) => accumulator.concat(value), []); - - const filterEmpty = (field: (typeof NURSING_CARE_PROCEDURES)[number]) => { - const filtered = dataToDisplay.filter((i: any) => i.procedure === field); - return filtered.length > 0; - }; - - const areFieldsEmpty = () => { - let emptyFieldCount = 0; - for (const field of NURSING_CARE_PROCEDURES) { - if (!filterEmpty(field)) emptyFieldCount++; - } - if (emptyFieldCount === NURSING_CARE_PROCEDURES.length) return true; - else return false; - }; - - return ( -
-
-
-
- {areFieldsEmpty() && ( -
-
- {t("no_data_found")} -
-
- )} - {NURSING_CARE_PROCEDURES.map( - (f) => - filterEmpty(f) && ( -
-
-
-

- {t(`NURSING_CARE_PROCEDURE__${f}`)} -

-
-
-
- {dataToDisplay - .filter((i: any) => i.procedure === f) - .map((care: any, index: number) => ( -
-
- {care.date} -
-
- {care.description} -
-
- ))} -
-
- ), - )} -
-
-
- - {!areFieldsEmpty() && totalCount > PAGINATION_LIMIT && ( -
- -
- )} -
- ); -};