import React from "react"; import {addHours, subHours} from "date-fns"; import {aqiSensorColorGradient, pmSensorColorGradient} from "../../common/ColorGradient"; import {BLACK_CSS, formatTimestamp, range, roundTo} from "../../common/Helpers"; import {getPMHistory} from "../../common/FrostApiProxy"; import {Typography} from "@material-ui/core"; import {CartesianGrid, Legend, Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis} from "recharts"; import {PopupDataInfo} from "./Popup"; import {PopupGrid, PopupGridItem} from "./PopupGrid"; type DateValue = { timestamp: number; value: number; } type PMPopupState = { chartData?: DateValue[]; isLoading: boolean; fromDate: Date, toDate: Date, } type PMPopupProps = { info: PopupDataInfo; } export class PMPopupContent extends React.Component { constructor(props: PMPopupProps) { super(props); let {fromDate, toDate} = this.props.info.dateFilter; if (!fromDate && !toDate) { toDate = new Date(); fromDate = subHours(toDate, 24); } else if (!fromDate && toDate) { fromDate = subHours(toDate, 24); } else if (fromDate && !toDate) { toDate = addHours(fromDate, 24); } this.state = { isLoading: false, fromDate: fromDate!, toDate: toDate!, }; } componentDidMount() { if (!this.state.isLoading && !this.state.chartData) { this.loadHistoryData(); } } private getGridItems(): PopupGridItem[] { const {pmInfo} = this.props.info; const textColor = pmSensorColorGradient.getColorAtAsCssHex( pmInfo?.pm, BLACK_CSS, true ); const aqiTextColor = aqiSensorColorGradient.getColorAtAsCssHex( pmInfo?.aqiValue, BLACK_CSS, true ); const averageStr = this.props.info.isFiltered ? " Average" : ""; return [ {key: "Sensor Type", value: "SDS 011"}, {key: "Description", value: pmInfo?.description}, {key: "Longitude", value: pmInfo?.longitude}, {key: "Latitude", value: pmInfo?.latitude}, {key: "PM2.5" + averageStr, value: roundTo(pmInfo?.pm), textColor, unit: "µg/m³"}, {key: "AQI", value: `${roundTo(pmInfo?.aqiValue)} (${pmInfo?.aqiRange?.name})`, textColor: aqiTextColor}, ]; } private getChartTitle(): string { const {fromDate, toDate} = this.props.info.dateFilter; const parts = []; if (fromDate || toDate) { const dateTimeFormat = "dd.MM.yyyy HH:mm"; const dayFormat = "dd.MM.yyyy"; if (fromDate && toDate && fromDate.getHours() === 0 && toDate.getHours() === 23) { parts.push(`for ${formatTimestamp(this.state.fromDate.getTime(), dayFormat)}`); } else { parts.push(`from ${formatTimestamp(this.state.fromDate.getTime(), dateTimeFormat)}`); parts.push(`to ${formatTimestamp(this.state.toDate.getTime(), dateTimeFormat)}`); } } const period = parts.length ? parts.join(" ") : "for the last 24 hours"; return `Emission rates ${period}`; } private loadHistoryData() { this.setState({isLoading: true}); setTimeout(() => { const {id} = this.props.info.pmInfo!; const {fromDate, toDate} = this.state; getPMHistory(+id, fromDate!, toDate!) .then(data => { this.setState({ chartData: data.map(it => ({timestamp: it.phenomenonTime.getTime(), value: it.result})), isLoading: false }); }); }, 100); } private getMinMaxValues() { const minValue = this.state.chartData ? Math.min(...this.state.chartData.map(d => d.value)) : 0; const maxValue = this.state.chartData ? Math.max(...this.state.chartData.map(d => d.value)) : 0; return {minValue, maxValue}; } render() { const {minValue, maxValue} = this.getMinMaxValues(); return
{this.getChartTitle()}
{this.state.isLoading ? "Loading..." : {range(0, 1, 10).map(v => )} formatTimestamp(timestamp)}/> Math.max(dataMax, 100)]} tickCount={5} tickFormatter={pm => roundTo(pm)?.toString() || ""}/> formatTimestamp(timestamp, "dd.MM.yyyy HH:mm")} formatter={(pm: number) => pm + " µg/m³"} /> () } /> }
; } }