added the bin fans table to the bins page

This commit is contained in:
csawatzky 2025-04-11 14:20:51 -06:00
parent 2e3458cc22
commit 6b5697e075
2 changed files with 268 additions and 3 deletions

View file

@ -0,0 +1,265 @@
import {
Box,
Button,
DialogActions,
DialogContent,
Grid2 as Grid,
IconButton
} from "@mui/material";
// import { getTableIcons } from "common/ResponsiveTable";
// import MaterialTable, { Column } from "material-table";
import { Bin } from "models";
import { useBinAPI, useGlobalState, useSnackbar } from "providers";
import fans from "fans/fans_client.json";
import React, { useState, useEffect } from "react";
import { getThemeType } from "theme";
import AerationFanIcon from "products/AgIcons/AerationFanIcon";
import FanPicker from "fans/fanPicker";
import ResponsiveDialog from "common/ResponsiveDialog";
import { useMobile } from "hooks";
import { makeStyles } from "@mui/styles";
import ResponsiveTable, { Column } from "common/ResponsiveTable";
import { cloneDeep } from "lodash";
const useStyles = makeStyles(() => ({
dark: {
backgroundColor: getThemeType() === "light" ? "rgb(245, 245, 245)" : "rgb(50, 50, 50)",
padding: 5
},
light: {
backgroundColor: getThemeType() === "light" ? "rgb(235, 235, 235)" : "rgb(60, 60, 60)",
padding: 5
}
})
);
interface jsonFan {
id: number;
name: string;
kind: string;
rpm: number;
diameter: number;
horsepower: number;
}
interface BinRow {
bin: Bin;
fan?: jsonFan;
}
interface Props {
isLoading: boolean;
bins: Bin[];
getControllerInfo?: (totalControllers: number, onControllers: number) => void;
}
export default function BinsFansStatusTable(props: Props) {
const [{ as }] = useGlobalState();
const binAPI = useBinAPI();
const { bins, isLoading, getControllerInfo } = props;
const { openSnack } = useSnackbar();
const [tableData, setTableData] = useState<BinRow[]>([]);
const [displayedRows, setDisplayedRows] = useState<BinRow[]>([]);
const [fanMap, setFanMap] = useState<Map<number, jsonFan>>(new Map());
const isMobile = useMobile();
const [tablePage, setTablePage] = useState(0);
const [pageSize, setPageSize] = useState(10);
const [openPickerDialog, setOpenPickerDialog] = useState(false);
const [selectedBinRow, setSelectedBinRow] = useState<BinRow | undefined>();
const [newFanID, setNewFanID] = useState<number | undefined>();
const classes = useStyles();
useEffect(()=>{
let clone: BinRow[] = cloneDeep(tableData)
let rows = clone.splice(tablePage * pageSize, pageSize)
setDisplayedRows(rows)
},[tableData, tablePage, pageSize])
//define the columns for the desktop table
const columns: Column<BinRow>[] = [
{
title: "Set Fan",
cellStyle: {padding: 2},
render: (row) => <Box>
<IconButton
onClick={() => {
setSelectedBinRow(row);
setOpenPickerDialog(true);
}}
>
<AerationFanIcon />
</IconButton>
</Box>
},
{
title: "Bin",
cellStyle: {padding: 2},
render: (row) => <Box>{row.bin.settings.name}</Box>
},
{
title: "Bin Fan",
cellStyle: {padding: 2},
hidden: isMobile,
render: row => {
if (row.fan) {
return <Box>{row.fan.name}</Box>
} else {
return <Box>"No Fan Set on Bin"</Box>
}
}
},
{
title: "Fan Type",
cellStyle: {padding: 2},
hidden: isMobile,
render: (row) => <Box>{row.fan?.kind}</Box>
},
{
title: "Horsepower",
cellStyle: {padding: 2},
hidden: isMobile,
render: (row) => <Box>{row.fan?.horsepower}</Box>
},
//the controllers
{
title: "Fan Controllers",
cellStyle: {padding: 2},
render: row => {
if (row.bin.status.fans.length > 0) {
return (
<Grid container direction="column" alignItems="center">
{row.bin.status.fans.map((binFan, i) => (
<Grid
key={i}
container
direction="row"
justifyContent="space-between"
className={i % 2 === 0 ? classes.dark : classes.light}>
<Grid>{binFan.name}</Grid>
<Grid>{binFan.state ? "On" : "Off"}</Grid>
</Grid>
))}
</Grid>
);
} else {
return <Box>No Controllers attached to this bin</Box>
}
}
}
];
useEffect(() => {
//build the fanmap
let fanMap: Map<number, jsonFan> = new Map();
fans["bulk"].forEach(fan => {
fanMap.set(fan.id, fan);
});
setFanMap(fanMap);
let data: BinRow[] = [];
let dataMap: Map<string, BinRow> = new Map();
let totalControllers = 0;
let onControllers = 0;
bins.forEach(bin => {
//put the bin in the row
let row: BinRow = {
bin: bin
};
//if the bin has a fan id set get it from the json and put it in the row data
if (bin.fanID() !== 0) {
row.fan = fanMap.get(bin.fanID());
}
data.push(row);
dataMap.set(bin.key(), row);
//add to the controller numbers
bin.status.fans.forEach(fan => {
//add to the total for each fan
totalControllers++;
//if the fan is on add to the count for controllers that are on
if (fan.state) {
onControllers++;
}
});
});
setTableData(data);
//setTableDataMap(dataMap)
if (getControllerInfo) {
getControllerInfo(totalControllers, onControllers);
}
}, [as, bins, getControllerInfo]);
const updateBinFan = () => {
if (selectedBinRow && newFanID) {
//use the bin api to update the bin in the selected row
let bin = selectedBinRow.bin;
bin.settings.fanId = newFanID;
binAPI
.updateBin(bin.key(), bin.settings)
.then(resp => {
//when an update succeeds update the table with the fan information
//let dataMap = tableDataMap
selectedBinRow.bin = bin;
selectedBinRow.fan = fanMap.get(newFanID);
openSnack("Updated bin with new fan");
//close dialog
setOpenPickerDialog(false);
})
.catch(err => {
openSnack("failed to update bin with new fan");
});
}
};
const fanPickerDialog = () => {
return (
<ResponsiveDialog
open={openPickerDialog}
onClose={() => {
setOpenPickerDialog(false);
}}>
<DialogContent>
<FanPicker
updateFan={fanID => {
setNewFanID(fanID);
}}
useCardView
/>
</DialogContent>
<DialogActions>
<Button
onClick={() => {
setOpenPickerDialog(false);
}}>
Cancel
</Button>
<Button onClick={updateBinFan} variant="contained" color="primary">
Confirm
</Button>
</DialogActions>
</ResponsiveDialog>
);
};
//function to make the table
const fanStatusTable = () => {
return (
<ResponsiveTable
rows={displayedRows}
isLoading={isLoading}
columns={columns}
page={tablePage}
pageSize={pageSize}
total={tableData.length}
setPage={(page)=>{setTablePage(page)}}
handleRowsPerPageChange={(e)=>{setPageSize(e.target.value)}}
/>
);
};
return (
<React.Fragment>
{fanStatusTable()}
{fanPickerDialog()}
</React.Fragment>
);
}

View file

@ -40,7 +40,7 @@ import {
ViewComfy,
ViewList
} from "@mui/icons-material";
// import BinsFansStatusTable from "bin/BinFansStatusTable";
import BinsFansStatusTable from "bin/BinFansStatusTable";
// import BinSettings from "bin/BinSettings";
import BinsList from "bin/BinsList";
// import BinYard from "bin/BinYard";
@ -1013,14 +1013,14 @@ export default function Bins(props: Props) {
</Typography>
</AccordionSummary>
<AccordionDetails>
{/* <BinsFansStatusTable
<BinsFansStatusTable
bins={paginatedBins.bins}
isLoading={binsLoading}
getControllerInfo={(total, on) => {
setTotalFanControllers(total);
setTotalFanControllersOn(on);
}}
/> */}
/>
</AccordionDetails>
</Accordion>
);