diff --git a/src/Components/Patient/models.tsx b/src/Components/Patient/models.tsx
index d62a66dbfc..0ce23f68c2 100644
--- a/src/Components/Patient/models.tsx
+++ b/src/Components/Patient/models.tsx
@@ -49,7 +49,6 @@ export interface PatientModel {
id?: string;
action?: number;
name?: string;
- age?: number;
allow_transfer?: boolean;
discharge?: boolean;
gender?: number;
@@ -113,6 +112,8 @@ export interface PatientModel {
number_of_doses?: number;
last_vaccinated_date?: string;
date_of_birth?: string;
+ year_of_birth?: number;
+ readonly death_datetime?: string;
blood_group?: string;
review_interval?: number;
review_time?: string;
diff --git a/src/Components/Shifting/ListView.tsx b/src/Components/Shifting/ListView.tsx
index e1f0a0545e..5ad0dfa8b3 100644
--- a/src/Components/Shifting/ListView.tsx
+++ b/src/Components/Shifting/ListView.tsx
@@ -8,7 +8,7 @@ import { ExportButton } from "../Common/Export";
import ListFilter from "./ListFilter";
import Page from "../Common/components/Page";
import SearchInput from "../Form/SearchInput";
-import { formatAge, formatDateTime } from "../../Utils/utils";
+import { formatDateTime, formatPatientAge } from "../../Utils/utils";
import { formatFilter } from "./Commons";
import { navigate } from "raviger";
@@ -90,11 +90,7 @@ export default function ListView() {
{shift.patient_object.name} -{" "}
- {formatAge(
- shift.patient_object.age,
- shift.patient_object.date_of_birth,
- true
- )}
+ {formatPatientAge(shift.patient_object, true)}
{shift.emergency && (
diff --git a/src/Components/Shifting/ShiftDetails.tsx b/src/Components/Shifting/ShiftDetails.tsx
index acc3565487..c3f42456f6 100644
--- a/src/Components/Shifting/ShiftDetails.tsx
+++ b/src/Components/Shifting/ShiftDetails.tsx
@@ -15,7 +15,7 @@ import { CopyToClipboard } from "react-copy-to-clipboard";
import Page from "../Common/components/Page";
import QRCode from "qrcode.react";
import RecordMeta from "../../CAREUI/display/RecordMeta";
-import { formatAge, formatDateTime } from "../../Utils/utils";
+import { formatDateTime, formatPatientAge } from "../../Utils/utils";
import useConfig from "../../Common/hooks/useConfig";
import { useTranslation } from "react-i18next";
@@ -24,6 +24,7 @@ import routes from "../../Redux/api.js";
import request from "../../Utils/request/request.js";
import { ConsultationModel } from "../Facility/models.js";
import CareIcon from "../../CAREUI/icons/CareIcon.js";
+import { PatientModel } from "../Patient/models.js";
const Loading = lazy(() => import("../Common/Loading"));
@@ -94,13 +95,9 @@ export default function ShiftDetails(props: { id: string }) {
"\n" +
t("age") +
":" +
- +(
- formatAge(
- data?.patient_object?.age,
- data?.patient_object?.date_of_birth,
- true
- ) ?? "-"
- ) +
+ +(data?.patient_object
+ ? formatPatientAge(data.patient_object, true)
+ : "") +
"\n" +
t("origin_facility") +
":" +
@@ -128,7 +125,7 @@ export default function ShiftDetails(props: { id: string }) {
setIsCopied(false);
}, 5000);
- const showPatientCard = (patientData: any) => {
+ const showPatientCard = (patientData: PatientModel) => {
const patientGender = GENDER_TYPES.find(
(i) => i.id === patientData?.gender
)?.text;
@@ -185,7 +182,7 @@ export default function ShiftDetails(props: { id: string }) {
{t("age")}:{" "}
- {formatAge(patientData?.age, patientData?.date_of_birth, true)}
+ {patientData ? formatPatientAge(patientData, true) : ""}
)}
{patientData?.gender === 2 && patientData?.is_antenatal && (
@@ -370,7 +367,7 @@ export default function ShiftDetails(props: { id: string }) {
{t("age")}:{" "}
- {formatAge(patientData.age, patientData.date_of_birth, true)}
+ {patientData ? formatPatientAge(patientData, true) : ""}
@@ -794,7 +791,7 @@ export default function ShiftDetails(props: { id: string }) {
{t("details_of_patient")} {showCopyToclipBoard(data)}
- {showPatientCard(data?.patient_object)}
+ {data?.patient_object && showPatientCard(data?.patient_object)}
{t("comments")}
diff --git a/src/Components/Shifting/ShiftingBoard.tsx b/src/Components/Shifting/ShiftingBoard.tsx
index ae94514e6e..e07fb5d96e 100644
--- a/src/Components/Shifting/ShiftingBoard.tsx
+++ b/src/Components/Shifting/ShiftingBoard.tsx
@@ -6,7 +6,11 @@ import {
useRef,
useState,
} from "react";
-import { classNames, formatAge, formatDateTime } from "../../Utils/utils";
+import {
+ classNames,
+ formatDateTime,
+ formatPatientAge,
+} from "../../Utils/utils";
import { downloadShiftRequests } from "../../Redux/actions";
import { useDrag, useDrop } from "react-dnd";
@@ -88,11 +92,7 @@ const ShiftCard = ({ shift, filter }: any) => {
{shift.patient_object.name} -{" "}
- {formatAge(
- shift.patient_object?.age,
- shift.patient_object?.age.date_of_birth,
- true
- )}
+ {formatPatientAge(shift.patient_object, true)}
{shift.emergency && (
diff --git a/src/Components/VitalsMonitor/VitalsMonitorHeader.tsx b/src/Components/VitalsMonitor/VitalsMonitorHeader.tsx
index 8fa272d405..c3b2888c2f 100644
--- a/src/Components/VitalsMonitor/VitalsMonitorHeader.tsx
+++ b/src/Components/VitalsMonitor/VitalsMonitorHeader.tsx
@@ -2,6 +2,7 @@ import { PatientAssetBed } from "../Assets/AssetTypes";
import { Link } from "raviger";
import CareIcon from "../../CAREUI/icons/CareIcon";
import { GENDER_TYPES } from "../../Common/constants";
+import { formatPatientAge } from "../../Utils/utils";
interface VitalsMonitorHeaderProps {
patientAssetBed?: PatientAssetBed;
@@ -27,7 +28,7 @@ const VitalsMonitorHeader = ({ patientAssetBed }: VitalsMonitorHeaderProps) => {
)}
{patient && (
- {patient.age}y;{" "}
+ {`${formatPatientAge(patient)}; `}
{GENDER_TYPES.find((g) => g.id === patient.gender)?.icon}
)}
diff --git a/src/Utils/utils.ts b/src/Utils/utils.ts
index 4bbc6317d2..0d350267d1 100644
--- a/src/Utils/utils.ts
+++ b/src/Utils/utils.ts
@@ -6,6 +6,7 @@ import {
import phoneCodesJson from "../Common/static/countryPhoneAndFlags.json";
import dayjs from "./dayjs";
import { UserModel } from "../Components/Users/models";
+import { PatientModel } from "../Components/Patient/models";
interface ApacheParams {
age: number;
@@ -396,31 +397,46 @@ export const getCountryCode = (phoneNumber: string) => {
return undefined;
};
-export const formatAge = (
- age?: number,
- date_of_birth?: string,
- abbreviated = false
-) => {
- if (!age && !date_of_birth) return undefined;
- if (!age) age = 0;
-
- const daySuffix = abbreviated ? "d" : "days";
- const monthSuffix = abbreviated ? "mo" : "months";
- const yearSuffix = abbreviated ? "yr" : "years";
-
- if (age < 1 && date_of_birth) {
- const dob = new Date(date_of_birth);
- const today = new Date();
- const diffTime = Math.abs(today.getTime() - dob.getTime());
- const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
- const months = Math.floor(diffDays / 30);
- const days = diffDays % 30;
- if (months === 0) {
- return `${days} ${daySuffix}`;
- }
- return `${months} ${monthSuffix} ${days} ${daySuffix}`;
+const getRelativeDateSuffix = (abbreviated: boolean) => {
+ return {
+ day: abbreviated ? "d" : "days",
+ month: abbreviated ? "mo" : "months",
+ year: abbreviated ? "yr" : "years",
+ };
+};
+
+export const formatPatientAge = (obj: PatientModel, abbreviated = false) => {
+ const suffixes = getRelativeDateSuffix(abbreviated);
+
+ const start = dayjs(
+ obj.date_of_birth
+ ? new Date(obj.date_of_birth)
+ : new Date(obj.year_of_birth!, 0, 1)
+ );
+
+ const end = dayjs(
+ obj.death_datetime ? new Date(obj.death_datetime) : new Date()
+ );
+
+ const years = end.diff(start, "years");
+ if (years) {
+ return `${years}${suffixes.year}`;
+ }
+
+ // Skip representing as no. of months/days if we don't know the date of birth
+ // since it would anyways be inaccurate.
+ if (!obj.date_of_birth) {
+ return abbreviated
+ ? `Born ${obj.year_of_birth}`
+ : `Born on ${obj.year_of_birth}`;
+ }
+
+ const month = end.diff(start, "month");
+ const day = end.diff(start.add(month, "month"), "day");
+ if (month) {
+ return `${month}${suffixes.month} ${day}${suffixes.day}`;
}
- return `${age} ${yearSuffix}`;
+ return `${day}${suffixes.day}`;
};
export const scrollTo = (id: string | boolean) => {