diff --git a/Client/src/Pages/DistributedUptime/Details/index.jsx b/Client/src/Pages/DistributedUptime/Details/index.jsx new file mode 100644 index 000000000..6c921063f --- /dev/null +++ b/Client/src/Pages/DistributedUptime/Details/index.jsx @@ -0,0 +1,325 @@ +//Components +import DistributedUptimeMap from "./Components/DistributedUptimeMap"; +import Breadcrumbs from "../../../Components/Breadcrumbs"; +import { Stack, Typography, Box, Button, ButtonGroup } from "@mui/material"; +import ChartBox from "../../../Components/Charts/ChartBox"; +import StatBox from "../../../Components/StatBox"; +import ResponseTimeIcon from "../../../assets/icons/response-time-icon.svg?react"; +import DeviceTicker from "./Components/DeviceTicker"; +import DistributedUptimeResponseChart from "./Components/DistributedUptimeResponseChart"; +import UptLogo from "../../../assets/icons/upt_logo.png"; +import LastUpdate from "./Components/LastUpdate"; +import NextExpectedCheck from "./Components/NextExpectedCheck"; +import Footer from "./Components/Footer"; +//Utils +import { networkService } from "../../../main"; +import { useSelector } from "react-redux"; +import { useTheme } from "@mui/material/styles"; +import { useEffect, useState, useCallback, useRef } from "react"; +import { useParams } from "react-router-dom"; + +//Constants +const BASE_BOX_PADDING_VERTICAL = 8; +const BASE_BOX_PADDING_HORIZONTAL = 8; +const MAX_RETRIES = 10; +const RETRY_DELAY = 5000; + +function getRandomDevice() { + const manufacturers = { + Apple: ["iPhone 15 Pro Max", "iPhone 15", "iPhone 14 Pro", "iPhone 14", "iPhone 13"], + Samsung: [ + "Galaxy S23 Ultra", + "Galaxy S23+", + "Galaxy S23", + "Galaxy Z Fold5", + "Galaxy Z Flip5", + ], + Google: ["Pixel 8 Pro", "Pixel 8", "Pixel 7a", "Pixel 7", "Pixel 6a"], + OnePlus: [ + "OnePlus 11", + "OnePlus 10T", + "OnePlus Nord 3", + "OnePlus 10 Pro", + "OnePlus Nord 2T", + ], + Xiaomi: ["13 Pro", "13", "Redmi Note 12", "POCO F5", "Redmi 12"], + Huawei: ["P60 Pro", "Mate X3", "Nova 11", "P50 Pro", "Mate 50"], + Sony: ["Xperia 1 V", "Xperia 5 V", "Xperia 10 V", "Xperia Pro-I", "Xperia 1 IV"], + Motorola: ["Edge 40 Pro", "Edge 40", "G84", "G54", "Razr 40 Ultra"], + ASUS: [ + "ROG Phone 7", + "Zenfone 10", + "ROG Phone 6", + "Zenfone 9", + "ROG Phone 7 Ultimate", + ], + }; + + const manufacturerNames = Object.keys(manufacturers); + const randomManufacturer = + manufacturerNames[Math.floor(Math.random() * manufacturerNames.length)]; + + const models = manufacturers[randomManufacturer]; + const randomModel = models[Math.floor(Math.random() * models.length)]; + + return { + manufacturer: randomManufacturer, + model: randomModel, + }; +} + +// export const StatBox = ({ heading, value, img, altTxt }) => { +// const theme = useTheme(); +// return ( +// +// {img && ( +// {altTxt} +// )} +// +// {heading} +// {value} +// +// +// ); +// }; + +const DistributedUptimeDetails = () => { + // Redux State + const { authToken } = useSelector((state) => state.auth); + const { mode } = useSelector((state) => state.ui); + + // Local State + // const [hoveredUptimeData, setHoveredUptimeData] = useState(null); + // const [hoveredIncidentsData, setHoveredIncidentsData] = useState(null); + const [retryCount, setRetryCount] = useState(0); + const [connectionStatus, setConnectionStatus] = useState("down"); + const [lastUpdateTrigger, setLastUpdateTrigger] = useState(Date.now()); + const [dateRange, setDateRange] = useState("day"); + const [monitor, setMonitor] = useState(null); + const [devices, setDevices] = useState([]); + + // Refs + const prevDateRangeRef = useRef(dateRange); + + // Utils + const theme = useTheme(); + const { monitorId } = useParams(); + + // Constants + const BREADCRUMBS = [ + { name: "Distributed Uptime", path: "/distributed-uptime" }, + { name: "Details", path: `/distributed-uptime/${monitorId}` }, + ]; + + useEffect(() => { + const hasDateRangeChanged = prevDateRangeRef.current !== dateRange; + prevDateRangeRef.current = dateRange; // Update the ref to the current dateRange + + if (!hasDateRangeChanged) { + setDevices(Array.from({ length: 5 }, getRandomDevice)); + } + }, [dateRange]); + + const connectToService = useCallback(() => { + return networkService.subscribeToDistributedUptimeDetails({ + authToken, + monitorId, + dateRange: dateRange, + normalize: true, + onUpdate: (data) => { + setLastUpdateTrigger(Date.now()); + const latestChecksWithDevice = data?.monitor?.latestChecks.map((check, idx) => { + check.device = devices[idx]; + return check; + }); + const monitorWithDevice = { + ...data.monitor, + latestChecks: latestChecksWithDevice, + }; + setMonitor(monitorWithDevice); + }, + onOpen: () => { + setConnectionStatus("up"); + setRetryCount(0); // Reset retry count on successful connection + }, + onError: () => { + setConnectionStatus("down"); + console.log("Error, attempting reconnect..."); + + if (retryCount < MAX_RETRIES) { + setTimeout(() => { + setRetryCount((prev) => prev + 1); + connectToService(); + }, RETRY_DELAY); + } else { + console.log("Max retries reached"); + } + }, + }); + }, [authToken, monitorId, dateRange, retryCount, devices]); + + useEffect(() => { + const devices = Array.from({ length: 5 }, getRandomDevice); + const cleanup = connectToService(devices); + return cleanup; + }, [connectToService]); + + return ( + monitor && ( + + + {monitor?.url !== "https://jup.ag/" && + monitor?.url !== "https://explorer.solana.com/" && ( + + + {monitor.name} + + + )} + + + Distributed Uptime Monitoring powered by DePIN + + + + + + + } + /> + + } + /> + + + + + + + + + Showing statistics for past{" "} + {dateRange === "day" + ? "24 hours" + : dateRange === "week" + ? "7 days" + : "30 days"} + . + + + + + + + + } + header="Response Times" + sx={{ padding: 0 }} + > + + + + + + +