124 lines
No EOL
3.8 KiB
TypeScript
124 lines
No EOL
3.8 KiB
TypeScript
import { Box, Grid2, Theme, Tooltip, Typography } from "@mui/material";
|
|
import { blue, orange } from "@mui/material/colors";
|
|
import { makeStyles } from "@mui/styles";
|
|
import { Device } from "models";
|
|
import PulseBox from "./PulseBox";
|
|
import { or } from "utils";
|
|
import { useEffect, useState } from "react";
|
|
|
|
interface Props {
|
|
device: Device
|
|
}
|
|
|
|
const useStyles = makeStyles((theme: Theme) => {
|
|
const lightMode = theme.palette?.mode === "light";
|
|
return ({
|
|
box: {
|
|
display: "inline-block",
|
|
borderRadius: "6px",
|
|
backgroundColor: lightMode ? "rgb(210, 210, 210)" : "rgb(50, 50, 50)",
|
|
padding: theme.spacing(0.75),
|
|
marginRight: "auto",
|
|
margin: theme.spacing(1),
|
|
},
|
|
})
|
|
})
|
|
|
|
export default function StatusPlenum(props: Props) {
|
|
const { device } = props;
|
|
const classes = useStyles()
|
|
|
|
const colors = or(device.status.plenum?.overlays.map(overlay => overlay.color), []);
|
|
const messages = or(device.status.plenum?.overlays.map(overlay => overlay.message), []);
|
|
|
|
const [color, setColor] = useState(colors.length > 0 ? colors[0] : "");
|
|
const [, setColorIndex] = useState(0)
|
|
|
|
useEffect(() => {
|
|
const interval = setInterval(() => {
|
|
setColorIndex(prevIndex => {
|
|
const newIndex = prevIndex >= colors.length - 1 ? 0 : prevIndex + 1;
|
|
setColor(colors[newIndex]); // Use the new index here
|
|
return newIndex;
|
|
});
|
|
}, 5000);
|
|
|
|
return () => clearInterval(interval);
|
|
}, []);
|
|
|
|
const tooltip = () => {
|
|
if (messages.length === 0) return null
|
|
if (messages.length < 2) return (
|
|
messages[0]
|
|
)
|
|
return (
|
|
<Grid2 container direction={"column"}>
|
|
<Grid2 container direction="row">
|
|
<Typography fontWeight={"bold"} variant="caption">
|
|
Overlay Messages
|
|
</Typography>
|
|
</Grid2>
|
|
{messages.map((message, index) => {
|
|
return (
|
|
<Grid2 key={"tooltip-overly-message-" + message} container direction="row" alignItems={"center"}>
|
|
<Box
|
|
sx={{
|
|
width: 10, // Size of the square
|
|
height: 10,
|
|
backgroundColor: colors[index], // Passed color prop
|
|
borderRadius: 1, // Optional: slight rounding, remove for sharp square
|
|
border: "1px solid black",
|
|
}}
|
|
/>
|
|
<Typography variant="caption" sx={{ marginLeft: 1 }}>
|
|
{message}
|
|
</Typography>
|
|
</Grid2>
|
|
)
|
|
})}
|
|
</Grid2>
|
|
)
|
|
}
|
|
|
|
function compareTimestamps(timestamp1: string, timestamp2: string): number {
|
|
const date1 = new Date(timestamp1);
|
|
const date2 = new Date(timestamp2);
|
|
|
|
// Check if dates are valid
|
|
if (isNaN(date1.getTime()) || isNaN(date2.getTime())) {
|
|
throw new Error("Invalid RFC3339 timestamp format");
|
|
}
|
|
|
|
// Compare using getTime() for millisecond precision
|
|
return date1.getTime() - date2.getTime();
|
|
}
|
|
|
|
if (device.status.plenum?.timestamp) {
|
|
const now = new Date();
|
|
const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
|
|
if (compareTimestamps(device.status.plenum?.timestamp, oneDayAgo.toISOString()) < 0) {
|
|
return null
|
|
}
|
|
} else {
|
|
return null
|
|
}
|
|
|
|
return (
|
|
<Tooltip title={tooltip()}>
|
|
<PulseBox color={color} className={classes.box} >
|
|
<Grid2 container direction="column" >
|
|
<Grid2>
|
|
<Typography variant="body2" style={{ color: orange[700]}}>
|
|
{device.status.plenum?.temperature.toFixed(1)}°C
|
|
</Typography>
|
|
</Grid2>
|
|
<Grid2>
|
|
<Typography variant="body2" style={{ color: blue[700]}}>
|
|
{device.status.plenum?.humidity.toFixed(1)}%
|
|
</Typography>
|
|
</Grid2>
|
|
</Grid2>
|
|
</PulseBox>
|
|
</Tooltip>
|
|
)
|
|
} |