-
+
{
variant="h7"
sx={{
fontWeight:
- selectedDate.healthDataId === item.healthDataId
+ selectedDate?.healthDataId === item.healthDataId
? 400
: 0,
}}
diff --git a/client/src/routes/merchant/PatientDetails.js b/client/src/routes/merchant/PatientDetails.js
index 4eb54050..68936e77 100644
--- a/client/src/routes/merchant/PatientDetails.js
+++ b/client/src/routes/merchant/PatientDetails.js
@@ -1,15 +1,16 @@
import {
Box,
- Typography,
+ Button,
Card,
CardContent,
- Button,
- useTheme,
+ Divider,
+ Typography,
useMediaQuery,
+ useTheme,
} from "@mui/material";
-import { useState, useEffect } from "react";
-import { useNavigate, useParams } from "react-router-dom";
import { BarChart } from "@mui/x-charts/BarChart";
+import { useEffect, useState } from "react";
+import { useNavigate, useParams } from "react-router-dom";
// AppBar height: 56px toolbar + 2px border on mobile (xs), 64px + 2px on desktop (sm+)
const APPBAR_HEIGHT = { xs: "58px", sm: "66px" };
@@ -44,7 +45,7 @@ const PatientDetails = () => {
.then((data) => {
setPatientData(data);
});
- }, []);
+ }, [API_BASE, patientID, navigate]);
const chartData = (patientData?.risks?.dates ?? [])
.map((date, i) => ({
@@ -81,7 +82,7 @@ const PatientDetails = () => {
>
{
>
Patient Details
-
+
-
+
Given Name:
-
- {" " + patientData?.patientInfo?.givenNames}
+ {" "}
+ {patientData?.patientInfo?.givenNames}
-
+
Last Name:
-
- {" " + patientData?.patientInfo?.familyName}
+ {" "}
+ {patientData?.patientInfo?.familyName}
-
+
Date Of Birth:
-
- {" " + patientData?.patientInfo?.dateOfBirth}
+ {" "}
+ {patientData?.patientInfo?.dateOfBirth}
-
+
Age:
-
- {" " + patientData?.patientInfo?.age}
+ {" "}
+ {patientData?.patientInfo?.age}
-
+
Gender:
{" "}
- {patientData?.patientInfo?.gender == 1 ? "Male" : "Female"}
+ {patientData?.patientInfo?.gender === 1 ? "Male" : "Female"}
-
+
+
Weight:
-
- {" " + patientData?.patientInfo?.weight} kg
+ {" "}
+ {patientData?.patientInfo?.weight} kg
-
+
+
Height:
-
- {" " + patientData?.patientInfo?.height} cm
+ {" "}
+ {patientData?.patientInfo?.height} cm
-
-
- It has been {patientData?.days} days since{" "}
- {patientData?.patientInfo?.givenNames}'s last health report
-
+
+
+
+ It has been {patientData?.days} days since{" "}
+ {patientData?.patientInfo?.givenNames}'s last health report
+
-
+
+
@@ -206,7 +213,7 @@ const PatientDetails = () => {
sx={{
display: "flex",
gap: { xs: 1, sm: 2 },
- flexDirection: "row",
+ flexDirection: isMobile ? "column" : "row",
}}
>
{["stroke", "diabetes", "cvd"].map((key) => (
@@ -231,7 +238,13 @@ const PatientDetails = () => {
>
{key.toUpperCase()}
-
+
{patientData?.risks?.[key]?.[0] ?? 0}%
{
height: { xs: "auto", md: "95%" },
}}
>
-
+
Latest Recommendations
@@ -311,7 +324,10 @@ const PatientDetails = () => {
: "none",
}}
>
-
+
{key.toUpperCase()}
diff --git a/client/src/routes/merchant/PatientManagement.js b/client/src/routes/merchant/PatientManagement.js
index fbf6a874..5604a512 100644
--- a/client/src/routes/merchant/PatientManagement.js
+++ b/client/src/routes/merchant/PatientManagement.js
@@ -1,25 +1,27 @@
-import { useState, useEffect } from "react";
-import { useNavigate } from "react-router-dom";
-import ConfirmationDialog from "../../components/dialog/confirmationDialog";
-import InputAdornment from "@mui/material/InputAdornment";
import {
Box,
- Typography,
Button,
- Paper,
- TextField,
+ Divider,
Menu,
MenuItem,
- Divider,
+ Paper,
Stack,
+ TextField,
+ Typography,
+ useMediaQuery,
+ useTheme,
} from "@mui/material";
+import InputAdornment from "@mui/material/InputAdornment";
import { DataGrid } from "@mui/x-data-grid";
+import { useEffect, useState, useCallback } from "react";
+import { useNavigate } from "react-router-dom";
+import ConfirmationDialog from "../../components/dialog/confirmationDialog";
// Icons
import DeleteIcon from "@mui/icons-material/Delete";
-import VisibilityIcon from "@mui/icons-material/Visibility";
import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
import SearchIcon from "@mui/icons-material/Search";
+import VisibilityIcon from "@mui/icons-material/Visibility";
/**
* A page used to display a list of all patients for a merchant user.
@@ -30,13 +32,15 @@ const PatientManagement = () => {
const API_BASE = process.env.REACT_APP_API_URL || "http://localhost:8000";
const navigate = useNavigate();
+ const theme = useTheme();
+ const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
+
const [patientData, setPatientData] = useState([]);
const [paginationModel, setPaginationModel] = useState({
page: 0,
pageSize: 25,
});
const [totalPatients, setTotalPatients] = useState(0);
- const [loading, setLoading] = useState(false);
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [selectedPatientID, setSelectedPatientID] = useState(null);
@@ -108,38 +112,7 @@ const PatientManagement = () => {
),
},
];
-
- useEffect(() => {
- fetchPatients();
- }, [
- paginationModel.page,
- paginationModel.pageSize,
- givenNameInput,
- familyNameInput,
- ]);
-
- // Debounce given name input
- useEffect(() => {
- const timer = setTimeout(() => {
- // resetting page to 0 when filter changes
- setPaginationModel((prev) => ({ ...prev, page: 0 }));
- setGivenNameInput(givenNameInput);
- }, 500);
- return () => clearTimeout(timer);
- }, [givenNameInput]);
-
- // Debounce last name input
- useEffect(() => {
- const timer = setTimeout(() => {
- // resetting page to 0 when filter changes
- setPaginationModel((prev) => ({ ...prev, page: 0 }));
- setFamilyNameInput(familyNameInput);
- }, 500);
- return () => clearTimeout(timer);
- }, [familyNameInput]);
-
- const fetchPatients = () => {
- setLoading(true);
+ const fetchPatients = useCallback(() => {
const params = new URLSearchParams({
skip: paginationModel.page * paginationModel.pageSize,
limit: paginationModel.pageSize,
@@ -156,13 +129,17 @@ const PatientManagement = () => {
.then((data) => {
setPatientData(data.patients || []);
setTotalPatients(data.totalPatients || 0);
- setLoading(false);
})
.catch((err) => {
console.log("An error has occurred");
- setLoading(false);
});
- };
+ }, [
+ API_BASE,
+ paginationModel.page,
+ paginationModel.pageSize,
+ givenNameInput,
+ familyNameInput,
+ ]);
async function handleDelete(patientID) {
await fetch(`${API_BASE}/remove-patient/${patientID}`, {
@@ -177,6 +154,30 @@ const PatientManagement = () => {
setDeleteDialogOpen(false);
}
+ useEffect(() => {
+ fetchPatients();
+ }, [fetchPatients]);
+
+ // Debounce given name input
+ useEffect(() => {
+ const timer = setTimeout(() => {
+ // resetting page to 0 when filter changes
+ setPaginationModel((prev) => ({ ...prev, page: 0 }));
+ setGivenNameInput(givenNameInput);
+ }, 500);
+ return () => clearTimeout(timer);
+ }, [givenNameInput]);
+
+ // Debounce last name input
+ useEffect(() => {
+ const timer = setTimeout(() => {
+ // resetting page to 0 when filter changes
+ setPaginationModel((prev) => ({ ...prev, page: 0 }));
+ setFamilyNameInput(familyNameInput);
+ }, 500);
+ return () => clearTimeout(timer);
+ }, [familyNameInput]);
+
return (
{
}}
>
-
+
Patient Management
diff --git a/client/src/routes/merchant/RequestPatientAccess.js b/client/src/routes/merchant/RequestPatientAccess.js
index 7c8e2a6b..0cfeb7ef 100644
--- a/client/src/routes/merchant/RequestPatientAccess.js
+++ b/client/src/routes/merchant/RequestPatientAccess.js
@@ -1,13 +1,4 @@
-import {
- Box,
- Container,
- Stack,
- Typography,
- Button,
- Link,
- Divider,
-} from "@mui/material";
-import ForgotPasswordForm from "../../components/authentication/ForgotPasswordForm";
+import { Box, Container } from "@mui/material";
import RequestPatientAccessForm from "../../components/patientAccessRequest/RequestPatientAccessForm";
/**
@@ -17,23 +8,32 @@ import RequestPatientAccessForm from "../../components/patientAccessRequest/Requ
*/
const RequestPatientAccess = () => {
return (
-
-
-
-
-
+
+
+
+
+
+
);
};
diff --git a/client/src/routes/public/ErrorPage.js b/client/src/routes/public/ErrorPage.js
index c4ca9e26..0fc4ab8c 100644
--- a/client/src/routes/public/ErrorPage.js
+++ b/client/src/routes/public/ErrorPage.js
@@ -1,6 +1,5 @@
-import { Typography, Button, Box, Stack } from "@mui/material";
+import { Box, Button, Stack, Typography } from "@mui/material";
import { useNavigate } from "react-router-dom";
-import Logo from "../../assets/WellAiLogoTR.png";
/**
* A page that is displayed when a user tried to navigate a non-existent
diff --git a/client/src/routes/public/Login.js b/client/src/routes/public/Login.js
index bde537d5..1f3ed332 100644
--- a/client/src/routes/public/Login.js
+++ b/client/src/routes/public/Login.js
@@ -1,6 +1,5 @@
-import { Box, Container, Stack, Typography } from "@mui/material";
+import { Box, Stack } from "@mui/material";
import LoginForm from "../../components/authentication/LoginForm";
-import Logo from "../../assets/WellAiLogoTR.png";
import WelcomePanel from "../../components/WelcomePanel";
/**
diff --git a/client/src/routes/standardUser/AcceptAccessRequest.js b/client/src/routes/standardUser/AcceptAccessRequest.js
index 853b6927..1508e057 100644
--- a/client/src/routes/standardUser/AcceptAccessRequest.js
+++ b/client/src/routes/standardUser/AcceptAccessRequest.js
@@ -1,12 +1,4 @@
-import {
- Box,
- Container,
- Stack,
- Typography,
- Button,
- Link,
- Divider,
-} from "@mui/material";
+import { Box, Container } from "@mui/material";
import AcceptRequestForm from "../../components/patientAccessRequest/AcceptRequestForm";
/**
@@ -17,23 +9,32 @@ import AcceptRequestForm from "../../components/patientAccessRequest/AcceptReque
*/
const AcceptAccessRequest = () => {
return (
-
-
-
-
-
+
+
+
+
+
+
);
};
diff --git a/client/src/routes/standardUser/GenerateReport.js b/client/src/routes/standardUser/GenerateReport.js
index 2b49cb83..25f95b28 100644
--- a/client/src/routes/standardUser/GenerateReport.js
+++ b/client/src/routes/standardUser/GenerateReport.js
@@ -1,12 +1,12 @@
-import GenerateReportForm from "../../components/healthReport/GenerateReportForm";
import { Box } from "@mui/material";
+import GenerateReportForm from "../../components/healthReport/GenerateReportForm";
/**
* A page that provides the form for user's to generate a health report.
*
* @returns {@mui.material.Box}
*/
-const GenerateReport = ({}) => {
+const GenerateReport = () => {
return (
{
if (!label) {
@@ -107,7 +107,10 @@ const HealthAnalytics = () => {
};
// Helpers for aggregation and y-axis scaling
- const colors = [theme.palette.primary.main, "#ff7043", "#42a5f5"];
+ const colors = useMemo(
+ () => [theme.palette.primary.main, "#ff7043", "#42a5f5"],
+ [theme.palette.primary.main],
+ );
const cardWrapperSx = useMemo(
() => ({
@@ -290,16 +293,12 @@ const HealthAnalytics = () => {
boxSizing: "border-box",
}}
>
-
-
- Health Analytics
-
-
+
+ Health Analytics
+
@@ -311,9 +310,10 @@ const HealthAnalytics = () => {
mb: showSettings ? 2 : 0,
}}
>
-
+
Probability Metrics Selection
+
{isMobile && (
setShowSettings(!showSettings)}
@@ -377,11 +377,7 @@ const HealthAnalytics = () => {
-
+
Health Risk Trends Over Time
{chartSeries.length > 0 && healthData.length > 0 ? (
@@ -468,7 +464,8 @@ const HealthAnalytics = () => {
>