frontend/src/bin/graphs/BinWaterLevel.tsx
2025-05-23 11:07:34 -06:00

145 lines
4.5 KiB
TypeScript

import { Box, InputAdornment, TextField, Typography } from "@mui/material";
import WaterLevelChart, { DataPoint } from "charts/WaterLevelChart";
import { DateRange } from "common/time/DateRange";
import { WaterContent } from "grain";
import { Bin } from "models";
import moment from "moment";
import { useBinAPI, useGlobalState } from "providers";
import React, { useEffect, useState } from "react";
interface Props {
bin: Bin;
// range: DateRange;
start: string,
end: string,
plenumKey: string;
cableKey: string;
pressureKey: string;
fanKey?: string;
returnLast: (lastWater: DataPoint | undefined) => void;
newXDomain?: number[] | string[];
multiGraphZoom?: (domain: number[] | string[]) => void;
multiGraphZoomOut?: boolean;
}
export default function BinWaterLevel(props: Props) {
const {
bin,
//range,
start,
end,
plenumKey,
cableKey,
pressureKey,
fanKey,
newXDomain,
multiGraphZoom,
multiGraphZoomOut,
returnLast
} = props;
const binAPI = useBinAPI();
const [chartData, setChartData] = useState<DataPoint[]>([]);
const grainMoisture = bin.settings.inventory?.initialMoisture ?? 0;
const [targetMoisture, setTargetMoisture] = useState(
bin.settings.inventory?.targetMoisture.toString() ?? ""
);
const [reference, setReference] = useState(0);
const [{ as }] = useGlobalState();
const [loading, setLoading] = useState(false);
useEffect(() => {
if (bin.settings.inventory) {
let moisture = isNaN(parseFloat(targetMoisture)) ? 0 : parseFloat(targetMoisture);
setReference(
WaterContent(
bin.settings.inventory.grainType,
bin.settings.inventory.grainBushels,
moisture
)
);
}
}, [targetMoisture, bin]);
useEffect(() => {
if (!isNaN(grainMoisture) && plenumKey && cableKey) {
if (!loading) {
setLoading(true);
binAPI
.listBinLiters(
bin.key(),
start,
end,
grainMoisture,
//(note: the variable needs to be the device the component belongs to and then the component key ie. "10:LTe7Q1sT5g65")
plenumKey,
cableKey,
pressureKey,
fanKey,
as
)
.then(resp => {
let lastData: DataPoint | undefined;
let data: DataPoint[] = [];
if (resp.data.liters) {
resp.data.liters.forEach(l => {
let newPoint: DataPoint = {
liters: l.liters ?? 0,
timestamp: moment(l.time).valueOf()
};
data.push(newPoint);
if (!lastData || lastData.timestamp < newPoint.timestamp) {
lastData = newPoint;
}
});
}
returnLast(lastData);
setChartData(data);
setLoading(false);
});
}
}
}, [binAPI, start, end, bin, grainMoisture, plenumKey, cableKey, pressureKey, as]); // eslint-disable-line react-hooks/exhaustive-deps
return (
<React.Fragment>
<Box paddingY={1}>
{chartData.length > 0 ? (
<React.Fragment>
<TextField
style={{ marginBottom: 10 }}
variant="outlined"
fullWidth
value={targetMoisture}
error={isNaN(+targetMoisture) && targetMoisture !== ""}
onChange={e => setTargetMoisture(e.target.value)}
label="Target Moisture"
helperText={isNaN(+targetMoisture) && targetMoisture !== "" ? "Invalid number" : ""}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<InputAdornment position="end">% WB</InputAdornment>
</InputAdornment>
)
}}
/>
<WaterLevelChart
data={chartData}
reference={reference}
newXDomain={newXDomain}
multiGraphZoom={multiGraphZoom}
multiGraphZoomOut={multiGraphZoomOut}
/>
</React.Fragment>
) : (
<Box display="flex" justifyContent="center" alignItems="center">
{isNaN(grainMoisture) && (
<Typography variant="subtitle1" color="textSecondary" align="center">
Set initial moisture in the bin settings to calculate estimated water content
</Typography>
)}
</Box>
)}
</Box>
</React.Fragment>
);
}