import PropTypes from "prop-types"; import PageSpeedIcon from "../../assets/icons/page-speed.svg?react"; import { StatusLabel } from "../../Components/Label"; import { Box, Grid, Stack, Typography } from "@mui/material"; import { useNavigate } from "react-router"; import { useTheme } from "@emotion/react"; import { IconBox } from "./Details/styled"; import { Area, AreaChart, CartesianGrid, ResponsiveContainer, Tooltip } from "recharts"; import { useSelector } from "react-redux"; import { formatDateWithTz, formatDurationSplit } from "../../Utils/timeUtils"; import useUtils from "../Monitors/utils"; import { useState } from "react"; /** * CustomToolTip displays a tooltip with formatted date and score information. * @param {Object} props * @param {Array} props.payload - Data to display in the tooltip * @returns {JSX.Element} The rendered tooltip component */ const CustomToolTip = ({ payload }) => { const theme = useTheme(); const uiTimezone = useSelector((state) => state.ui.timezone); return ( {formatDateWithTz( payload[0]?.payload.createdAt, "ddd, MMMM D, YYYY, h:mm A", uiTimezone )} {payload[0]?.name} {" "} {payload[0]?.payload.score} ); }; CustomToolTip.propTypes = { payload: PropTypes.array, }; /** * Processes the raw data to include a score for each entry. * @param {Array} data - The raw data array. * @returns {Array} - The formatted data array with scores. */ const processData = (data) => { if (data.length === 0) return []; let formattedData = []; const calculateScore = (entry) => { return ( (entry.accessibility + entry.bestPractices + entry.performance + entry.seo) / 4 ); }; data.forEach((entry) => { entry = { ...entry, score: calculateScore(entry) }; formattedData.push(entry); }); return formattedData; }; /** * Renders an area chart displaying page speed scores. * @param {Object} props * @param {Array} props.data - The raw data to be displayed in the chart. * @param {string} props.status - The status of the page speed which determines the chart's color scheme. * @returns {JSX.Element} - The rendered area chart. */ const PagespeedAreaChart = ({ data, status }) => { const theme = useTheme(); const [isHovered, setIsHovered] = useState(false); const { pagespeedStyles } = useUtils(); const formattedData = processData(data); return ( setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} > } /> ); }; PagespeedAreaChart.propTypes = { data: PropTypes.arrayOf( PropTypes.shape({ accessibility: PropTypes.number.isRequired, bestPractices: PropTypes.number.isRequired, performance: PropTypes.number.isRequired, seo: PropTypes.number.isRequired, }) ).isRequired, status: PropTypes.string.isRequired, }; /** * Renders a card displaying monitor details and an area chart. * @param {Object} props * @param {Object} props.monitor - The monitor data to be displayed in the card. * @returns {JSX.Element} - The rendered card. */ const Card = ({ monitor }) => { const { determineState, pagespeedStatusMsg } = useUtils(); const theme = useTheme(); const navigate = useNavigate(); const monitorState = determineState(monitor); return ( navigate(`/pagespeed/${monitor._id}`)} border={1} borderColor={theme.palette.border.light} borderRadius={theme.shape.borderRadius} backgroundColor={theme.palette.background.main} sx={{ display: "grid", gridTemplateColumns: "34px 2fr 1fr", columnGap: theme.spacing(5), gridTemplateRows: "34px 1fr 3fr", cursor: "pointer", "&:hover": { backgroundColor: theme.palette.background.accent, }, "& path": { transition: "stroke-width 400ms ease", }, }} > {monitor.name} {monitor.url} Checking every{" "} {(() => { const { time, format } = formatDurationSplit(monitor?.interval); return ( <> {time}{" "} {format} ); })()} ); }; Card.propTypes = { monitor: PropTypes.object.isRequired, }; export default Card;