finished hooking up the inventory adjustment slider when using manual control on the bin page
This commit is contained in:
parent
b8a49197cb
commit
13c15ec195
6 changed files with 169 additions and 26 deletions
|
|
@ -207,16 +207,16 @@ export default function BinTableExpanded(props: Props) {
|
|||
<Typography sx={{fontWeight: 600, fontSize: 10}}>{user.tempUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT ? "+20 °F" : "+10 °C"} above target</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", flexDirection: "row", overflowX: "auto", gap: 2}}>
|
||||
{cables.map((cable, i) => (
|
||||
<Box key={i} sx={{ flexShrink: 0 }}>
|
||||
<Typography className={classes.headerCellStyle} sx={{ textAlign: "center" }}>
|
||||
{cable.name}
|
||||
</Typography>
|
||||
{cableTable(cable)}
|
||||
<Box sx={{ display: "flex", flexDirection: "row", overflowX: "auto", gap: 2, paddingBottom: 2}}>
|
||||
{cables.map((cable, i) => (
|
||||
<Box key={i} sx={{ flexShrink: 0 }}>
|
||||
<Typography className={classes.headerCellStyle} sx={{ textAlign: "center" }}>
|
||||
{cable.name}
|
||||
</Typography>
|
||||
{cableTable(cable)}
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { Box, Card, DialogContent, DialogTitle, Grid2, IconButton, LinearProgress, Switch, Typography } from "@mui/material";
|
||||
import { Box, Card, DialogContent, DialogTitle, Grid2, IconButton, LinearProgress, Slider, Switch, Tooltip, Typography } from "@mui/material";
|
||||
import { useMobile } from "hooks";
|
||||
import { Bin, Component, Device } from "models";
|
||||
import Bin3dVisualizer from "./components/bin3dVisualizer";
|
||||
|
|
@ -13,9 +13,12 @@ import BinDetails from "./components/binDetails";
|
|||
import { Plenum } from "models/Plenum";
|
||||
import BinSensorsDisplay from "../binSensorsDisplay";
|
||||
import ResponsiveDialog from "common/ResponsiveDialog";
|
||||
import { useState } from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import SearchSelect from "common/SearchSelect";
|
||||
import ChangeGrainDialog from "grain/ChangeGrainDialog";
|
||||
import { useGlobalState } from "providers";
|
||||
import GrainTransaction from "grain/GrainTransaction";
|
||||
import { cloneDeep } from "lodash";
|
||||
|
||||
interface Props {
|
||||
bin: Bin
|
||||
|
|
@ -32,13 +35,33 @@ interface Props {
|
|||
React.SetStateAction<Map<string, pond.BinComponentPreferences> | undefined>
|
||||
>;
|
||||
updateBinCallback?: (bin: Bin) => void
|
||||
setBin?: React.Dispatch<React.SetStateAction<Bin>>;
|
||||
|
||||
}
|
||||
export default function BinSummary(props: Props){
|
||||
const {bin, devices, fans, heaters, permissions, componentDevices, componentMap, binPrefs, updateBinCallback, cables = [], plenums = [], setPreferences} = props
|
||||
const {bin, devices, fans, heaters, permissions, componentDevices, componentMap, binPrefs, updateBinCallback, cables = [], plenums = [], setPreferences, setBin} = props
|
||||
//const [currentDevice, setCurrentDevice] = useState<Device | undefined>(undefined)
|
||||
const isMobile = useMobile()
|
||||
const [openGrainDialog, setOpenGrainDialog] = useState(false)
|
||||
const [manualFillPercent, setManualFillPercent] = useState(0)
|
||||
const [manualBushels, setManualBushels] = useState(0)
|
||||
const [{user}] = useGlobalState()
|
||||
const fillCapRef = useRef<HTMLSpanElement>(null);
|
||||
const [fillCapWidth, setFillCapWidth] = useState<number | undefined>(undefined);
|
||||
const [openNewTransaction, setOpenNewTransaction] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
if (fillCapRef.current) {
|
||||
// measure the max possible string width once
|
||||
fillCapRef.current.textContent = `${bin.grainCapacity(user)}/${bin.grainCapacity(user)}`;
|
||||
setFillCapWidth(fillCapRef.current.offsetWidth);
|
||||
}
|
||||
}, [bin, user]);
|
||||
|
||||
useEffect(()=>{
|
||||
setManualFillPercent(bin.fillPercent())
|
||||
setManualBushels(bin.bushels())
|
||||
},[bin])
|
||||
|
||||
// useEffect(() => {
|
||||
// if(devices.length > 0){
|
||||
|
|
@ -76,6 +99,18 @@ export default function BinSummary(props: Props){
|
|||
)
|
||||
}
|
||||
|
||||
const currentFill = () => {
|
||||
if(bin.inventoryControl() === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_MANUAL){
|
||||
if(user.grainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && bin.bushelsPerTonne() > 1){
|
||||
return Math.round((manualBushels / bin.bushelsPerTonne())*10)/10
|
||||
}else if (user.grainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && bin.bushelsPerTonne() > 1){
|
||||
return Math.round((manualBushels / (bin.bushelsPerTonne() * 0.907))*10)/10
|
||||
}
|
||||
return Math.round(manualBushels)
|
||||
}
|
||||
return bin.grainInventory(user)
|
||||
}
|
||||
|
||||
const inventorySummary = () => {
|
||||
return (
|
||||
<Card raised sx={{ marginBottom: 2 }}>
|
||||
|
|
@ -111,14 +146,58 @@ export default function BinSummary(props: Props){
|
|||
</Box>
|
||||
|
||||
{/* Bin Fill */}
|
||||
<Box sx={{ flexGrow: 1, maxWidth: 400, mx: 4 }}>
|
||||
<Box sx={{ flexGrow: 1, maxWidth: 450, mx: 4 }}>
|
||||
<Typography variant="caption" sx={{ color: grey[500] }}>
|
||||
Bin Fill
|
||||
</Typography>
|
||||
<Box display="flex" alignItems="center" gap={1} sx={{ mt: 0.5 }}>
|
||||
<Typography variant="body2" noWrap>
|
||||
{bin.binFillCap()}
|
||||
{/* hidden measuring span, renders off-screen */}
|
||||
<span
|
||||
ref={fillCapRef}
|
||||
style={{
|
||||
position: "absolute",
|
||||
visibility: "hidden",
|
||||
whiteSpace: "nowrap",
|
||||
fontSize: "0.875rem", // match body2
|
||||
}}
|
||||
/>
|
||||
<Typography variant="body2" noWrap sx={{ width: fillCapWidth, flexShrink: 0 }}>
|
||||
{currentFill()}/{bin.grainCapacity(user)}
|
||||
</Typography>
|
||||
{bin.inventoryControl() === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_MANUAL ?
|
||||
<Slider
|
||||
value={manualFillPercent}
|
||||
onChangeCommitted={() => {
|
||||
setOpenNewTransaction(true)
|
||||
}}
|
||||
onChange={(_, val) => {
|
||||
let fillPercent = val as number
|
||||
setManualFillPercent(fillPercent)
|
||||
let newBushels = (fillPercent/100) * bin.bushelCapacity()
|
||||
setManualBushels(newBushels)
|
||||
//this does casue the 3d bin to fill as you drag it but it throws off the transaction and the reset if you cancel
|
||||
// let clone = cloneDeep(bin)
|
||||
// let inventory = clone.settings.inventory ?? pond.BinInventory.create()
|
||||
// inventory.grainBushels = newBushels
|
||||
// if(setBin){
|
||||
// setBin(clone)
|
||||
// }
|
||||
}}
|
||||
min={0}
|
||||
max={100}
|
||||
sx={{
|
||||
flexGrow: 1,
|
||||
color: "#4caf50",
|
||||
"& .MuiSlider-thumb": {
|
||||
width: 16,
|
||||
height: 16,
|
||||
},
|
||||
"& .MuiSlider-rail": {
|
||||
backgroundColor: "rgba(255,255,255,0.1)",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
:
|
||||
<LinearProgress
|
||||
variant="determinate"
|
||||
value={bin.fillPercent()}
|
||||
|
|
@ -133,6 +212,10 @@ export default function BinSummary(props: Props){
|
|||
},
|
||||
}}
|
||||
/>
|
||||
}
|
||||
<Typography variant="body2" noWrap sx={{ width: 100 }}>
|
||||
{bin.inventoryControl() === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_MANUAL ? manualFillPercent : bin.fillPercent()}%
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
|
|
@ -141,15 +224,17 @@ export default function BinSummary(props: Props){
|
|||
<Typography variant="caption" sx={{ color: grey[500] }}>
|
||||
Last Updated
|
||||
</Typography>
|
||||
<Box display="flex" alignItems="center" gap={2} sx={{ mt: 0.5 }}>
|
||||
<Box display="flex" alignItems="center" gap={1}>
|
||||
<AccessTime sx={{ fontSize: 16, color: grey[400] }} />
|
||||
<Typography variant="body2" sx={{ color: grey[300] }}>
|
||||
{moment(bin.status.timestamp).fromNow()}
|
||||
</Typography>
|
||||
<Tooltip title="Bin Status will update whenever its settings change or a device with a connected sensor checks in">
|
||||
<Box display="flex" alignItems="center" gap={2} sx={{ mt: 0.5 }}>
|
||||
<Box display="flex" alignItems="center" gap={1}>
|
||||
<AccessTime sx={{ fontSize: 16, color: grey[400] }} />
|
||||
<Typography variant="body2" sx={{ color: grey[300] }}>
|
||||
{moment(bin.status.timestamp).fromNow()}
|
||||
</Typography>
|
||||
</Box>
|
||||
{activity(bin.status.timestamp)}
|
||||
</Box>
|
||||
{activity(bin.status.timestamp)}
|
||||
</Box>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
</Box>
|
||||
</Card>
|
||||
|
|
@ -158,6 +243,27 @@ export default function BinSummary(props: Props){
|
|||
|
||||
return (
|
||||
<Box padding={2}>
|
||||
<GrainTransaction
|
||||
open={openNewTransaction}
|
||||
mainObject={bin}
|
||||
grainAdjustment={manualBushels - bin.bushels()}
|
||||
close={(confirmed) => {
|
||||
//this resets all of the state variables used
|
||||
setOpenNewTransaction(false);
|
||||
if(!confirmed){
|
||||
setManualBushels(bin.bushels())
|
||||
setManualFillPercent(bin.fillPercent())
|
||||
}else{
|
||||
let clone = cloneDeep(bin)
|
||||
let inventory = clone.settings.inventory ?? pond.BinInventory.create()
|
||||
inventory.grainBushels = manualBushels
|
||||
if(setBin){
|
||||
setBin(clone)
|
||||
}
|
||||
}
|
||||
|
||||
}}
|
||||
/>
|
||||
<ChangeGrainDialog bin={bin} open={openGrainDialog} closeDialog={()=>setOpenGrainDialog(false)} permissions={permissions} updateBin={updateBinCallback}/>
|
||||
{inventorySummary()}
|
||||
<Grid2 container spacing={2}>
|
||||
|
|
|
|||
|
|
@ -300,7 +300,8 @@ export default function BinTableView(props: Props) {
|
|||
}}>
|
||||
Show All Cables
|
||||
</Button>
|
||||
<Tooltip title="testing">
|
||||
<Tooltip title="This table shows the bins levels using nodes that are in the grain averaged together. Data comes from the bins status.
|
||||
Use the button to see all of the cables individually.">
|
||||
<Info />
|
||||
</Tooltip>
|
||||
</Box>
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ interface Props {
|
|||
asDestination?: boolean;
|
||||
restrictMatching?: boolean;
|
||||
open: boolean;
|
||||
close: () => void;
|
||||
close: (confirmed?: boolean) => void;
|
||||
callback?: (newTransaction?: pond.Transaction) => void;
|
||||
allowAttachmentUploads?: boolean;
|
||||
}
|
||||
|
|
@ -82,7 +82,7 @@ export default function GrainTransaction(props: Props) {
|
|||
const [filePermission, setFilePermission] = useState(false);
|
||||
|
||||
const closeDialogs = (confirmed: boolean, newTransaction?: pond.Transaction) => {
|
||||
close();
|
||||
close(confirmed);
|
||||
setGrainChangeVal("0");
|
||||
setGrainEntry("0");
|
||||
setIsObject("");
|
||||
|
|
|
|||
|
|
@ -162,6 +162,11 @@ export class Bin {
|
|||
return colour;
|
||||
}
|
||||
|
||||
/**
|
||||
* this function returns the number of bushels in the bin, if using the automatic lidar or libracart to control inventory it will use the bushels in status
|
||||
* otherwise will use the bushels in the inventory found in settings
|
||||
* @returns (number) the current bushels in the bin
|
||||
*/
|
||||
public bushels(): number {
|
||||
let control = this.settings.inventory?.inventoryControl;
|
||||
let bushels = this.settings.inventory?.grainBushels || 0
|
||||
|
|
@ -172,6 +177,14 @@ export class Bin {
|
|||
return bushels
|
||||
}
|
||||
|
||||
/**
|
||||
* this function returns the bushelCapacity in the bins specs as it is stored or 0 if the specs are undefined
|
||||
* @returns (number) the capacity of the bin in bushels
|
||||
*/
|
||||
public bushelCapacity(): number {
|
||||
return this.settings.specs?.bushelCapacity ?? 0
|
||||
}
|
||||
|
||||
public fillPercent(): number {
|
||||
let fill = 0;
|
||||
if (this.settings.inventory && this.settings.specs) {
|
||||
|
|
@ -281,6 +294,12 @@ export class Bin {
|
|||
return bpt;
|
||||
}
|
||||
|
||||
/**
|
||||
* this function returns a bins stored inventory in the unit of the passed in user,
|
||||
* it can return it in bushels, US tons, or metric Tonnes
|
||||
* @param user the user object
|
||||
* @returns (number) bins current stored inventory
|
||||
*/
|
||||
public grainInventory(user: User): number {
|
||||
let grain = this.bushels()
|
||||
if(user.grainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && this.bushelsPerTonne() > 1){
|
||||
|
|
@ -291,6 +310,22 @@ export class Bin {
|
|||
return Math.round(grain*100)/100
|
||||
}
|
||||
|
||||
/**
|
||||
* this function returns a bins capacity in the unit of the passed in user,
|
||||
* it can return it in bushels, US tons, or metric Tonnes
|
||||
* @param user the user object
|
||||
* @returns (number) bins max capacity
|
||||
*/
|
||||
public grainCapacity(user: User): number {
|
||||
let capacity = this.bushelCapacity()
|
||||
if(user.grainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && this.bushelsPerTonne() > 1){
|
||||
capacity = capacity / this.bushelsPerTonne()
|
||||
}else if (user.grainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && this.bushelsPerTonne() > 1){
|
||||
capacity = capacity / (this.bushelsPerTonne() * 0.907)
|
||||
}
|
||||
return Math.round(capacity*100)/100
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the enum value for the inventory control in the bins inventory
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -553,6 +553,7 @@ export default function BinV2(){
|
|||
openSnack("Bin has Been Updated")
|
||||
})
|
||||
}}
|
||||
setBin={setBin}
|
||||
/>
|
||||
{/* render drawers */}
|
||||
{noteDrawer()}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue