import React, { useState, useEffect } from 'react'; import { Bar } from 'react-chartjs-2'; import { useTranslation } from 'react-i18next'; import { BigNumber } from 'ethers'; import { moment, formatDate } from '../../../utils/time'; import { Button, ButtonGroup, makeStyles, createStyles, useTheme } from '@material-ui/core'; import { reverse } from '../../../utils/helper'; import { EnergyFormatter } from '../../../utils/EnergyFormatter'; import { useOriginConfiguration } from '../../../utils/configuration'; import { IOriginDevice } from '../../../types'; enum TIMEFRAME { DAY = 'Day', WEEK = 'Week', MONTH = 'Month', YEAR = 'Year' } const DEFAULT_TIMEFRAME = TIMEFRAME.MONTH; interface ISmartMeterReadingsChartProps { device: IOriginDevice; } export function SmartMeterReadingsChart(props: ISmartMeterReadingsChartProps) { const { device } = props; const originConfiguration = useOriginConfiguration(); const originBgColor = originConfiguration?.styleConfig?.MAIN_BACKGROUND_COLOR; const useStyles = makeStyles(() => createStyles({ selected: { backgroundColor: originBgColor } }) ); const classes = useStyles(useTheme()); const { t } = useTranslation(); const [selectedTimeFrame, setSelectedTimeFrame] = useState({ timeframe: DEFAULT_TIMEFRAME, endDate: moment().toDate() }); const [readings, setReadings] = useState([]); useEffect(() => { if (device) { setReadings(device.smartMeterReads); } }, [device]); const graphOptions = { maintainAspectRatio: false, scales: { yAxes: [ { ticks: { beginAtZero: true } } ] }, tooltips: { callbacks: { label: (tooltipItem, data) => { const tooltipValue = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index]; return parseInt(tooltipValue, 10).toLocaleString(); } } } }; const endDateInTimezone = moment(selectedTimeFrame?.endDate).tz(device.timezone).clone(); function changeSelectedTimeFrame(increment = true) { const { timeframe } = selectedTimeFrame; let measurementUnit; if (timeframe === TIMEFRAME.DAY) { measurementUnit = 'day'; } else if (timeframe === TIMEFRAME.WEEK) { measurementUnit = 'week'; } else if (timeframe === TIMEFRAME.MONTH) { measurementUnit = 'month'; } else { measurementUnit = 'year'; } const currentDate = endDateInTimezone; const newEndDate = increment ? currentDate.add(1, measurementUnit) : currentDate.subtract(1, measurementUnit); setSelectedTimeFrame({ timeframe, endDate: newEndDate.toDate() }); } function getFormattedReadings() { const formatted = []; let measurementUnit; let amount; let keyFormat; let chartEndDate; switch (selectedTimeFrame.timeframe) { case TIMEFRAME.DAY: measurementUnit = 'hour'; amount = 24; keyFormat = 'HH'; chartEndDate = endDateInTimezone.endOf('day'); break; case TIMEFRAME.WEEK: measurementUnit = 'day'; amount = 7; keyFormat = 'ddd D MMM'; chartEndDate = endDateInTimezone.endOf('week'); break; case TIMEFRAME.MONTH: measurementUnit = 'day'; amount = endDateInTimezone.daysInMonth(); keyFormat = 'D MMM'; chartEndDate = endDateInTimezone.endOf('month'); break; case TIMEFRAME.YEAR: measurementUnit = 'month'; amount = 12; keyFormat = 'MMM'; chartEndDate = endDateInTimezone.endOf('year'); } let currentIndex = 0; while (currentIndex < amount) { const currentDate = chartEndDate .clone() .subtract(currentIndex, measurementUnit) .tz(device.timezone); let totalEnergy = BigNumber.from(0); for (const reading of readings) { const readingDate = moment.unix(reading.timestamp).tz(device.timezone); if (readingDate.isSame(currentDate, measurementUnit)) { totalEnergy = totalEnergy.add(reading.meterReading); } } formatted.push({ label: measurementUnit !== 'hour' ? currentDate.format(keyFormat) : `${currentDate.format(keyFormat)}:00`, color: originConfiguration?.styleConfig?.PRIMARY_COLOR, value: EnergyFormatter.getValueInDisplayUnit(totalEnergy) }); currentIndex += 1; } return reverse(formatted); } function getCurrentRangeInfo(): string { const { timeframe } = selectedTimeFrame; if (timeframe === TIMEFRAME.WEEK) { return `${formatDate(endDateInTimezone.startOf('week'))} - ${formatDate( endDateInTimezone.endOf('week') )}`; } else if (timeframe === TIMEFRAME.MONTH) { return endDateInTimezone.format('MMM YYYY'); } else if (timeframe === TIMEFRAME.YEAR) { return endDateInTimezone.format('YYYY'); } return formatDate(endDateInTimezone); } const currentRangeInfo = getCurrentRangeInfo(); const formattedReadings = getFormattedReadings(); const data = { labels: formattedReadings.map((entry) => entry.label), datasets: [ { label: t('meterReads.properties.energy', { unit: EnergyFormatter.displayUnit }), backgroundColor: formattedReadings.map((entry) => entry.color), data: formattedReadings.map((entry) => entry.value) } ] }; const timeFrameButtons = Object.keys(TIMEFRAME).map((timeframe, index) => { const onClick = () => setSelectedTimeFrame({ timeframe: TIMEFRAME[timeframe], endDate: moment().toDate() }); const isCurrentlySelected = selectedTimeFrame.timeframe === TIMEFRAME[timeframe]; return ( ); }); (graphOptions as any).title = { display: true, text: currentRangeInfo }; return (
changeSelectedTimeFrame(false)} > {'<'}
{timeFrameButtons}
changeSelectedTimeFrame(true)} > {'>'}
); }