diff --git a/client/src/Components/monitors/HeaderGeoTabs.tsx b/client/src/Components/monitors/HeaderGeoTabs.tsx
new file mode 100644
index 000000000..06753bc14
--- /dev/null
+++ b/client/src/Components/monitors/HeaderGeoTabs.tsx
@@ -0,0 +1,56 @@
+import Stack from "@mui/material/Stack";
+import { Tabs, Tab } from "@/Components/design-elements";
+import { useTheme } from "@mui/material/styles";
+import { useTranslation } from "react-i18next";
+import type { GeoContinent } from "@/Types/GeoCheck";
+
+interface HeaderGeoTabsProps {
+ geoCheckEnabled: boolean;
+ locations: GeoContinent[] | undefined;
+ selectedLocation: GeoContinent;
+ onLocationChange: (location: GeoContinent) => void;
+}
+
+export const HeaderGeoTabs = ({
+ geoCheckEnabled,
+ locations,
+ selectedLocation,
+ onLocationChange,
+}: HeaderGeoTabsProps) => {
+ const { t } = useTranslation();
+ const theme = useTheme();
+
+ if (!geoCheckEnabled || !locations || locations.length === 0) {
+ return null;
+ }
+
+ const handleChange = (_event: React.SyntheticEvent, newValue: GeoContinent) => {
+ onLocationChange(newValue);
+ };
+
+ console.log(locations);
+
+ return (
+
+
+ {locations.map((location) => (
+
+ ))}
+
+
+ );
+};
diff --git a/client/src/Components/monitors/index.tsx b/client/src/Components/monitors/index.tsx
index 9496395f6..d06a374a3 100644
--- a/client/src/Components/monitors/index.tsx
+++ b/client/src/Components/monitors/index.tsx
@@ -1,6 +1,7 @@
export * from "./ControlsFilter";
export * from "./MonitorStatBoxes";
export * from "./HeaderMonitorControls";
+export * from "./HeaderGeoTabs";
export * from "./charts/HistogramStatus";
export * from "./charts/RadialAvgResponse";
export * from "./charts/HistogramDetails";
diff --git a/client/src/Pages/Uptime/Details/index.tsx b/client/src/Pages/Uptime/Details/index.tsx
index 23f9a2196..d6ffc213c 100644
--- a/client/src/Pages/Uptime/Details/index.tsx
+++ b/client/src/Pages/Uptime/Details/index.tsx
@@ -6,6 +6,7 @@ import {
RadialAvgResponse,
HistogramDetails,
HeaderMonitorControls,
+ HeaderGeoTabs,
} from "@/Components/monitors";
import { TrendingUp, AlertTriangle } from "lucide-react";
import { ChecksTable } from "@/Pages/Uptime/Details/Components/ChecksTable";
@@ -19,9 +20,11 @@ import { useSelector } from "react-redux";
import { useGet } from "@/Hooks/UseApi";
import type { MonitorDetailsResponse } from "@/Types/Monitor";
import type { ChecksResponse } from "@/Types/Check";
+import type { GeoChecksResult, GeoContinent } from "@/Types/GeoCheck";
import type { RootState } from "@/Types/state";
import { formatDateWithTz } from "@/Utils/TimeUtils";
import { t } from "i18next";
+import { Typography } from "@mui/material";
const certificateDateFormat = "MMM D, YYYY h A";
@@ -38,6 +41,7 @@ const UptimeDetailsPage = () => {
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(5);
const [dateRange, setDateRange] = useState("recent");
+ const [selectedLocation, setSelectedLocation] = useState("NA");
const monitorDetailsUrl = useMemo(() => {
if (!monitorId) {
@@ -105,6 +109,22 @@ const UptimeDetailsPage = () => {
{ keepPreviousData: true }
);
+ // Geo checks fetch - only for HTTP monitors with geo checks enabled
+ const geoChecksUrl = useMemo(() => {
+ if (!monitorId || monitor?.type !== "http" || !monitor?.geoCheckEnabled) {
+ return null;
+ }
+ const params = new URLSearchParams();
+ params.append("dateRange", dateRange);
+ return `/monitors/${monitorId}/geo-checks?${params.toString()}`;
+ }, [monitorId, monitor?.type, monitor?.geoCheckEnabled, dateRange]);
+
+ const { data: _geoChecksData, isLoading: _geoChecksIsLoading } =
+ useGet(geoChecksUrl, {}, { keepPreviousData: true });
+
+ // Extract unique locations from geo checks data
+ const geoLocations = monitor?.geoCheckLocations;
+
const checks = checksData?.checks ?? [];
const checksCount = checksData?.checksCount ?? 0;
@@ -127,6 +147,7 @@ const UptimeDetailsPage = () => {
dateRange={dateRange}
setDateRange={setDateRange}
/>
+
{
rowsPerPage={rowsPerPage}
setRowsPerPage={setRowsPerPage}
/>
+
+ {monitor?.geoCheckEnabled && (
+
+ Location breakdown
+
+
+ )}
);
};