bin card, no svg yet
This commit is contained in:
parent
a0eabf50c6
commit
7edba7e25b
4 changed files with 848 additions and 153 deletions
525
src/bin/BinCardV2.tsx
Normal file
525
src/bin/BinCardV2.tsx
Normal file
|
|
@ -0,0 +1,525 @@
|
|||
import {
|
||||
Box,
|
||||
Card,
|
||||
darken,
|
||||
Grid,
|
||||
IconButton,
|
||||
Theme,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import HumidityIcon from "component/HumidityIcon";
|
||||
import TemperatureIcon from "component/TemperatureIcon";
|
||||
import GrainDescriber from "grain/GrainDescriber";
|
||||
import { cloneDeep } from "lodash";
|
||||
import { Bin } from "models";
|
||||
import { GrainCable } from "models/GrainCable";
|
||||
import moment from "moment";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
import { useGlobalState } from "providers";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { celsiusToFahrenheit, getGrainUnit, or } from "utils";
|
||||
//import { useHistory } from "react-router";
|
||||
//import BinModeDot from "./BinModeDot";
|
||||
// import BinSVGV2 from "./BinSVGV2";
|
||||
import { avg } from "utils";
|
||||
import { describeMeasurement } from "pbHelpers/MeasurementDescriber";
|
||||
import { quack } from "protobuf-ts/quack";
|
||||
import AerationFanIcon from "products/AgIcons/AerationFanIcon";
|
||||
import ObjectHeaterIcon from "products/Construction/ObjectHeaterIcon";
|
||||
import { CheckCircle, Warning } from "@mui/icons-material";
|
||||
import { makeStyles } from "@mui/styles";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => {
|
||||
return ({
|
||||
displayBox: {
|
||||
background: darken(theme.palette.background.default, 0.05),
|
||||
borderRadius: 5,
|
||||
marginRight: -30, //negative margin to extend the box behind the bin svg
|
||||
paddingRight: 30, //padding to offset the text and ignore the extension
|
||||
marginTop: 5
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
interface Props {
|
||||
bin: Bin;
|
||||
duplicateBin: (bin: Bin) => void;
|
||||
dupHovered: (hovered: boolean) => void;
|
||||
valDisplay?: "high" | "low" | "average";
|
||||
}
|
||||
|
||||
interface GrainDetails {
|
||||
temp: number;
|
||||
humid: number;
|
||||
emc: number | undefined;
|
||||
}
|
||||
|
||||
export default function BinCard(props: Props) {
|
||||
const { bin, valDisplay } = props;
|
||||
const [cables, setCables] = useState<GrainCable[]>();
|
||||
//const [modeDetails, setModeDetails] = useState("");
|
||||
const [lidarPercentage, setLidarPercentage] = useState<number | undefined>();
|
||||
const [lidarBushels, setLidarBushels] = useState<number | undefined>();
|
||||
const [{ user }] = useGlobalState();
|
||||
const classes = useStyles();
|
||||
const [average, setAverage] = useState<GrainDetails>();
|
||||
const [coldNode, setColdNode] = useState<GrainDetails>();
|
||||
const [hotNode, setHotNode] = useState<GrainDetails>();
|
||||
const [mostMissed, setMostMissed] = useState(0);
|
||||
const warningThreshold = 6;
|
||||
const tempColour = describeMeasurement(
|
||||
quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE
|
||||
).colour();
|
||||
const humColour = describeMeasurement(quack.MeasurementType.MEASUREMENT_TYPE_PERCENT).colour();
|
||||
const emcColour = describeMeasurement(quack.MeasurementType.MEASUREMENT_TYPE_GRAIN_EMC).colour();
|
||||
|
||||
useEffect(() => {
|
||||
let newGrainCables: GrainCable[] = [];
|
||||
if (bin.status.grainCables === undefined) return;
|
||||
let mostMissedReadings = 0;
|
||||
let allTemps: number[] = [];
|
||||
let allHums: number[] = [];
|
||||
let allMoistures: number[] = [];
|
||||
let coldestNode: GrainDetails | undefined;
|
||||
let hottestNode: GrainDetails | undefined;
|
||||
let now = moment();
|
||||
bin.status.grainCables.forEach(cable => {
|
||||
let c: GrainCable = new GrainCable();
|
||||
//flip the cables so that for display node 1 is at the bottom
|
||||
let cableTemps = cloneDeep(cable.celcius);
|
||||
let cableHums = cloneDeep(cable.relativeHumidity);
|
||||
let cableEMC = cloneDeep(cable.moisture);
|
||||
c.temperatures = cableTemps.reverse();
|
||||
c.humidities = cableHums.reverse();
|
||||
c.grainMoistures = cableEMC.reverse();
|
||||
|
||||
c.topNode = cable.topNode;
|
||||
newGrainCables.push(c);
|
||||
|
||||
//determine the averages for temp/RH/EMC for the bin using all of the cables
|
||||
let temps = cloneDeep(cable.celcius);
|
||||
let hums = cloneDeep(cable.relativeHumidity);
|
||||
let moistures = cloneDeep(cable.moisture);
|
||||
|
||||
const spliceEnd = cable.topNode > 0 ? cable.topNode : temps.length;
|
||||
let grainTemps = temps.splice(0, spliceEnd);
|
||||
let grainHums = hums.splice(0, spliceEnd);
|
||||
let grainEMCs = moistures.splice(0, spliceEnd);
|
||||
allTemps.push(...grainTemps);
|
||||
allHums.push(...grainHums);
|
||||
allMoistures.push(...grainEMCs);
|
||||
|
||||
//set the hottest and coldest nodes
|
||||
if (coldestNode === undefined || Math.min(...grainTemps) < coldestNode.temp) {
|
||||
let lowTempIndex =
|
||||
grainTemps.indexOf(Math.min(...grainTemps)) === -1
|
||||
? 0
|
||||
: grainTemps.indexOf(Math.min(...grainTemps));
|
||||
|
||||
coldestNode = {
|
||||
temp: grainTemps[lowTempIndex],
|
||||
humid: grainHums[lowTempIndex],
|
||||
emc: grainEMCs[lowTempIndex]
|
||||
};
|
||||
}
|
||||
|
||||
if (hottestNode === undefined || Math.max(...grainTemps) > hottestNode.temp) {
|
||||
let highTempIndex =
|
||||
grainTemps.indexOf(Math.max(...grainTemps)) === -1
|
||||
? 0
|
||||
: grainTemps.indexOf(Math.max(...grainTemps));
|
||||
|
||||
hottestNode = {
|
||||
temp: grainTemps[highTempIndex],
|
||||
humid: grainHums[highTempIndex],
|
||||
emc: grainEMCs[highTempIndex]
|
||||
};
|
||||
}
|
||||
|
||||
let lastRead = moment(cable.lastRead);
|
||||
let elapsedMS = now.diff(lastRead);
|
||||
|
||||
if (elapsedMS > cable.measurementInterval) {
|
||||
let missedReadings = Math.floor(elapsedMS / cable.measurementInterval);
|
||||
if (missedReadings > mostMissedReadings) {
|
||||
mostMissedReadings = missedReadings;
|
||||
}
|
||||
}
|
||||
});
|
||||
setCables(newGrainCables);
|
||||
setMostMissed(mostMissedReadings);
|
||||
setColdNode(coldestNode);
|
||||
setHotNode(hottestNode);
|
||||
setAverage({
|
||||
temp: avg(allTemps),
|
||||
humid: avg(allHums),
|
||||
emc: avg(allMoistures)
|
||||
});
|
||||
|
||||
let cm = 0;
|
||||
if (bin.status.distance && bin.status.distance > 0) {
|
||||
//note that no conversions are happening as the unit measurement model is not being used so the value will be in cm
|
||||
cm = bin.status.distance;
|
||||
let height = or(bin.settings.specs?.heightCm, 0);
|
||||
let ratio = 1 - cm / height;
|
||||
let capacity = or(bin.settings.specs?.bushelCapacity, 0);
|
||||
let lidarEstimate = Math.round(capacity * ratio);
|
||||
setLidarBushels(lidarEstimate);
|
||||
setLidarPercentage(Math.round((lidarEstimate / capacity) * 100));
|
||||
}
|
||||
}, [bin]);
|
||||
|
||||
// useEffect(() => {
|
||||
// let now = moment();
|
||||
// let duration = moment.duration(moment(bin.status.lastModeChange).diff(now));
|
||||
// let days = duration.asDays();
|
||||
// days = Math.abs(days);
|
||||
// duration.subtract(moment.duration(days, "days"));
|
||||
// let hours = duration.hours();
|
||||
// hours = Math.abs(hours);
|
||||
|
||||
// if (days > 50 && bin.settings.mode === pond.BinMode.BIN_MODE_DRYING) {
|
||||
// setModeDetails("Calculating...");
|
||||
// } else if (bin.settings.mode === pond.BinMode.BIN_MODE_NONE) {
|
||||
// setModeDetails("No Mode");
|
||||
// } else {
|
||||
// setModeDetails(Math.floor(days) + "d " + hours + "h");
|
||||
// }
|
||||
// }, [bin]);
|
||||
|
||||
const typeDisplay = () => {
|
||||
let grainType = bin.settings.inventory?.grainType ?? pond.Grain.GRAIN_NONE;
|
||||
if (bin.storage() === pond.BinStorage.BIN_STORAGE_SUPPORTED_GRAIN) {
|
||||
return (
|
||||
<Box>
|
||||
<Typography variant="subtitle2" style={{ fontSize: "0.7rem", fontWeight: 700 }}>
|
||||
{GrainDescriber(grainType).name}
|
||||
</Typography>
|
||||
{/* <Typography variant="subtitle2" style={{ fontSize: "0.7rem", fontWeight: 700 }}>
|
||||
{bin.settings.inventory?.grainSubtype}
|
||||
</Typography> */}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Box>
|
||||
<Typography variant="subtitle2" style={{ fontSize: "0.7rem", fontWeight: 700 }}>
|
||||
{bin.settings.inventory?.customTypeName}
|
||||
</Typography>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
const tempDisplay = () => {
|
||||
let display = "--";
|
||||
let val;
|
||||
switch (valDisplay) {
|
||||
case "average":
|
||||
val = average?.temp;
|
||||
break;
|
||||
case "low":
|
||||
val = coldNode?.temp;
|
||||
break;
|
||||
case "high":
|
||||
val = hotNode?.temp;
|
||||
break;
|
||||
}
|
||||
|
||||
if (val !== undefined && !isNaN(val)) {
|
||||
if (user.settings.temperatureUnit === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT) {
|
||||
val = celsiusToFahrenheit(val);
|
||||
}
|
||||
display = val.toFixed(2);
|
||||
}
|
||||
|
||||
return (
|
||||
<Typography
|
||||
align="center"
|
||||
noWrap
|
||||
style={{ fontSize: "0.85rem", fontWeight: 650, color: tempColour }}>
|
||||
{display +
|
||||
(user.settings.temperatureUnit === pond.TemperatureUnit.TEMPERATURE_UNIT_CELSIUS
|
||||
? "°C"
|
||||
: "°F")}
|
||||
</Typography>
|
||||
);
|
||||
};
|
||||
|
||||
const percentDisplay = () => {
|
||||
let display = "--";
|
||||
let val;
|
||||
let useEMC = false;
|
||||
|
||||
switch (valDisplay) {
|
||||
case "average":
|
||||
if (average?.emc) {
|
||||
useEMC = true;
|
||||
val = average.emc;
|
||||
} else {
|
||||
val = average?.humid;
|
||||
}
|
||||
break;
|
||||
case "low":
|
||||
if (coldNode?.emc) {
|
||||
useEMC = true;
|
||||
val = coldNode.emc;
|
||||
} else {
|
||||
val = coldNode?.humid;
|
||||
}
|
||||
break;
|
||||
case "high":
|
||||
if (hotNode?.emc) {
|
||||
useEMC = true;
|
||||
val = hotNode.emc;
|
||||
} else {
|
||||
val = hotNode?.humid;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (val !== undefined && !isNaN(val)) {
|
||||
display = val.toFixed(2);
|
||||
}
|
||||
|
||||
return (
|
||||
<Typography
|
||||
align="center"
|
||||
noWrap
|
||||
style={{ fontSize: "0.85rem", fontWeight: 650, color: useEMC ? emcColour : humColour }}>
|
||||
{display}%
|
||||
</Typography>
|
||||
);
|
||||
};
|
||||
|
||||
const cableBox = () => {
|
||||
return (
|
||||
<Box className={classes.displayBox}>
|
||||
<Grid container alignContent="center" alignItems="center" direction="row">
|
||||
<Grid item xs={3}>
|
||||
<TemperatureIcon heightWidth={20} />
|
||||
</Grid>
|
||||
<Grid item xs={9}>
|
||||
<Box>
|
||||
{tempDisplay()}
|
||||
<Typography
|
||||
align="center"
|
||||
color="textSecondary"
|
||||
noWrap
|
||||
style={{ fontSize: "0.5rem" }}>
|
||||
{valDisplay === "high" ? "High" : valDisplay === "low" ? "Low" : "Average"}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item xs={3} style={{ paddingLeft: 5 }}>
|
||||
<HumidityIcon height={20} />
|
||||
</Grid>
|
||||
<Grid item xs={9}>
|
||||
<Box>
|
||||
{percentDisplay()}
|
||||
<Typography
|
||||
align="center"
|
||||
color="textSecondary"
|
||||
noWrap
|
||||
style={{ fontSize: "0.5rem" }}>
|
||||
{valDisplay === "high" ? "High" : valDisplay === "low" ? "Low" : "Average"}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
const fanBox = (controller: pond.BinFan) => {
|
||||
return (
|
||||
<Box className={classes.displayBox} key={controller.key}>
|
||||
<Grid container direction="row" alignItems="center" alignContent="center">
|
||||
<Grid item xs={3} style={{ paddingLeft: 5, paddingTop: 5 }}>
|
||||
<AerationFanIcon size={18} />
|
||||
</Grid>
|
||||
<Grid item xs={9}>
|
||||
<Box>
|
||||
<Typography
|
||||
align="center"
|
||||
noWrap
|
||||
style={{
|
||||
fontSize: "0.7rem",
|
||||
fontWeight: 650,
|
||||
color: controller.state ? "green" : "orange"
|
||||
}}>
|
||||
{controller.state ? "ON" : "OFF"}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
const heaterBox = (controller: pond.BinHeater) => {
|
||||
return (
|
||||
<Box className={classes.displayBox} key={controller.key}>
|
||||
<Grid container direction="row" alignItems="center" alignContent="center">
|
||||
<Grid item xs={3} style={{ paddingLeft: 5, paddingTop: 3 }}>
|
||||
{/* <ObjectHeaterIcon height={18} width={18} /> */}
|
||||
<ObjectHeaterIcon />
|
||||
</Grid>
|
||||
<Grid item xs={9}>
|
||||
<Box>
|
||||
<Typography
|
||||
align="center"
|
||||
noWrap
|
||||
style={{
|
||||
fontSize: "0.7rem",
|
||||
fontWeight: 650,
|
||||
color: controller.state ? "green" : "orange"
|
||||
}}>
|
||||
{controller.state ? "ON" : "OFF"}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
const binGraphic = () => {
|
||||
return (
|
||||
<Box display="flex" justifyContent="center" paddingTop={0}>
|
||||
<Box padding={0} style={{ flex: 1, textAlign: "left", flexDirection: "column" }}>
|
||||
{typeDisplay()}
|
||||
{cableBox()}
|
||||
{bin.status.fans.map(controller => fanBox(controller))}
|
||||
{bin.status.heaters.map(controller => heaterBox(controller))}
|
||||
</Box>
|
||||
<Box style={{ flex: 1, textAlign: "center", flexDirection: "column" }}>
|
||||
{/* <BinSVGV2
|
||||
cableEstimate={bin.settings.autoGrainNode}
|
||||
height={160}
|
||||
binShape={bin.settings.specs?.shape}
|
||||
fillPercentage={bin.fillPercent()}
|
||||
lidarEstimate={lidarPercentage}
|
||||
cables={cables}
|
||||
highTemp={bin.settings.highTemp}
|
||||
lowTemp={bin.settings.lowTemp}
|
||||
hottestNodeTemp={valDisplay === "high" ? hotNode?.temp : undefined}
|
||||
coldestNodeTemp={valDisplay === "low" ? coldNode?.temp : undefined}
|
||||
inventoryControl={bin.inventoryControl()}
|
||||
/> */}
|
||||
hi
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
const inventoryDisplay = (current: number, capacity: number) => {
|
||||
if (bin.storage() === pond.BinStorage.BIN_STORAGE_FERTILIZER) {
|
||||
return (
|
||||
Math.round(current * 35.239).toLocaleString() +
|
||||
"/" +
|
||||
Math.round(capacity * 35.239).toLocaleString() +
|
||||
(lidarBushels ? "(" + Math.round(lidarBushels * 35.239).toLocaleString() + " est)" : "") +
|
||||
" L"
|
||||
);
|
||||
}
|
||||
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT && bin.bushelsPerTonne() > 1) {
|
||||
return (
|
||||
bin.grainTonnes().toLocaleString() +
|
||||
(lidarBushels
|
||||
? "(" + Math.round(lidarBushels / bin.bushelsPerTonne()).toLocaleString() + " est)"
|
||||
: "") +
|
||||
" mT " +
|
||||
bin.fillPercent() +
|
||||
"%"
|
||||
);
|
||||
}
|
||||
return (
|
||||
current.toLocaleString() +
|
||||
"/" +
|
||||
capacity.toLocaleString() +
|
||||
(lidarBushels ? "(" + lidarBushels.toLocaleString() + " est)" : "") +
|
||||
" bu"
|
||||
);
|
||||
};
|
||||
|
||||
const componentStateBanner = () => {
|
||||
const hasCables = bin.status.grainCables.length > 0;
|
||||
return (
|
||||
<Box display="flex" justifyContent="space-between">
|
||||
{hasCables ? (
|
||||
<React.Fragment>
|
||||
<Typography style={{ fontSize: 15, fontWeight: 650 }}>
|
||||
{mostMissed < 3 ? "Active" : mostMissed <= warningThreshold ? "Missing" : "Inactive"}
|
||||
</Typography>
|
||||
{mostMissed < 3 ? (
|
||||
<CheckCircle style={{ color: "green" }} />
|
||||
) : mostMissed <= warningThreshold ? (
|
||||
<Warning style={{ color: "yellow" }} />
|
||||
) : (
|
||||
<Warning style={{ color: "red" }} />
|
||||
)}
|
||||
</React.Fragment>
|
||||
) : (
|
||||
<Typography style={{ fontSize: 15, fontWeight: 650 }}>Unmonitored</Typography>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
const info = () => {
|
||||
const inv = bin.settings.inventory;
|
||||
let bushelAmount = inv?.grainBushels;
|
||||
let bushelCapacity = bin.settings.specs?.bushelCapacity;
|
||||
const empty =
|
||||
!inv || inv.empty || !bushelCapacity || bushelCapacity <= 0 || inv.grainBushels <= 0;
|
||||
return (
|
||||
<Box width={1} marginTop={0}>
|
||||
<Typography align="center" color="textSecondary" noWrap style={{ fontSize: "0.65rem" }}>
|
||||
{empty || !bushelAmount || !bushelCapacity
|
||||
? "empty"
|
||||
: inventoryDisplay(bushelAmount, bushelCapacity)}
|
||||
</Typography>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Card>
|
||||
{user.hasFeature("admin") && (
|
||||
<IconButton
|
||||
style={{
|
||||
height: 35,
|
||||
width: 35,
|
||||
position: "absolute",
|
||||
zIndex: 2,
|
||||
right: 1,
|
||||
top: 1
|
||||
}}
|
||||
onClick={e => props.duplicateBin(bin)}
|
||||
onMouseEnter={() => props.dupHovered(true)}
|
||||
onMouseLeave={() => props.dupHovered(false)}>
|
||||
+
|
||||
</IconButton>
|
||||
)}
|
||||
{/* <Box position="absolute" top={4} right={4}>
|
||||
<BinModeDot mode={bin.settings.mode} />
|
||||
</Box> */}
|
||||
<Box padding={1}>
|
||||
<Typography
|
||||
align="left"
|
||||
variant="body1"
|
||||
color="textPrimary"
|
||||
noWrap
|
||||
style={{ fontSize: "0.8rem", fontWeight: 700 }}>
|
||||
{bin.name()}
|
||||
</Typography>
|
||||
{binGraphic()}
|
||||
{info()}
|
||||
{componentStateBanner()}
|
||||
</Box>
|
||||
{/* <Box style={{position: "absolute", right:5, bottom: 1}}>
|
||||
<Warning />
|
||||
</Box> */}
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
152
src/bin/BinsList.tsx
Normal file
152
src/bin/BinsList.tsx
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
import {
|
||||
Box,
|
||||
Button,
|
||||
Grid2 as Grid,
|
||||
Theme,
|
||||
Typography
|
||||
} from "@mui/material";
|
||||
import { Bin } from "models";
|
||||
import React, { useRef, useState } from "react";
|
||||
// import ScrollMenu from "react-horizontal-scroll-menu";
|
||||
// import { useHistory } from "react-router";
|
||||
import { ArrowForward, ArrowBack } from "@mui/icons-material";
|
||||
import { useMobile } from "hooks";
|
||||
import BinCardV2 from "./BinCardV2";
|
||||
import { makeStyles } from "@mui/styles";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
interface Props {
|
||||
bins: Bin[];
|
||||
duplicateBin: (bin: Bin) => void;
|
||||
title?: string;
|
||||
gridView?: boolean;
|
||||
loadMore?: (newTranslation: number) => void;
|
||||
startingTranslate: number;
|
||||
valDisplay?: "high" | "low" | "average";
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => {
|
||||
return ({
|
||||
gridListTile: {
|
||||
position: "relative",
|
||||
minHeight: "184px",
|
||||
height: "auto !important",
|
||||
//width: "184px",
|
||||
padding: 2
|
||||
},
|
||||
hidden: {
|
||||
visibility: "hidden"
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
export default function BinsList(props: Props) {
|
||||
const { bins, duplicateBin, title, gridView, loadMore, startingTranslate, valDisplay } = props;
|
||||
const classes = useStyles();
|
||||
// const history = useHistory();
|
||||
const navigate = useNavigate()
|
||||
const isMobile = useMobile();
|
||||
const [duplicate, setDuplicate] = useState(false);
|
||||
const scrollRef = useRef<any>(null);
|
||||
|
||||
const goToBin = (i: number) => {
|
||||
let path = "/bins/" + bins[i].key();
|
||||
navigate(path, { state: {bin: bins[i]} });
|
||||
};
|
||||
|
||||
// const scroll = () => {
|
||||
// return (
|
||||
// <ScrollMenu
|
||||
// wheel={false}
|
||||
// ref={scrollRef}
|
||||
// alignCenter={false}
|
||||
// inertiaScrolling
|
||||
// translate={startingTranslate}
|
||||
// hideArrows
|
||||
// hideSingleArrow
|
||||
// arrowDisabledClass={classes.hidden}
|
||||
// onUpdate={params => {
|
||||
// if (scrollRef.current.state) {
|
||||
// if (scrollRef.current.getOffsetAtEnd() === params.translate && loadMore) {
|
||||
// loadMore(params.translate);
|
||||
// }
|
||||
// }
|
||||
// }}
|
||||
// onSelect={e => {
|
||||
// if (!duplicate) {
|
||||
// goToBin(e as number);
|
||||
// }
|
||||
// }}
|
||||
// arrowLeft={
|
||||
// <Button style={{ height: 184, display: isMobile ? "none" : "block" }}>
|
||||
// <ArrowBack />
|
||||
// </Button>
|
||||
// }
|
||||
// arrowRight={
|
||||
// <Button style={{ height: 184, display: isMobile ? "none" : "block" }}>
|
||||
// <ArrowForward />
|
||||
// </Button>
|
||||
// }
|
||||
// data={bins.map((b, i) => (
|
||||
// <Box key={i} className={classes.gridListTile}>
|
||||
// <BinCardV2
|
||||
// bin={b}
|
||||
// duplicateBin={duplicateBin}
|
||||
// dupHovered={setDuplicate}
|
||||
// valDisplay={valDisplay}
|
||||
// />
|
||||
// </Box>
|
||||
// ))}
|
||||
// />
|
||||
// );
|
||||
// };
|
||||
|
||||
const grid = () => {
|
||||
return (
|
||||
<Grid container direction="row">
|
||||
{bins.map((b, i) =>
|
||||
isMobile ? (
|
||||
<Grid
|
||||
size={{
|
||||
xs: 6,
|
||||
sm: 4,
|
||||
md: 3,
|
||||
lg: 2,
|
||||
}}
|
||||
key={i}
|
||||
className={classes.gridListTile}
|
||||
onClick={() => goToBin(i)}>
|
||||
<BinCardV2
|
||||
bin={b}
|
||||
duplicateBin={duplicateBin}
|
||||
dupHovered={setDuplicate}
|
||||
valDisplay={valDisplay}
|
||||
/>
|
||||
</Grid>
|
||||
) : (
|
||||
<Box
|
||||
key={i}
|
||||
style={{ width: "184px" }}
|
||||
className={classes.gridListTile}
|
||||
onClick={() => goToBin(i)}>
|
||||
<BinCardV2
|
||||
bin={b}
|
||||
duplicateBin={duplicateBin}
|
||||
dupHovered={setDuplicate}
|
||||
valDisplay={valDisplay}
|
||||
/>
|
||||
</Box>
|
||||
)
|
||||
)}
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{title && <Typography>{title}</Typography>}
|
||||
{/* {gridView ? grid() : scroll()} */}
|
||||
{grid()}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue