diff --git a/Client/src/Pages/Monitors/Details/Charts/index.jsx b/Client/src/Pages/Monitors/Details/Charts/index.jsx
new file mode 100644
index 000000000..54d9716fa
--- /dev/null
+++ b/Client/src/Pages/Monitors/Details/Charts/index.jsx
@@ -0,0 +1,92 @@
+import { useTheme } from "@emotion/react";
+import {
+ BarChart,
+ Bar,
+ XAxis,
+ CartesianGrid,
+ ResponsiveContainer,
+} from "recharts";
+import { formatDate } from "../../../../Utils/timeUtils";
+
+const CustomLabels = ({ x, width, height, firstDataPoint, lastDataPoint }) => {
+ let options = {
+ month: "short",
+ year: undefined,
+ hour: undefined,
+ minute: undefined,
+ };
+
+ return (
+ <>
+
+ {formatDate(new Date(firstDataPoint.day), options)}
+
+
+ {formatDate(new Date(lastDataPoint.day), options)}
+
+ >
+ );
+};
+
+export const UpBarChart = ({ data, dateRange }) => {
+ const theme = useTheme();
+
+ return (
+
+
+
+ }
+ />
+
+
+
+ );
+};
+
+export const DownBarChart = ({ data }) => {
+ const theme = useTheme();
+
+ return (
+
+
+
+ }
+ />
+
+
+
+ );
+};
diff --git a/Client/src/Pages/Monitors/Details/index.jsx b/Client/src/Pages/Monitors/Details/index.jsx
index 8aef758a0..6f717143e 100644
--- a/Client/src/Pages/Monitors/Details/index.jsx
+++ b/Client/src/Pages/Monitors/Details/index.jsx
@@ -33,6 +33,7 @@ import PaginationTable from "./PaginationTable";
import Breadcrumbs from "../../../Components/Breadcrumbs";
import PulseDot from "../../../Components/Animated/PulseDot";
import { StatBox, ChartBox, IconBox } from "./styled";
+import { DownBarChart, UpBarChart } from "./Charts";
import "./index.css";
/**
@@ -186,6 +187,55 @@ const DetailsPage = ({ isAdmin }) => {
};
let loading = Object.keys(monitor).length === 0;
+
+ const [aggregateStats, setAggregateStats] = useState({});
+ useEffect(() => {
+ const fetchAggregateStats = async () => {
+ try {
+ const res = await networkService.getAggregateStatsById(
+ authToken,
+ monitorId,
+ dateRange
+ );
+
+ setAggregateStats(res?.data?.data);
+ } catch (error) {
+ console.error(error);
+ }
+ };
+ fetchAggregateStats();
+ }, [monitorId, dateRange]);
+
+ const calculateStats = () => {
+ let totalChecks = 0;
+ let totalIncidents = 0;
+ let totalResponseTime = 0;
+ let count = 0;
+
+ Object.keys(aggregateStats).forEach((entry) => {
+ totalChecks += aggregateStats[entry].totalChecks;
+ totalIncidents += aggregateStats[entry].totalIncidents;
+ totalResponseTime += aggregateStats[entry].totalIncidents;
+ count++;
+ });
+
+ let uptime =
+ dateRange === "day"
+ ? monitor.uptime24Hours
+ : dateRange === "week"
+ ? monitor.uptime7Days
+ : dateRange === "month" && monitor.uptime30Days;
+
+ return {
+ totalChecks: totalChecks,
+ totalIncidents: totalIncidents,
+ averageResponseTime: totalResponseTime / count,
+ uptime: uptime,
+ };
+ };
+
+ const monitorStats = calculateStats();
+ console.log(aggregateStats);
return (
{loading ? (
@@ -431,18 +481,22 @@ const DetailsPage = ({ isAdmin }) => {
Uptime
-
+
Total Checks
- 87
+
+ {monitorStats.totalChecks}
+
Uptime Percentage
- 98.3%
+ {monitorStats.uptime}
+ %
+
@@ -451,10 +505,13 @@ const DetailsPage = ({ isAdmin }) => {
Incidents
-
+
Total Incidents
- 0
+
+ {monitorStats.totalIncidents}
+
+
diff --git a/Client/src/Pages/Monitors/Details/styled.jsx b/Client/src/Pages/Monitors/Details/styled.jsx
index 8e1ee9774..1ed6ca8ee 100644
--- a/Client/src/Pages/Monitors/Details/styled.jsx
+++ b/Client/src/Pages/Monitors/Details/styled.jsx
@@ -36,6 +36,10 @@ export const ChartBox = styled(Box)(({ theme }) => ({
"& > .MuiBox-root:not(:first-of-type)": {
marginTop: theme.spacing(8),
},
+ "& tspan, & text": {
+ fontSize: 11,
+ fill: theme.palette.text.tertiary,
+ },
}));
export const IconBox = styled(Box)(({ theme }) => ({
diff --git a/Client/src/Utils/NetworkService.js b/Client/src/Utils/NetworkService.js
index 6dcde82bb..acb1134e4 100644
--- a/Client/src/Utils/NetworkService.js
+++ b/Client/src/Utils/NetworkService.js
@@ -146,6 +146,31 @@ class NetworkService {
);
}
+ /**
+ * ************************************
+ * Gets aggregate stats by monitor ID
+ * ************************************
+ *
+ * @async
+ * @param {string} authToken - The authorization token to be used in the request header.
+ * @param {string} monitorId - The ID of the monitor whose certificate expiry is to be retrieved.
+ * @returns {Promise} The response from the axios GET request.
+ *
+ */
+ async getAggregateStatsById(authToken, monitorId, dateRange) {
+ const params = new URLSearchParams();
+ if (dateRange) params.append("dateRange", dateRange);
+
+ return this.axiosInstance.get(
+ `/monitors/aggregate/${monitorId}?${params.toString()}`,
+ {
+ headers: {
+ Authorization: `Bearer ${authToken}`,
+ },
+ }
+ );
+ }
+
/**
* ************************************
* Updates a single monitor