diff --git a/index.html b/index.html index 3386ca010..a667d1ecf 100644 --- a/index.html +++ b/index.html @@ -14,4 +14,4 @@ - + \ No newline at end of file diff --git a/package.json b/package.json index 52b2eb0f0..2853123a8 100644 --- a/package.json +++ b/package.json @@ -19,9 +19,9 @@ "@mui/lab": "6.0.0-beta.28", "@mui/material": "6.4.5", "@mui/x-charts": "^7.5.1", + "@reduxjs/toolkit": "2.6.0", "@mui/x-data-grid": "7.27.0", "@mui/x-date-pickers": "7.27.0", - "@reduxjs/toolkit": "2.6.0", "@solana/wallet-adapter-base": "0.9.23", "@solana/wallet-adapter-material-ui": "0.16.34", "@solana/wallet-adapter-react": "0.15.35", @@ -32,16 +32,18 @@ "dayjs": "1.11.13", "flag-icons": "7.3.2", "html2canvas": "^1.4.1", + "maplibre-gl": "5.1.1", "i18next": "^24.2.2", "immutability-helper": "^3.1.1", "joi": "17.13.3", - "maplibre-gl": "5.1.1", + "jwt-decode": "^4.0.0", "mui-color-input": "^5.0.1", "react": "18.3.1", "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", "react-dom": "^18.2.0", "react-i18next": "^15.4.0", + "react-icons": "5.4.0", "react-redux": "9.2.0", "react-router": "^6.23.0", "react-router-dom": "^6.23.1", diff --git a/src/Components/Buttons/RoundGradientButton.jsx b/src/Components/Buttons/RoundGradientButton.jsx new file mode 100644 index 000000000..f9e14735c --- /dev/null +++ b/src/Components/Buttons/RoundGradientButton.jsx @@ -0,0 +1,30 @@ +import React from "react"; +import Button from "@mui/material/Button"; +import { styled } from "@mui/material/styles"; + +const RoundGradientButton = styled(Button)(({ theme }) => ({ + position: "relative", + border: "5px solid transparent", + backgroundClip: "padding-box", + borderRadius: 30, + fontSize: "1.2rem", + color: theme.palette.primary.contrastText, + backgroundColor: theme.palette.background.main, + + "&:after": { + position: "absolute", + top: -3, + left: -3, + right: -3, + bottom: -3, + background: + theme.palette.mode === "dark" + ? "linear-gradient(90deg, #842bd2, #ff5451, #8c52ff)" + : "linear-gradient(90deg, #842bd2, #ff5451, #8c52ff)", + content: '""', + zIndex: -1, + borderRadius: 30, + }, +})); + +export default RoundGradientButton; diff --git a/src/Components/Charts/DePINStatusPageBarChart/index.jsx b/src/Components/Charts/DePINStatusPageBarChart/index.jsx new file mode 100644 index 000000000..65c6278f1 --- /dev/null +++ b/src/Components/Charts/DePINStatusPageBarChart/index.jsx @@ -0,0 +1,181 @@ +// Components +import { Stack, Box, Tooltip, Typography } from "@mui/material"; + +// Utils +import { useTheme } from "@emotion/react"; +import { useState, useEffect } from "react"; +import PropTypes from "prop-types"; +import { formatDateWithTz } from "../../../Utils/timeUtils"; +import { useSelector } from "react-redux"; + +const PlaceholderCheck = ({ daysToShow }) => { + const theme = useTheme(); + + return ( + + ); +}; + +PlaceholderCheck.propTypes = { + daysToShow: PropTypes.number, +}; + +const Check = ({ check, daysToShow }) => { + const [animate, setAnimate] = useState(false); + + const theme = useTheme(); + useEffect(() => { + setAnimate(true); + }, []); + const uiTimezone = useSelector((state) => state.ui.timezone); + + return ( + + + {formatDateWithTz(check._id, "ddd, MMMM D, YYYY", uiTimezone)} + + + + + Uptime percentage + + + {check.upPercentage.toFixed(2)} + + {" "} + % + + + + + + } + placement="top" + key={`check-${check?._id}`} + slotProps={{ + popper: { + className: "bar-tooltip", + modifiers: [ + { + name: "offset", + options: { + offset: [0, -10], + }, + }, + ], + sx: { + "& .MuiTooltip-tooltip": { + backgroundColor: theme.palette.secondary.main, + border: 1, + borderColor: theme.palette.primary.lowContrast, + borderRadius: theme.shape.borderRadius, + boxShadow: theme.shape.boxShadow, + px: theme.spacing(4), + py: theme.spacing(3), + }, + "& .MuiTooltip-tooltip p": { + /* TODO Font size should point to theme */ + fontSize: 12, + color: theme.palette.secondary.contrastText, + fontWeight: 500, + }, + "& .MuiTooltip-tooltip span": { + /* TODO Font size should point to theme */ + fontSize: 11, + color: theme.palette.secondary.contrastText, + fontWeight: 600, + }, + }, + }, + }} + > + + + + + ); +}; + +Check.propTypes = { + check: PropTypes.object, + daysToShow: PropTypes.number, +}; + +const DePINStatusPageBarChart = ({ checks = [], daysToShow = 30 }) => { + if (checks.length !== daysToShow) { + const placeholders = Array(daysToShow - checks.length).fill("placeholder"); + checks = [...checks, ...placeholders]; + } + return ( + + {checks.map((check) => { + if (check === "placeholder") { + return ( + + ); + } + return ( + + ); + })} + + ); +}; + +DePINStatusPageBarChart.propTypes = { + checks: PropTypes.array, + daysToShow: PropTypes.number, +}; + +export default DePINStatusPageBarChart; diff --git a/src/Components/Common/AppBar.jsx b/src/Components/Common/AppBar.jsx new file mode 100644 index 000000000..df0660cf5 --- /dev/null +++ b/src/Components/Common/AppBar.jsx @@ -0,0 +1,216 @@ +import { useState } from "react"; +import { styled, alpha } from "@mui/material/styles"; +import Box from "@mui/material/Box"; +import AppBar from "@mui/material/AppBar"; +import Toolbar from "@mui/material/Toolbar"; +import Button from "@mui/material/Button"; +import IconButton from "@mui/material/IconButton"; +import Container from "@mui/material/Container"; +import MenuItem from "@mui/material/MenuItem"; +import Drawer from "@mui/material/Drawer"; +import MenuIcon from "@mui/icons-material/Menu"; +import CloseRoundedIcon from "@mui/icons-material/CloseRounded"; +import ThemeSwitch from "../ThemeSwitch"; +import { useTheme } from "@mui/material/styles"; +import { useSelector } from "react-redux"; +import { useLocation, useNavigate } from "react-router-dom"; + +const StyledToolbar = styled(Toolbar)(({ theme, mode }) => ({ + display: "flex", + alignItems: "center", + justifyContent: "space-between", + flexShrink: 0, + borderRadius: `calc(${theme.shape.borderRadius}px + 4px)`, + backdropFilter: "blur(24px)", + border: "1px solid", + borderColor: + mode === "light" + ? alpha(theme.palette.common.black, 0.1) + : alpha(theme.palette.common.white, 0.1), + backgroundColor: + mode === "light" + ? alpha(theme.palette.common.white, 0.4) + : alpha(theme.palette.common.black, 0.4), + boxShadow: theme.shadows[3], + padding: "8px 12px", +})); + +const StyledMenuItem = styled(MenuItem)(({ theme }) => ({ + fontSize: "1.1rem", + margin: theme.spacing(4, 2), +})); + +const AppAppBar = () => { + const [open, setOpen] = useState(false); + const theme = useTheme(); + const mode = useSelector((state) => state.ui.mode); + const location = useLocation(); + const navigate = useNavigate(); + + // Debugging: Log the current theme mode + console.log("Current theme mode:", mode); + + const logoSrc = + mode === "light" ? "/images/prism-black.png" : "/images/prism-white.png"; + + const toggleDrawer = (newOpen) => () => { + setOpen(newOpen); + }; + + const handleScroll = (id) => { + if (location.pathname === "/") { + const element = document.getElementById(id); + if (element) { + element.scrollIntoView({ behavior: "smooth" }); + } + } else { + navigate(`/#${id}`); + } + }; + + return ( + + + + + Prism Logo + + + + + + + + + {/* + */} + + + + + + + + + + + + + + Features + Testimonials + Highlights + FAQ + + Blog + + {/* + + + + + */} + + + + + + + + ); +}; + +export default AppAppBar; diff --git a/src/Components/Common/Footer.jsx b/src/Components/Common/Footer.jsx new file mode 100644 index 000000000..4c33512be --- /dev/null +++ b/src/Components/Common/Footer.jsx @@ -0,0 +1,214 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Container from '@mui/material/Container'; +import IconButton from '@mui/material/IconButton'; +import Link from '@mui/material/Link'; +import Stack from '@mui/material/Stack'; +import Typography from '@mui/material/Typography'; +import { FaFacebook, FaLinkedin, FaGithub, FaTwitter, FaEnvelope } from 'react-icons/fa'; + + +function Copyright() { + return ( + + {'Copyright © '} + + UpRock + +   + {new Date().getFullYear()} + + ); +} + +export default function Footer() { + return ( + + + +
+ + Privacy Policy + + +  •  + + + Terms of Service + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + Made with ❤️ by  + + UpRock  + + &  + + Bluewave Labs + + + + + Built on  + + + + + + + + + + + + + + + + + + + + +  Solana + + + +
+ ); +} diff --git a/src/Components/Dot/index.jsx b/src/Components/Dot/index.jsx index 0fd51730f..0676d0a6f 100644 --- a/src/Components/Dot/index.jsx +++ b/src/Components/Dot/index.jsx @@ -1,6 +1,6 @@ import PropTypes from "prop-types"; -const Dot = ({ color = "gray", size = "4px" }) => { +const Dot = ({ color = "gray", size = "4px", style }) => { return ( { borderRadius: "50%", backgroundColor: color, opacity: 0.8, + ...style, }} /> ); diff --git a/src/Components/Home/ArcadeEmbed.jsx b/src/Components/Home/ArcadeEmbed.jsx new file mode 100644 index 000000000..4a522874d --- /dev/null +++ b/src/Components/Home/ArcadeEmbed.jsx @@ -0,0 +1,17 @@ +import React from 'react'; + +export function ArcadeEmbed() { + return ( +
+