ag visual farm added to the dev branch field related stuff not imported yet, and the geocoder has some bugs with the new version
This commit is contained in:
parent
b4da0d6859
commit
022925d7d7
41 changed files with 8895 additions and 79 deletions
833
src/bin/BinyardDisplay.tsx
Normal file
833
src/bin/BinyardDisplay.tsx
Normal file
|
|
@ -0,0 +1,833 @@
|
|||
import {
|
||||
Accordion,
|
||||
AccordionDetails,
|
||||
AccordionSummary,
|
||||
Box,
|
||||
Button,
|
||||
Checkbox,
|
||||
Chip,
|
||||
darken,
|
||||
Divider,
|
||||
FormControl,
|
||||
FormControlLabel,
|
||||
Grid2 as Grid,
|
||||
ImageList as GridList,
|
||||
ImageListItem as GridListTile,
|
||||
InputLabel,
|
||||
Menu,
|
||||
MenuItem,
|
||||
Select,
|
||||
Skeleton,
|
||||
Theme,
|
||||
Typography,
|
||||
useTheme
|
||||
} from "@mui/material";
|
||||
import { green, yellow } from "@mui/material/colors";
|
||||
import { makeStyles } from "@mui/styles";
|
||||
import { ArrowBackIos, ArrowForwardIos, ExpandMore, MoreVert } from "@mui/icons-material";
|
||||
//import { Skeleton } from "@material-ui/lab";
|
||||
import BinInventoryChart, { GrainAmount } from "charts/BinInventoryChart";
|
||||
import BinUtilizationChart from "charts/BinUtilizationChart";
|
||||
//import QrCodeGenerator, { QrCodeKey } from "common/QrCodeGenerator";
|
||||
import GrainDescriber, { grainName } from "grain/GrainDescriber";
|
||||
import { useMobile, useWidth } from "hooks";
|
||||
import { Bin } from "models";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
import { useBinAPI, useGlobalState } from "providers";
|
||||
import React, { useEffect, useState, useCallback, SetStateAction } from "react";
|
||||
import { getGrainUnit, stringToMaterialColour } from "utils";
|
||||
//import BinsFansStatusTable from "./BinFansStatusTable";
|
||||
import BinsList from "./BinsList";
|
||||
|
||||
interface Props {
|
||||
yardKey: string;
|
||||
insert?: boolean;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
"@keyframes pulsate": {
|
||||
to: {
|
||||
boxShadow: "0 0 0 16px" + yellow["500"] + "00"
|
||||
}
|
||||
},
|
||||
green: {
|
||||
color: green["500"],
|
||||
"&:hover": {
|
||||
color: green["600"]
|
||||
}
|
||||
},
|
||||
gridList: {
|
||||
width: "100%",
|
||||
flexWrap: "nowrap",
|
||||
transform: "translateZ(0)"
|
||||
},
|
||||
pulse: {
|
||||
boxShadow: "0 0 0 0 " + yellow["500"] + "75",
|
||||
animation: "$pulsate 1.75s infinite cubic-bezier(0.66, 0.33, 0, 1)"
|
||||
},
|
||||
icon: {
|
||||
padding: 6,
|
||||
width: 36,
|
||||
height: 36,
|
||||
borderRadius: "18px",
|
||||
background: "rgba(0,0,0,0)",
|
||||
"&:hover": {
|
||||
background:
|
||||
"radial-gradient(closest-side, rgba(150, 150, 150, 0.5) 50%, rgba(150, 150, 150, 0.5))"
|
||||
}
|
||||
},
|
||||
accordion: {
|
||||
background: darken(theme.palette.background.paper, 0.4)
|
||||
}
|
||||
}));
|
||||
|
||||
export default function BinyardDisplay(props: Props) {
|
||||
const { yardKey, insert } = props;
|
||||
const classes = useStyles();
|
||||
const binAPI = useBinAPI();
|
||||
const theme = useTheme();
|
||||
const width = useWidth();
|
||||
const isMobile = useMobile();
|
||||
const [carouselIndex, setCarouselIndex] = useState(0);
|
||||
const [binMenuAnchorEl, setBinMenuAnchorEl] = useState<Element | null>(null);
|
||||
const [{ as }] = useGlobalState();
|
||||
const maxBins = 40;
|
||||
const [binsLoading, setBinsLoading] = useState(false);
|
||||
const [expandTotal, setExpandTotal] = useState(false);
|
||||
const [displayedInventory, setDisplayedInventory] = useState<GrainAmount[]>([]);
|
||||
const [displayedFertilizer, setDisplayedFertilizer] = useState<GrainAmount[]>([]);
|
||||
const [expandUtilization, setExpandUtilization] = useState(false);
|
||||
const [expandFanTable, setExpandFanTable] = useState(false);
|
||||
const [displayGrain, setDisplayGrain] = useState(true);
|
||||
const [displayFert, setDisplayFert] = useState(false);
|
||||
const [displayEmpty, setDisplayEmpty] = useState(false);
|
||||
const [yardBins, setYardBins] = useState<Bin[]>([]);
|
||||
const [grainBins, setGrainBins] = useState<Bin[]>([]);
|
||||
const [fertBins, setFertBins] = useState<Bin[]>([]);
|
||||
const [emptyBins, setEmptyBins] = useState<Bin[]>([]);
|
||||
const [binTotal, setBinTotal] = useState(0);
|
||||
const [binMetrics, setBinMetrics] = useState<pond.BinMetrics>();
|
||||
const [contentFilter, setContentFilter] = useState<string>("");
|
||||
const [totalFanControllers, setTotalFanControllers] = useState(0);
|
||||
const [totalFanControllersOn, setTotalFanControllersOn] = useState(0);
|
||||
const [openQrGenerator, setOpenQrGenerator] = useState(false);
|
||||
const [order, setOrder] = useState<"asc" | "desc">("asc");
|
||||
const [orderBy, setOrderBy] = useState<string>("name");
|
||||
|
||||
//const [qrKeyList, setQrKeyList] = useState<QrCodeKey[]>([]);
|
||||
|
||||
const [scrollTranslations, setScrollTranslations] = useState({
|
||||
bins: 0,
|
||||
empty: 0,
|
||||
fertilizer: 0
|
||||
});
|
||||
|
||||
const loadBins = useCallback(() => {
|
||||
setBinsLoading(true);
|
||||
//load the bins based on the yard key
|
||||
binAPI
|
||||
.listBinsAndData(maxBins, 0, "asc", "name", undefined, as, undefined, [yardKey], ["binyard"])
|
||||
.then(resp => {
|
||||
let yardBins: Bin[] = [];
|
||||
let grainBins: Bin[] = [];
|
||||
let fertBins: Bin[] = [];
|
||||
let emptyBins: Bin[] = [];
|
||||
//let qr: QrCodeKey[] = [];
|
||||
//set the list of bins into the yard bins
|
||||
resp.data.bins.forEach(b => {
|
||||
let bin = Bin.any(b);
|
||||
yardBins.push(bin);
|
||||
if (bin.empty()) {
|
||||
emptyBins.push(bin);
|
||||
} else if (bin.storage() === pond.BinStorage.BIN_STORAGE_FERTILIZER) {
|
||||
fertBins.push(bin);
|
||||
} else {
|
||||
grainBins.push(bin);
|
||||
}
|
||||
//build qr keys here
|
||||
// qr.push({
|
||||
// key: bin.key(),
|
||||
// name: bin.name()
|
||||
// });
|
||||
});
|
||||
setYardBins(yardBins);
|
||||
setBinTotal(resp.data.total);
|
||||
//setQrKeyList(qr);
|
||||
setGrainBins(grainBins);
|
||||
if (fertBins.length > 0) {
|
||||
setDisplayFert(true);
|
||||
}
|
||||
if (emptyBins.length > 0) {
|
||||
setDisplayEmpty(true);
|
||||
}
|
||||
setFertBins(fertBins);
|
||||
setEmptyBins(emptyBins);
|
||||
setBinsLoading(false);
|
||||
|
||||
let metrics = pond.BinMetrics.fromObject(resp.data.metrics ?? {});
|
||||
let inventory: GrainAmount[] = [];
|
||||
let fertInventory: GrainAmount[] = [];
|
||||
if (metrics) {
|
||||
metrics.grainInventory.forEach(grain => {
|
||||
inventory.push({
|
||||
grain: grain.grainType,
|
||||
bushelAmount: grain.bushelAmount,
|
||||
grainName: grainName(grain.grainType)
|
||||
});
|
||||
});
|
||||
metrics.customInventory.forEach(invObject => {
|
||||
if (invObject.storageType === pond.BinStorage.BIN_STORAGE_UNSUPPORTED_GRAIN) {
|
||||
inventory.push({
|
||||
grain: pond.Grain.GRAIN_CUSTOM,
|
||||
bushelAmount: invObject.amount,
|
||||
grainName: invObject.name
|
||||
});
|
||||
} else if (invObject.storageType === pond.BinStorage.BIN_STORAGE_FERTILIZER) {
|
||||
fertInventory.push({
|
||||
grain: pond.Grain.GRAIN_CUSTOM,
|
||||
bushelAmount: invObject.amount * 35.239,
|
||||
grainName: invObject.name
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
setBinMetrics(metrics);
|
||||
setDisplayedInventory(inventory);
|
||||
setDisplayedFertilizer(fertInventory);
|
||||
});
|
||||
}, [as, binAPI, yardKey]);
|
||||
|
||||
const loadMoreBins = (filter: string, total?: number, offset?: number) => {
|
||||
setBinsLoading(true);
|
||||
binAPI
|
||||
.listBins(
|
||||
total ?? maxBins,
|
||||
offset ?? 0,
|
||||
order,
|
||||
orderBy,
|
||||
filter,
|
||||
as,
|
||||
undefined,
|
||||
undefined,
|
||||
[yardKey],
|
||||
["binyard"]
|
||||
)
|
||||
.then(resp => {
|
||||
let bins = yardBins;
|
||||
//if the offset was 0 or undefined we started from the beginning so replace the yard bins with the new ones
|
||||
if (!offset || offset === 0) {
|
||||
bins = resp.data.bins.map(b => Bin.any(b));
|
||||
//else append the new ones on to the end of the existing yard bins
|
||||
} else {
|
||||
bins = bins.concat(resp.data.bins.map(b => Bin.any(b)));
|
||||
}
|
||||
//loop through the new list of bins setting the bins into the correct sections
|
||||
let grainBins: Bin[] = [];
|
||||
let fertBins: Bin[] = [];
|
||||
let emptyBins: Bin[] = [];
|
||||
//let qr: QrCodeKey[] = [];
|
||||
//set the list of bins into the yard bins
|
||||
resp.data.bins.forEach(b => {
|
||||
let bin = Bin.any(b);
|
||||
yardBins.push(bin);
|
||||
if (bin.empty()) {
|
||||
emptyBins.push(bin);
|
||||
} else if (bin.storage() === pond.BinStorage.BIN_STORAGE_FERTILIZER) {
|
||||
fertBins.push(bin);
|
||||
} else {
|
||||
grainBins.push(bin);
|
||||
}
|
||||
//build qr keys here
|
||||
// qr.push({
|
||||
// key: bin.key(),
|
||||
// name: bin.name()
|
||||
// });
|
||||
});
|
||||
setYardBins(bins);
|
||||
setBinTotal(resp.data.total);
|
||||
//setQrKeyList(qr);
|
||||
setGrainBins(grainBins);
|
||||
if (fertBins.length > 0) {
|
||||
setDisplayFert(true);
|
||||
}
|
||||
if (emptyBins.length > 0) {
|
||||
setDisplayEmpty(true);
|
||||
}
|
||||
setFertBins(fertBins);
|
||||
setEmptyBins(emptyBins);
|
||||
setBinsLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
loadBins();
|
||||
}, [yardKey, loadBins]);
|
||||
|
||||
useEffect(() => {
|
||||
let ebt = sessionStorage.getItem("expandBinTotal");
|
||||
if (ebt === "true") {
|
||||
setExpandTotal(true);
|
||||
} else {
|
||||
setExpandTotal(false);
|
||||
}
|
||||
|
||||
let ebu = sessionStorage.getItem("expandBinUtilization");
|
||||
if (ebu === "true") {
|
||||
setExpandUtilization(true);
|
||||
} else {
|
||||
setExpandUtilization(false);
|
||||
}
|
||||
|
||||
let fanTable = sessionStorage.getItem("expandFanTable");
|
||||
if (fanTable === "true") {
|
||||
setExpandFanTable(true);
|
||||
} else {
|
||||
setExpandFanTable(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const duplicateBin = (bin: Bin) => {
|
||||
binAPI.addBin(bin.settings).then(resp => {
|
||||
loadBins();
|
||||
});
|
||||
};
|
||||
|
||||
const binsContent = () => {
|
||||
if (!binsLoading && binTotal === 0) {
|
||||
return (
|
||||
<Box textAlign="center" marginTop={1}>
|
||||
<Typography variant="subtitle1">No bins found</Typography>
|
||||
<Typography variant="body1" color="textSecondary">
|
||||
Create a bin and it will appear here
|
||||
</Typography>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Grid container>
|
||||
{displayGrain && (
|
||||
<React.Fragment>
|
||||
<Grid size={12}>
|
||||
<Divider />
|
||||
</Grid>
|
||||
<Grid size={12}>
|
||||
<BinsList
|
||||
gridView
|
||||
bins={grainBins}
|
||||
duplicateBin={duplicateBin}
|
||||
title={"Grain Bins"}
|
||||
// because this only triggers in scroll view it is no longer necessary as we dont do the scroll here
|
||||
// loadMore={newTranslation => {
|
||||
// //only triggered in the scroll view so this will never trigger in grid view
|
||||
// if (yardBins.length < binTotal) {
|
||||
// loadMoreBins(contentFilter);
|
||||
// setScrollTranslations({ ...scrollTranslations, bins: newTranslation });
|
||||
// }
|
||||
// }}
|
||||
/>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
)}
|
||||
{displayFert && (
|
||||
<React.Fragment>
|
||||
<Grid size={12}>
|
||||
<Divider />
|
||||
</Grid>
|
||||
<Grid size={12}>
|
||||
<BinsList
|
||||
gridView
|
||||
bins={fertBins}
|
||||
duplicateBin={duplicateBin}
|
||||
title={"Fertilizer Bins"}
|
||||
// loadMore={newTranslation => {
|
||||
// //only triggered in the scroll view so this will never trigger in grid view
|
||||
// if (yardBins.length < binTotal) {
|
||||
// loadMoreBins(contentFilter);
|
||||
// setScrollTranslations({ ...scrollTranslations, fertilizer: newTranslation });
|
||||
// }
|
||||
// }}
|
||||
/>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
)}
|
||||
{displayEmpty && (
|
||||
<React.Fragment>
|
||||
<Grid size={12}>
|
||||
<Divider />
|
||||
</Grid>
|
||||
<Grid size={12}>
|
||||
<BinsList
|
||||
gridView
|
||||
bins={emptyBins}
|
||||
duplicateBin={duplicateBin}
|
||||
title={"Empty Bins"}
|
||||
// loadMore={newTranslation => {
|
||||
// //only triggered in the scroll view so this will never trigger in grid view
|
||||
// if (yardBins.length < binTotal) {
|
||||
// loadMoreBins(contentFilter);
|
||||
// setScrollTranslations({ ...scrollTranslations, empty: newTranslation });
|
||||
// }
|
||||
// }}
|
||||
/>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
)}
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const binsHeader = () => {
|
||||
return (
|
||||
<Menu
|
||||
id="yardMenu"
|
||||
anchorEl={binMenuAnchorEl ? binMenuAnchorEl : null}
|
||||
open={binMenuAnchorEl !== null}
|
||||
onClose={() => {
|
||||
setBinMenuAnchorEl(null);
|
||||
}}
|
||||
disableAutoFocusItem>
|
||||
<MenuItem>
|
||||
<FormControl style={{ marginLeft: theme.spacing(2) }}>
|
||||
<InputLabel id="demo-simple-select-label">Order</InputLabel>
|
||||
<Select
|
||||
labelId="demo-simple-select-label"
|
||||
id="demo-simple-select"
|
||||
value={order}
|
||||
onChange={event => setOrder(event.target.value as SetStateAction<"asc" | "desc">)}>
|
||||
<MenuItem value={"asc"}>Ascending</MenuItem>
|
||||
<MenuItem value={"desc"}>Descending</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
</MenuItem>
|
||||
<MenuItem>
|
||||
<FormControl style={{ marginLeft: theme.spacing(2) }}>
|
||||
<InputLabel id="demo-simple-select-label">Order By</InputLabel>
|
||||
<Select
|
||||
labelId="demo-simple-select-label"
|
||||
id="demo-simple-select"
|
||||
value={orderBy}
|
||||
onChange={event => setOrderBy(event.target.value as SetStateAction<string>)}>
|
||||
<MenuItem value={"name"}>Name</MenuItem>
|
||||
<MenuItem value={"timestamp"}>Timestamp</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
</MenuItem>
|
||||
<Divider />
|
||||
<MenuItem>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={displayGrain}
|
||||
onChange={(e, checked) => {
|
||||
setDisplayGrain(checked);
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label={<Typography>Grain</Typography>}
|
||||
/>
|
||||
</MenuItem>
|
||||
<MenuItem>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={displayFert}
|
||||
onChange={(e, checked) => {
|
||||
setDisplayFert(checked);
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label={<Typography>Fertilizer</Typography>}
|
||||
/>
|
||||
</MenuItem>
|
||||
<MenuItem>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={displayEmpty}
|
||||
onChange={(e, checked) => {
|
||||
setDisplayEmpty(checked);
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label={<Typography>Empty Bins</Typography>}
|
||||
/>
|
||||
</MenuItem>
|
||||
{/* <MenuItem
|
||||
onClick={() => {
|
||||
setOpenQrGenerator(true);
|
||||
}}>
|
||||
<Typography>Generate QR Codes</Typography>
|
||||
</MenuItem> */}
|
||||
</Menu>
|
||||
);
|
||||
};
|
||||
|
||||
const binsByGrainType = () => {
|
||||
return (
|
||||
<Box width={1} marginBottom={1}>
|
||||
<Grid
|
||||
container
|
||||
direction="row"
|
||||
alignContent="center"
|
||||
alignItems="center">
|
||||
<Grid>
|
||||
<Box display="flex" paddingY={1} alignContent="center" alignItems="center">
|
||||
<Typography variant="h6" style={{ fontWeight: 650 }}>
|
||||
Bins - ({yardBins.length} of {binTotal})
|
||||
</Typography>
|
||||
{contentFilter && (
|
||||
<Box marginLeft={1}>
|
||||
<Chip
|
||||
size="small"
|
||||
onDelete={() => {
|
||||
setContentFilter("");
|
||||
loadMoreBins("");
|
||||
}}
|
||||
label={contentFilter}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
{yardBins.length < binTotal && (
|
||||
<Button
|
||||
style={{ marginLeft: 10 }}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
loadMoreBins(contentFilter, 0, yardBins.length);
|
||||
}}>
|
||||
Load All
|
||||
</Button>
|
||||
)}
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<MoreVert
|
||||
className={classes.icon}
|
||||
onClick={event => {
|
||||
let target = event.currentTarget;
|
||||
setBinMenuAnchorEl(target);
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
{binsLoading ? <Skeleton variant="rectangular" height="200px" /> : binsContent()}
|
||||
{binsHeader()}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
const desktopInventory = () => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Grid container direction="row" alignContent="center" alignItems="center">
|
||||
<Grid style={{ height: "200px" }} size={6}>
|
||||
<BinInventoryChart
|
||||
customLabel="Grain"
|
||||
inventory={displayedInventory}
|
||||
onClick={(grain: pond.Grain, grainName: string) => {
|
||||
let filter = "";
|
||||
if (grain !== pond.Grain.GRAIN_NONE && grain !== pond.Grain.GRAIN_CUSTOM) {
|
||||
filter = pond.Grain[grain];
|
||||
} else {
|
||||
filter = grainName;
|
||||
}
|
||||
setContentFilter(filter);
|
||||
loadMoreBins(filter);
|
||||
}}
|
||||
//activeGrain={grainFilter}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid style={{ height: "200px" }} size={6}>
|
||||
<BinInventoryChart
|
||||
customLabel="Fertilizer"
|
||||
inventory={displayedFertilizer}
|
||||
onClick={(grain: pond.Grain, grainName: string) => {
|
||||
let filter = "";
|
||||
if (grain !== pond.Grain.GRAIN_NONE && grain !== pond.Grain.GRAIN_CUSTOM) {
|
||||
filter = pond.Grain[grain];
|
||||
} else {
|
||||
filter = grainName;
|
||||
}
|
||||
setContentFilter(filter);
|
||||
loadMoreBins(filter);
|
||||
}}
|
||||
customUnit={"L"}
|
||||
//activeGrain={grainFilter}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const mobileViewCarousel = () => {
|
||||
let length = 2;
|
||||
let charts: JSX.Element[] = [
|
||||
<BinInventoryChart
|
||||
customLabel="Grain"
|
||||
inventory={displayedInventory}
|
||||
onClick={(grain: pond.Grain, grainName: string) => {
|
||||
let filter = "";
|
||||
if (grain !== pond.Grain.GRAIN_NONE && grain !== pond.Grain.GRAIN_CUSTOM) {
|
||||
filter = pond.Grain[grain];
|
||||
} else {
|
||||
filter = grainName;
|
||||
}
|
||||
setContentFilter(filter);
|
||||
loadMoreBins(filter);
|
||||
}}
|
||||
//activeGrain={grainFilter}
|
||||
/>,
|
||||
<BinInventoryChart
|
||||
customLabel="Fertilizer"
|
||||
inventory={displayedFertilizer}
|
||||
onClick={(grain: pond.Grain, grainName: string) => {
|
||||
let filter = "";
|
||||
if (grain !== pond.Grain.GRAIN_NONE && grain !== pond.Grain.GRAIN_CUSTOM) {
|
||||
filter = pond.Grain[grain];
|
||||
} else {
|
||||
filter = grainName;
|
||||
}
|
||||
setContentFilter(filter);
|
||||
loadMoreBins(filter);
|
||||
}}
|
||||
customUnit={"L"}
|
||||
//activeGrain={grainFilter}
|
||||
/>
|
||||
];
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Grid container direction="row" alignContent="center" alignItems="center">
|
||||
<Grid size={2}>
|
||||
<Button
|
||||
style={{ height: 160 }}
|
||||
onClick={() => {
|
||||
const newIndex = carouselIndex - 1;
|
||||
setCarouselIndex(newIndex < 0 ? length - 1 : newIndex);
|
||||
}}>
|
||||
<ArrowBackIos />
|
||||
</Button>
|
||||
</Grid>
|
||||
<Grid size={8}>
|
||||
<Box height={"180px"} flexDirection="row" display="flex">
|
||||
{charts[carouselIndex]}
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid size={2}>
|
||||
<Button
|
||||
style={{ height: 160 }}
|
||||
onClick={() => {
|
||||
const newIndex = carouselIndex + 1;
|
||||
setCarouselIndex(newIndex >= length ? 0 : newIndex);
|
||||
}}>
|
||||
<ArrowForwardIos />
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const totalInventory = () => {
|
||||
return (
|
||||
<Accordion
|
||||
className={classes.accordion}
|
||||
expanded={expandTotal}
|
||||
onChange={(_, expanded) => {
|
||||
setExpandTotal(expanded);
|
||||
sessionStorage.setItem("expandBinTotal", expanded.toString());
|
||||
}}>
|
||||
<AccordionSummary expandIcon={<ExpandMore />}>
|
||||
<Typography variant="h6" style={{ fontWeight: 650 }}>
|
||||
Total Inventory
|
||||
</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
{isMobile || insert ? mobileViewCarousel() : desktopInventory()}
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
);
|
||||
};
|
||||
|
||||
const binUtilizationList = () => {
|
||||
const hasInventory = binMetrics && binMetrics.grainInventory.length > 0;
|
||||
const useWeight = getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT;
|
||||
return (
|
||||
<Accordion
|
||||
className={classes.accordion}
|
||||
style={{ marginTop: 5 }}
|
||||
expanded={expandUtilization}
|
||||
onChange={(_, expanded) => {
|
||||
setExpandUtilization(expanded);
|
||||
sessionStorage.setItem("expandBinUtilization", expanded.toString());
|
||||
}}>
|
||||
<AccordionSummary expandIcon={<ExpandMore />}>
|
||||
<Typography variant="h6" style={{ fontWeight: 650 }}>
|
||||
Bin Utilization
|
||||
</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
{hasInventory ? (
|
||||
<Box width={"100%"}>
|
||||
<Typography variant="caption" color="textSecondary">
|
||||
Click a chart to filter bins by grain
|
||||
</Typography>
|
||||
<GridList
|
||||
className={classes.gridList}
|
||||
cols={
|
||||
props.insert && !isMobile
|
||||
? 3.25
|
||||
: width === "xs"
|
||||
? 3.25
|
||||
: width === "sm"
|
||||
? 5.5
|
||||
: width === "md"
|
||||
? 6.5
|
||||
: width === "lg"
|
||||
? 7.5
|
||||
: 8.5
|
||||
}>
|
||||
{binMetrics &&
|
||||
binMetrics.grainInventory.map((inv, key) => (
|
||||
<GridListTile key={key}>
|
||||
<BinUtilizationChart
|
||||
grain={inv.grainType}
|
||||
customUnit={useWeight ? " mT" : " bu"}
|
||||
bushelAmount={
|
||||
useWeight
|
||||
? inv.bushelAmount / GrainDescriber(inv.grainType).bushelsPerTonne
|
||||
: inv.bushelAmount
|
||||
}
|
||||
bushelCapacity={
|
||||
useWeight
|
||||
? inv.bushelCapacity / GrainDescriber(inv.grainType).bushelsPerTonne
|
||||
: inv.bushelCapacity
|
||||
}
|
||||
onClick={() => {
|
||||
setContentFilter(pond.Grain[inv.grainType]);
|
||||
loadMoreBins(pond.Grain[inv.grainType]);
|
||||
}}
|
||||
grainActive={contentFilter === pond.Grain[inv.grainType]}
|
||||
/>
|
||||
</GridListTile>
|
||||
))}
|
||||
{binMetrics &&
|
||||
binMetrics.customInventory.map((inv, key) => {
|
||||
//default to bushel values
|
||||
let amount = inv.amount;
|
||||
let cap = inv.capacity;
|
||||
let unit = " bu";
|
||||
if (inv.storageType === pond.BinStorage.BIN_STORAGE_FERTILIZER) {
|
||||
amount = amount * 35.239;
|
||||
cap = cap * 35.239;
|
||||
unit = " L";
|
||||
}
|
||||
if (useWeight && inv.bushelsPerTonne > 1) {
|
||||
amount = amount / inv.bushelsPerTonne;
|
||||
cap = cap / inv.bushelsPerTonne;
|
||||
unit = " mT";
|
||||
}
|
||||
|
||||
return (
|
||||
<GridListTile key={key}>
|
||||
<BinUtilizationChart
|
||||
grain={pond.Grain.GRAIN_CUSTOM}
|
||||
bushelAmount={amount}
|
||||
bushelCapacity={cap}
|
||||
customUnit={unit}
|
||||
onClick={() => {
|
||||
setContentFilter(inv.name);
|
||||
loadMoreBins(inv.name);
|
||||
}}
|
||||
grainActive={contentFilter === inv.name}
|
||||
customLabel={inv.name}
|
||||
customColour={stringToMaterialColour(inv.name)}
|
||||
/>
|
||||
</GridListTile>
|
||||
);
|
||||
})}
|
||||
</GridList>
|
||||
</Box>
|
||||
) : (
|
||||
<Typography color="textSecondary" style={{ margin: "2rem", marginTop: "0rem" }}>
|
||||
No active bins
|
||||
</Typography>
|
||||
)}
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
);
|
||||
};
|
||||
|
||||
const binFanTable = () => {
|
||||
return (
|
||||
<Accordion
|
||||
className={classes.accordion}
|
||||
expanded={expandFanTable}
|
||||
style={{ marginTop: 5 }}
|
||||
onChange={(_, expanded) => {
|
||||
setExpandFanTable(expanded);
|
||||
sessionStorage.setItem("expandFanTable", expanded.toString());
|
||||
}}>
|
||||
<AccordionSummary expandIcon={<ExpandMore />}>
|
||||
<Typography variant="h6" style={{ fontWeight: 650 }}>
|
||||
Fan Status{" "}
|
||||
{totalFanControllers > 0 && !isMobile
|
||||
? " - " + totalFanControllersOn + " of " + totalFanControllers + " controllers on"
|
||||
: ""}
|
||||
</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
{/* <BinsFansStatusTable
|
||||
bins={yardBins}
|
||||
isLoading={binsLoading}
|
||||
getControllerInfo={(total, on) => {
|
||||
setTotalFanControllers(total);
|
||||
setTotalFanControllersOn(on);
|
||||
}}
|
||||
/> */}
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box height={1}>
|
||||
<Box paddingY={0.5} paddingX={1}>
|
||||
<Grid container>
|
||||
<Grid size={12}>
|
||||
{binsByGrainType()}
|
||||
</Grid>
|
||||
<Grid size={12}>
|
||||
{binsLoading ? <Skeleton variant="rectangular" height="200px" /> : totalInventory()}
|
||||
</Grid>
|
||||
<Grid size={12}>
|
||||
<Divider />
|
||||
</Grid>
|
||||
<Grid size={12}>
|
||||
{binsLoading ? <Skeleton variant="rectangular" height="200px" /> : binUtilizationList()}
|
||||
</Grid>
|
||||
<Grid size={12}>
|
||||
<Divider />
|
||||
</Grid>
|
||||
<Grid size={12}>
|
||||
{binsLoading ? <Skeleton variant="rectangular" height="200px" /> : binFanTable()}
|
||||
</Grid>
|
||||
<Grid size={12}>
|
||||
<Divider />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
{/* <QrCodeGenerator
|
||||
open={openQrGenerator}
|
||||
close={() => {
|
||||
setOpenQrGenerator(false);
|
||||
}}
|
||||
keyList={qrKeyList}
|
||||
requiredUrlAffix={"bins"}
|
||||
/> */}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue