frontend/src/pages/Heaters.tsx
2025-10-21 13:41:20 -06:00

191 lines
6.2 KiB
TypeScript

import { List, Typography } from "@mui/material";
import DeviceLinkDrawer from "common/DeviceLinkDrawer";
import ResponsiveTable, { Column } from "common/ResponsiveTable";
//import { getTableIcons } from "common/ResponsiveTable";
import { useMobile } from "hooks";
import { cloneDeep } from "lodash";
//import MaterialTable from "material-table";
import { Device } from "models";
import { ObjectHeater } from "models/ObjectHeater";
import AddObjectHeaterFab from "objectHeater/AddObjectHeaterFab";
import ObjectHeaterCard from "objectHeater/ObjectHeaterCard";
import ObjectHeaterSettings from "objectHeater/ObjectHeaterSettings";
import { pond } from "protobuf-ts/pond";
import { useGlobalState, useObjectHeaterAPI } from "providers";
import { useCallback, useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
//import { useHistory } from "react-router";
import PageContainer from "./PageContainer";
export default function Heaters() {
const [heaterDialog, setHeaterDialog] = useState(false);
const objectHeaterAPI = useObjectHeaterAPI();
const [{ as }] = useGlobalState();
//const history = useHistory();
const navigate = useNavigate();
const [heaters, setHeaters] = useState<pond.ObjectHeaterData[]>([]);
const [openLinkDrawer, setOpenLinkDrawer] = useState(false);
const [devices, setDevices] = useState<Map<string, pond.ComprehensiveDevice>>(
new Map<string, pond.ComprehensiveDevice>()
);
const [heaterToLink, setHeaterToLink] = useState<ObjectHeater>();
const isMobile = useMobile();
const [tablePage, setTablePage] = useState(0)
const [pageSize, setPageSize] = useState(10)
const [total, setTotal] = useState(0)
const [searchText, setSearchText] = useState("")
const loadData = useCallback(() => {
objectHeaterAPI
.listObjectHeatersPageData(pageSize, tablePage * pageSize, undefined, undefined, searchText, as)
.then(resp => {
// setHeaters(resp.data.heaterData ?? []);
setTotal(resp.data.total)
setHeaters(resp.data.heaterData ?? []);
});
}, [objectHeaterAPI, as, pageSize, tablePage, searchText]);
useEffect(() => {
loadData();
}, [loadData]);
const goToHeater = (row: pond.ObjectHeaterData) => {
let path = "/heaters/" + row.heater?.key;
navigate(path, {state: { heater: row.heater, devices: row.devices}})
};
const handleChange = (event: any) => {
setPageSize(event.target.value);
};
const columns = (): Column<pond.ObjectHeaterData>[] => {
return [
{
title: "Heater",
cellStyle: {padding: 2},
render: row => (<Typography>{row.heater?.name}</Typography>)
},
{
title: "Site",
cellStyle: {padding: 2},
render: row => (<Typography>{row.site?.settings?.siteName}</Typography>)
},
{
title: "Make",
cellStyle: {padding: 2},
render: row => (<Typography>{row.heater?.settings?.make}</Typography>)
},
{
title: "Model",
cellStyle: {padding: 2},
render: row => (<Typography>{row.heater?.settings?.model}</Typography>)
},
// {
// title: "Device",
// cellStyle: {padding: 2},
// render: row => {
// let display: string | number | undefined = "No Device Found"
// if (row.devices.length > 0) {
// if (row.devices[0].device?.settings?.name) {
// display = row.devices[0].device?.settings?.name;
// } else {
// display = row.devices[0].device?.settings?.deviceId;
// }
// }
// return (<Typography>{display}</Typography>)
// }
// }
]
}
const desktopTable = () => {
return (
<ResponsiveTable<pond.ObjectHeaterData>
title={"Heaters"}
page={tablePage}
setSearchText={(text) => {setSearchText(text)}}
pageSize={pageSize}
total={total}
rows={heaters}
columns={columns}
setPage={(page)=>{setTablePage(page)}}
handleRowsPerPageChange={handleChange}
onRowClick={goToHeater}
loadMore={()=>{
let current = cloneDeep(heaters)
objectHeaterAPI
.listObjectHeatersPageData(pageSize, current.length, undefined, undefined, searchText, as)
.then(resp => {
setHeaters(heaters.concat(resp.data.heaterData));
});
}}
renderMobile={(row)=>{
return (
<ObjectHeaterCard
key={row.heater?.key}
heaterData={row}
linkDevice={(heater, linkedDevices) => {
setHeaterToLink(heater);
setOpenLinkDrawer(true);
let d = new Map<string, pond.ComprehensiveDevice>();
linkedDevices.forEach(compDev => {
let device = Device.any(compDev.device);
d.set(device.id().toString(), compDev);
});
setDevices(d);
}}
/>
)
}}
/>
)
};
return (
<PageContainer>
{isMobile && (
<DeviceLinkDrawer
open={openLinkDrawer}
close={() => {
setOpenLinkDrawer(false);
}}
linkedDevices={devices}
updateLinkedDevices={(dev, linked) => {
let deviceID = dev.device?.settings?.deviceId;
if (deviceID && heaterToLink) {
if (linked) {
objectHeaterAPI
.updateLink(heaterToLink.key, "objectHeater", deviceID.toString(), "device", [
"read",
"write",
"grant",
"revoke"
], as)
.then(resp => {
if (deviceID) {
devices.set(deviceID.toString(), dev);
setOpenLinkDrawer(false);
loadData();
}
});
}
}
}}
/>
)}
<ObjectHeaterSettings
open={heaterDialog}
close={() => {
setHeaterDialog(false);
}}
/>
<AddObjectHeaterFab
onClick={() => {
setHeaterDialog(true);
}}
pulse={heaters.length < 1}
/>
{desktopTable()}
</PageContainer>
);
}