diff --git a/Plan/react/dashboard/src/components/cards/CardHeader.js b/Plan/react/dashboard/src/components/cards/CardHeader.js
new file mode 100644
index 000000000..3eeedaefb
--- /dev/null
+++ b/Plan/react/dashboard/src/components/cards/CardHeader.js
@@ -0,0 +1,18 @@
+import React from 'react';
+import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
+import {Card} from "react-bootstrap-v5";
+import {useTranslation} from "react-i18next";
+
+const CardHeader = ({icon, color, label}) => {
+ const {t} = useTranslation();
+
+ return (
+
+
+ {t(label)}
+
+
+ )
+};
+
+export default CardHeader
\ No newline at end of file
diff --git a/Plan/react/dashboard/src/components/cards/common/PingTableCard.js b/Plan/react/dashboard/src/components/cards/common/PingTableCard.js
new file mode 100644
index 000000000..e9b3c2552
--- /dev/null
+++ b/Plan/react/dashboard/src/components/cards/common/PingTableCard.js
@@ -0,0 +1,16 @@
+import React from 'react';
+import {Card} from "react-bootstrap-v5";
+import CardHeader from "../CardHeader";
+import {faWifi} from "@fortawesome/free-solid-svg-icons";
+import PingTable from "../../table/PingTable";
+
+const PingTableCard = ({data}) => {
+ return (
+
+
+
+
+ )
+};
+
+export default PingTableCard
\ No newline at end of file
diff --git a/Plan/react/dashboard/src/components/table/PingTable.js b/Plan/react/dashboard/src/components/table/PingTable.js
new file mode 100644
index 000000000..0c9895578
--- /dev/null
+++ b/Plan/react/dashboard/src/components/table/PingTable.js
@@ -0,0 +1,42 @@
+import React from "react";
+import {useTheme} from "../../hooks/themeHook";
+import {useTranslation} from "react-i18next";
+
+const PingRow = ({country}) => {
+ return (
+
+ {country.country} |
+ {country.avg_ping} |
+ {country.min_ping} |
+ {country.max_ping} |
+
+ );
+}
+
+const PingTable = ({countries}) => {
+ const {t} = useTranslation();
+ const {nightModeEnabled} = useTheme();
+
+ return (
+
+
+
+ {t('html.label.country')} |
+ {t('html.label.averagePing')} |
+ {t('html.label.bestPing')} |
+ {t('html.label.worstPing')} |
+
+
+
+ {countries.length ? countries.map((country, i) => ) :
+ {t('generic.noData')} |
+ - |
+ - |
+ - |
+
}
+
+
+ )
+};
+
+export default PingTable;
\ No newline at end of file
diff --git a/Plan/react/dashboard/src/service/serverService.js b/Plan/react/dashboard/src/service/serverService.js
index 955822362..33398fe38 100644
--- a/Plan/react/dashboard/src/service/serverService.js
+++ b/Plan/react/dashboard/src/service/serverService.js
@@ -48,6 +48,12 @@ export const fetchPlayers = async (identifier) => {
return doGetRequest(url);
}
+export const fetchPingTable = async (identifier) => {
+ const timestamp = Date.now();
+ const url = identifier ? `/v1/pingTable?server=${identifier}×tamp=${timestamp}` : `/v1/pingTable?timestamp=${timestamp}`;
+ return doGetRequest(url);
+}
+
export const fetchPlayersOnlineGraph = async (identifier) => {
const timestamp = Date.now();
const url = `/v1/graph?type=playersOnline&server=${identifier}×tamp=${timestamp}`;
diff --git a/Plan/react/dashboard/src/views/server/ServerGeolocations.js b/Plan/react/dashboard/src/views/server/ServerGeolocations.js
index 140ca9b04..48460c50e 100644
--- a/Plan/react/dashboard/src/views/server/ServerGeolocations.js
+++ b/Plan/react/dashboard/src/views/server/ServerGeolocations.js
@@ -1,25 +1,27 @@
import React from 'react';
import {useParams} from "react-router-dom";
import {useDataRequest} from "../../hooks/dataFetchHook";
-import {fetchGeolocations} from "../../service/serverService";
+import {fetchGeolocations, fetchPingTable} from "../../service/serverService";
import {Col, Row} from "react-bootstrap-v5";
-import ErrorView from "../ErrorView";
+import {ErrorViewCard} from "../ErrorView";
import GeolocationsCard from "../../components/cards/common/GeolocationsCard";
import LoadIn from "../../components/animation/LoadIn";
+import PingTableCard from "../../components/cards/common/PingTableCard";
const ServerGeolocations = () => {
const {identifier} = useParams();
const {data, loadingError} = useDataRequest(fetchGeolocations, [identifier]);
-
- if (loadingError) return
+ const {pingData, pingLoadingError} = useDataRequest(fetchPingTable, [identifier]);
return (
-
+ {loadingError ? : }
+ {pingLoadingError ? :
+ }