diff --git a/client/src/components/AppThemeProvider.jsx b/client/src/components/AppThemeProvider.jsx index be1f45f5..f14dacc8 100644 --- a/client/src/components/AppThemeProvider.jsx +++ b/client/src/components/AppThemeProvider.jsx @@ -1,7 +1,5 @@ -import React from "react"; -import { ThemeProvider, createTheme } from "@mui/material"; import "@fontsource/russo-one"; -import { color, fontWeight } from "@mui/system"; +import { ThemeProvider, createTheme } from "@mui/material"; /** * A centralized MUI theme for the web app. @@ -137,6 +135,10 @@ export const appTheme = createTheme({ fontWeight: "regular", fontFamily: "'Russo One', 'sans-serif'", }, + h6: { + fontWeight: "regular", + fontFamily: "'Russo One', 'sans-serif'", + }, h7: { fontWeight: "regular", fontFamily: "'Russo One', 'sans-serif'", @@ -150,7 +152,6 @@ export const appTheme = createTheme({ disableRowSelectionOnClick: true, autoHeight: false, density: "standard", - autoHeight: false, }, styleOverrides: { root: { diff --git a/client/src/components/Navbar.js b/client/src/components/Navbar.js index 8a9d3eb4..283ac71e 100644 --- a/client/src/components/Navbar.js +++ b/client/src/components/Navbar.js @@ -1,40 +1,35 @@ -import AppBar from "@mui/material/AppBar"; -import Box from "@mui/material/Box"; -import Toolbar from "@mui/material/Toolbar"; -import Typography from "@mui/material/Typography"; -import Button from "@mui/material/Button"; -import Menu from "@mui/material/Menu"; -import { useNavigate, useLocation } from "react-router-dom"; -import MenuItem from "@mui/material/MenuItem"; -import { useContext, useState } from "react"; -import logo from "../assets/WellAiLogoTR.png"; import { + Backdrop, Drawer, + IconButton, List, ListItemButton, - IconButton, Tooltip, - ClickAwayListener, - Backdrop, } from "@mui/material"; +import AppBar from "@mui/material/AppBar"; +import Box from "@mui/material/Box"; +import Toolbar from "@mui/material/Toolbar"; +import Typography from "@mui/material/Typography"; +import { useContext, useState } from "react"; +import { useLocation, useNavigate } from "react-router-dom"; +import logo from "../assets/WellAiLogoTR.png"; import { UserContext } from "../utils/UserContext"; -import PrivacyNotice from "./dialog/PrivacyNotice"; import DisclaimerPolicy from "./dialog/DisclaimerPolicy"; +import PrivacyNotice from "./dialog/PrivacyNotice"; // Icons -import AccountCircleIcon from "@mui/icons-material/AccountCircle"; +import ChevronLeftIcon from "@mui/icons-material/ChevronLeft"; import DashboardIcon from "@mui/icons-material/Dashboard"; -import RestorePageIcon from "@mui/icons-material/RestorePage"; -import TimelineIcon from "@mui/icons-material/Timeline"; -import HistoryIcon from "@mui/icons-material/History"; -import SettingsIcon from "@mui/icons-material/Settings"; -import LogoutIcon from "@mui/icons-material/Logout"; +import FileCopyIcon from "@mui/icons-material/FileCopy"; import GroupIcon from "@mui/icons-material/Group"; +import HistoryIcon from "@mui/icons-material/History"; import HowToRegIcon from "@mui/icons-material/HowToReg"; -import FileCopyIcon from "@mui/icons-material/FileCopy"; +import LogoutIcon from "@mui/icons-material/Logout"; import ManageAccountsIcon from "@mui/icons-material/ManageAccounts"; import MenuIcon from "@mui/icons-material/Menu"; -import ChevronLeftIcon from "@mui/icons-material/ChevronLeft"; +import RestorePageIcon from "@mui/icons-material/RestorePage"; +import SettingsIcon from "@mui/icons-material/Settings"; +import TimelineIcon from "@mui/icons-material/Timeline"; const API_BASE = process.env.REACT_APP_API_URL || "http://localhost:8000"; @@ -54,7 +49,7 @@ const NavBar = ({ role }) => { // User Pages "/user-landing": "Dashboard", "/generate-report": "Generate Report", - "/ai-health-prediction": "Report History", + "/report-history": "Report History", "/health-analytics": "Health Analytics", "/user-settings": "Settings", @@ -115,9 +110,6 @@ const NavBar = ({ role }) => { { icon: , title: "Logout" }, ]; - // Check if settings menu is open - const [openMenu, setOpenMenu] = useState(null); - // User Logout async function logout() { await fetch(`${API_BASE}/logout`, { @@ -169,11 +161,9 @@ const NavBar = ({ role }) => { navigate("/health-analytics"); } if (page === "Settings") { - handleCloseSettings(); navigate("/user-settings"); } if (page === "Logout") { - handleCloseSettings(); logout(); } if (page === "Users") { @@ -196,15 +186,6 @@ const NavBar = ({ role }) => { } } - function handleOpenSettings(e) { - setOpenMenu(e.currentTarget); - console.log(openMenu); - } - - function handleCloseSettings() { - setOpenMenu(null); - } - // Navigation Bar for standard user type if (role === "standard_user") return ( diff --git a/client/src/components/administrator/AccountApprovalTable.js b/client/src/components/administrator/AccountApprovalTable.js index 9d2ae3b8..92d97590 100644 --- a/client/src/components/administrator/AccountApprovalTable.js +++ b/client/src/components/administrator/AccountApprovalTable.js @@ -1,6 +1,6 @@ -import { useState, useEffect } from "react"; -import { Paper, Button, Box } from "@mui/material"; +import { Box, Button, Paper } from "@mui/material"; import { DataGrid } from "@mui/x-data-grid"; +import { useEffect, useState } from "react"; import ConfirmationDialog from "../dialog/confirmationDialog"; const API_BASE = process.env.REACT_APP_API_URL || "http://localhost:8000"; @@ -10,7 +10,7 @@ const API_BASE = process.env.REACT_APP_API_URL || "http://localhost:8000"; * * @returns {@mui.material.Box} */ -const AccountApprovalTable = ({}) => { +const AccountApprovalTable = () => { const [userData, setUserData] = useState([]); // Stores user data const [selectedUser, setselectedUser] = useState(); // Stores the selected user const [dialogOpen, setDialogOpen] = useState(false); // Stores dialog state diff --git a/client/src/components/administrator/AuditLogSearchBar.js b/client/src/components/administrator/AuditLogSearchBar.js index b98af4f3..f26e9740 100644 --- a/client/src/components/administrator/AuditLogSearchBar.js +++ b/client/src/components/administrator/AuditLogSearchBar.js @@ -1,5 +1,5 @@ import SearchIcon from "@mui/icons-material/Search"; -import { TextField, InputAdornment, Box } from "@mui/material"; +import { Box, InputAdornment, TextField } from "@mui/material"; import { memo, useEffect, useState } from "react"; /** diff --git a/client/src/components/administrator/AuditLogTable.js b/client/src/components/administrator/AuditLogTable.js index 7e4c241e..0fb6e367 100644 --- a/client/src/components/administrator/AuditLogTable.js +++ b/client/src/components/administrator/AuditLogTable.js @@ -1,14 +1,14 @@ -import { useCallback, useEffect, useState } from "react"; -import { DataGrid } from "@mui/x-data-grid"; import { - Paper, Box, - Select, - MenuItem, - InputLabel, - FormControl, Divider, + FormControl, + InputLabel, + MenuItem, + Paper, + Select, } from "@mui/material"; +import { DataGrid } from "@mui/x-data-grid"; +import { useCallback, useEffect, useState } from "react"; import AuditLogSearchBar from "./AuditLogSearchBar"; const API_BASE = process.env.REACT_APP_API_URL || "http://localhost:8000"; @@ -53,8 +53,9 @@ const AuditLogTable = () => { const [userEmail, setUserEmail] = useState(""); const [eventType, setEventType] = useState(""); - const fetchLogs = () => { + const fetchLogs = useCallback(() => { setLoading(true); + const params = new URLSearchParams({ skip: paginationModel.page * paginationModel.pageSize, limit: paginationModel.pageSize, @@ -62,12 +63,15 @@ const AuditLogTable = () => { if (userEmail) params.append("user_email", userEmail); if (eventType) params.append("event_type", eventType); + if (sortModel.length > 0) { params.append("sort_by", sortModel[0].field); params.append("sort_order", sortModel[0].sort || "desc"); } - fetch(`${API_BASE}/logs?${params.toString()}`, { credentials: "include" }) + fetch(`${API_BASE}/logs?${params.toString()}`, { + credentials: "include", + }) .then((response) => { if (!response.ok) { throw new Error(response.status); @@ -83,10 +87,6 @@ const AuditLogTable = () => { console.log(err); setLoading(false); }); - }; - - useEffect(() => { - fetchLogs(); }, [ paginationModel.page, paginationModel.pageSize, @@ -95,6 +95,10 @@ const AuditLogTable = () => { sortModel, ]); + useEffect(() => { + fetchLogs(); + }, [fetchLogs]); + const handleEmailSearchChange = useCallback((value) => { setPaginationModel((prev) => ({ ...prev, page: 0 })); setUserEmail(value); diff --git a/client/src/components/administrator/UserManagementTable.js b/client/src/components/administrator/UserManagementTable.js index 4c28ac26..127045f6 100644 --- a/client/src/components/administrator/UserManagementTable.js +++ b/client/src/components/administrator/UserManagementTable.js @@ -1,18 +1,10 @@ -import { - Paper, - Box, - Snackbar, - Alert, - Stack, - Typography, - Divider, -} from "@mui/material"; +import { Alert, Box, Divider, Paper, Snackbar } from "@mui/material"; import { DataGrid } from "@mui/x-data-grid"; -import { useState, useEffect, useCallback } from "react"; +import * as React from "react"; +import { useCallback, useEffect, useState } from "react"; import ConfirmationDialog from "../dialog/confirmationDialog"; import UserSearchBar from "./UserSearchBar"; import UserToolBar from "./UserToolBar"; -import * as React from "react"; /** * A table listing all the user accounts in the system with tools to search @@ -52,15 +44,18 @@ const UserManagementTable = () => { const API_BASE = process.env.REACT_APP_API_URL || "http://localhost:8000"; - const fetchUsers = () => { + const fetchUsers = useCallback(() => { setLoading(true); + const params = new URLSearchParams({ skip: paginationModel.page * paginationModel.pageSize, limit: paginationModel.pageSize, }); + if (debouncedSearchQuery) { params.append("search", debouncedSearchQuery); } + if (selectedClinic) { params.append("clinic_id", selectedClinic); } @@ -87,10 +82,6 @@ const UserManagementTable = () => { console.log(err); setLoading(false); }); - }; - - useEffect(() => { - fetchUsers(); }, [ API_BASE, paginationModel.page, @@ -100,6 +91,10 @@ const UserManagementTable = () => { sortModel, ]); + useEffect(() => { + fetchUsers(); + }, [fetchUsers]); + useEffect(() => { setPaginationModel((prev) => ({ ...prev, page: 0 })); }, [API_BASE]); diff --git a/client/src/components/administrator/UserSearchBar.js b/client/src/components/administrator/UserSearchBar.js index bc72c3ed..595f84e3 100644 --- a/client/src/components/administrator/UserSearchBar.js +++ b/client/src/components/administrator/UserSearchBar.js @@ -1,7 +1,7 @@ import SearchIcon from "@mui/icons-material/Search"; -import { TextField, Box } from "@mui/material"; +import { Box, TextField } from "@mui/material"; import InputAdornment from "@mui/material/InputAdornment"; -import { useEffect, useState, memo } from "react"; +import { memo, useEffect, useState } from "react"; /** * A search bar that is used as an element in the UserManagementTable to diff --git a/client/src/components/administrator/UserToolBar.js b/client/src/components/administrator/UserToolBar.js index e57404a7..495d0a69 100644 --- a/client/src/components/administrator/UserToolBar.js +++ b/client/src/components/administrator/UserToolBar.js @@ -1,5 +1,5 @@ -import { Box, Select, Button, MenuItem } from "@mui/material"; import DeleteForeverIcon from "@mui/icons-material/DeleteForever"; +import { Box, Button, MenuItem, Select } from "@mui/material"; /** * A tool bar to that provides the controls for modifying and filtering user diff --git a/client/src/components/administrator/analytics/ActiveMerchantsAnalytics.js b/client/src/components/administrator/analytics/ActiveMerchantsAnalytics.js index cec30903..37ba18b6 100644 --- a/client/src/components/administrator/analytics/ActiveMerchantsAnalytics.js +++ b/client/src/components/administrator/analytics/ActiveMerchantsAnalytics.js @@ -1,12 +1,4 @@ -import { - Card, - CardContent, - Container, - Divider, - Paper, - Stack, - Typography, -} from "@mui/material"; +import { Card, CardContent, Stack, Typography } from "@mui/material"; import { useEffect, useState } from "react"; const API_BASE = process.env.REACT_APP_API_URL || "http://localhost:8000"; diff --git a/client/src/components/administrator/analytics/ActiveUsersAnalytics.js b/client/src/components/administrator/analytics/ActiveUsersAnalytics.js index 782c02bc..079e8ab5 100644 --- a/client/src/components/administrator/analytics/ActiveUsersAnalytics.js +++ b/client/src/components/administrator/analytics/ActiveUsersAnalytics.js @@ -1,12 +1,4 @@ -import { - Card, - CardContent, - Container, - Divider, - Paper, - Stack, - Typography, -} from "@mui/material"; +import { Card, CardContent, Stack, Typography } from "@mui/material"; import { useEffect, useState } from "react"; const API_BASE = process.env.REACT_APP_API_URL || "http://localhost:8000"; diff --git a/client/src/components/administrator/analytics/AverageRiskSeriesAnalytics.js b/client/src/components/administrator/analytics/AverageRiskSeriesAnalytics.js index b2351026..f5810a31 100644 --- a/client/src/components/administrator/analytics/AverageRiskSeriesAnalytics.js +++ b/client/src/components/administrator/analytics/AverageRiskSeriesAnalytics.js @@ -1,23 +1,21 @@ import { Card, CardContent, - Container, - Paper, - Typography, - Select, - MenuItem, + FormControl, Grid, InputLabel, - FormControl, + MenuItem, + Select, + Typography, + useMediaQuery, + useTheme, } from "@mui/material"; -import { Stack } from "@mui/system"; -import { useEffect, useState } from "react"; -import { LineChart } from "@mui/x-charts/LineChart"; import Divider from "@mui/material/Divider"; +import { LineChart } from "@mui/x-charts/LineChart"; import dayjs from "dayjs"; +import { useEffect, useState } from "react"; const API_BASE = process.env.REACT_APP_API_URL || "http://localhost:8000"; -const DEFAULT_YEAR = 2026; /** * A card that displays the average progression for stroke, diabetes, @@ -26,6 +24,9 @@ const DEFAULT_YEAR = 2026; * @returns {@mui.material.Card} */ const AverageRiskSeriesAnalytics = () => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down("sm")); + const [availableYears, setAvailableYears] = useState([]); const [year, setYear] = useState(""); const [xAxisData, setXAxisData] = useState([]); @@ -73,10 +74,6 @@ const AverageRiskSeriesAnalytics = () => { }); }, [year]); - function extractXAxisData(rawData) { - return rawData.map((d) => new Date(d.date)); - } - return ( @@ -99,7 +96,7 @@ const AverageRiskSeriesAnalytics = () => { Average Disease Risk (%) - + Year