import { DialogActions, DialogContent, DialogTitle, MenuItem, Select, TextField, Button, Grid2 as Grid, Box, InputAdornment, Stepper, Step, StepLabel, Tabs, Tab } from "@mui/material"; import ResponsiveDialog from "common/ResponsiveDialog"; import { Terminal } from "models/Terminal"; import { Gate } from "models/Gate"; import { pond } from "protobuf-ts/pond"; import { useTerminalAPI, useGateAPI, useGlobalState } from "providers"; import React, { useEffect, useState } from "react"; import { useSnackbar } from "hooks"; //import { useHistory } from "react-router"; import { useNavigate } from "react-router-dom"; import DuctDescriber, { DuctOptions, FindDuctType } from "ducting/DuctDescriber"; interface DuctProps { diameter: number; length: number; thermalConductivity: number; thermalResistance: number; frictionFactor: number; } interface Props { open: boolean; close: (newGate?: Gate) => void; terminals?: Terminal[]; gate?: Gate; long?: number; lat?: number; } const steps = ["Gate", "Duct"]; export default function GateSettings(props: Props) { const { open, close, terminals, gate, long, lat } = props; const [{as}] = useGlobalState(); const [gateName, setGateName] = useState(""); const [lowerFlowBound, setLowerFlowBound] = useState(0); const [upperFlowBound, setUpperFlowBound] = useState(0); const [terminalOptions, setTerminalOptions] = useState(terminals); const [terminalKey, setTerminalKey] = useState(""); const gateAPI = useGateAPI(); const terminalAPI = useTerminalAPI(); const [loadingTerminals, setLoadingTerminals] = useState(false); const [removeDialog, setRemoveDialog] = useState(false); const { openSnack } = useSnackbar(); //const history = useHistory(); const navigate = useNavigate(); const ductOptions = DuctOptions(); const [ductType, setDuctType] = useState(0); const [ductName, setDuctName] = useState(""); const [ductProps, setDuctProps] = useState({ diameter: 0, length: 0, frictionFactor: 0, thermalConductivity: 0, thermalResistance: 0 }); const [pcaUnit, setPcaUnit] = useState(""); const [activeStep, setActiveStep] = useState(0); //user set identifier to be shown on the marker on the map const [terminalIdentifier, setTerminalIdentifier] = useState(""); const [gateIdentifier, setGateIdentifier] = useState(""); const [idleLimit, setIdleLimit] = useState(0); const [hourlyPCA, setHourlyPCA] = useState(0); const [hourlyAPU, setHourlyAPU] = useState(0); useEffect(() => { if (!terminals) { if (loadingTerminals) return; setLoadingTerminals(true); terminalAPI .listTerminals(500, 0, undefined, undefined, undefined, as) .then(resp => { setTerminalOptions(resp.data.terminals.map(a => Terminal.any(a))); }) .catch(err => {}) .finally(() => { setLoadingTerminals(false); }); } else { setTerminalOptions(terminals); } //eslint-disable-next-line react-hooks/exhaustive-deps }, [terminals, terminalAPI, as]); useEffect(() => { if (gate) { setGateName(gate.name); setTerminalKey(gate.terminal()); setDuctProps({ diameter: gate.settings.ductDiameter, length: gate.settings.ductLength, frictionFactor: gate.settings.frictionFactor, thermalConductivity: gate.settings.thermalConductivity, thermalResistance: gate.settings.thermalResistance }); let currentType = FindDuctType( gate.settings.thermalResistance, gate.settings.thermalConductivity, gate.settings.frictionFactor ); setDuctType(currentType); setLowerFlowBound(gate.lowerFlow()); setUpperFlowBound(gate.upperFlow()); setPcaUnit(gate.settings.pcaType); setDuctName(gate.settings.ductName); setTerminalIdentifier(gate.settings.letterIdentifier ?? ""); setGateIdentifier(gate.settings.numberIdentifier ?? ""); setHourlyAPU(gate.settings.hourlyApuCost ?? 0); setHourlyPCA(gate.settings.hourlyPcaCost ?? 0); } else { setGateName(""); setTerminalKey(""); } }, [gate]); const confirm = () => { if (gate) { let settings = gate.settings; settings.terminal = terminalKey; settings.ductDiameter = ductProps.diameter; settings.ductLength = ductProps.length; settings.frictionFactor = ductProps.frictionFactor; settings.thermalConductivity = ductProps.thermalConductivity; settings.thermalResistance = ductProps.thermalResistance; settings.lowerFlow = lowerFlowBound; settings.upperFlow = upperFlowBound; settings.idleFlow = idleLimit; settings.ductName = ductName; settings.pcaType = pcaUnit; settings.letterIdentifier = terminalIdentifier; settings.numberIdentifier = gateIdentifier.toString(); settings.hourlyApuCost = hourlyAPU; settings.hourlyPcaCost = hourlyPCA; gateAPI .updateGate(gate.key, gateName, settings, as) .then(resp => { openSnack("Gate update"); close(); }) .catch(err => { openSnack("Failed to update gate"); }); } else { let settings: pond.GateSettings = pond.GateSettings.create({ longitude: long, latitude: lat, terminal: terminalKey, ductDiameter: ductProps.diameter, ductLength: ductProps.length, frictionFactor: ductProps.frictionFactor, thermalConductivity: ductProps.thermalConductivity, thermalResistance: ductProps.thermalResistance, lowerFlow: lowerFlowBound, upperFlow: upperFlowBound, idleFlow: idleLimit, ductName: ductName, pcaType: pcaUnit, letterIdentifier: terminalIdentifier, numberIdentifier: gateIdentifier.toString(), hourlyApuCost: hourlyAPU, hourlyPcaCost: hourlyPCA }); gateAPI .addGate(gateName, settings, as) .then(resp => { openSnack("New gate added"); let newGate = Gate.create( pond.Gate.create({ key: resp.data.key, name: gateName, settings: settings }) ); close(newGate); }) .catch(err => { openSnack("There was a problem adding your gate"); }); } }; const remove = () => { if (gate) { gateAPI .removeGate(gate.key, as) .then(resp => { openSnack("Gate Deleted"); }) .catch(err => { openSnack("Failed to delete gate"); }) .finally(() => { navigate("/terminals"); }); } }; const stepper = () => { if (gate === undefined) { return ( {steps.map(label => { const stepProps: { completed?: boolean } = {}; const labelProps: { optional?: React.ReactNode; } = {}; return ( {label} ); })} ); } return ( setActiveStep(value)} indicatorColor="primary" textColor="primary" variant="fullWidth" aria-label="bin tabs" //classes={{ root: classes.tabs }} > {steps.map((step, i) => ( ))} ); }; const stepperContent = (step: number) => { switch (step) { case 1: return ductProperties(); default: return gateProperties(); } }; const gateProperties = () => { //build list of letters for select box let tiOptions: JSX.Element[] = []; //adds the letters to the terminal id options for (let l = 65; l <= 90; l++) { tiOptions.push( {String.fromCharCode(l)} ); } //add numbers 1-9 for terminal id options for (let n = 1; n <= 9; n++) { tiOptions.push( {n} ); } let numberOptions: JSX.Element[] = []; for (let n = 0; n <= 99; n++) { numberOptions.push( {n} ); } return ( setGateName(e.target.value)} /> { setTerminalKey(e.target.value as string); }}> Select Terminal {terminalOptions?.map(terminal => ( {terminal.name} ))} setLowerFlowBound(+e.target.value)} /> setUpperFlowBound(+e.target.value)} /> setIdleLimit(+e.target.value)} /> setPcaUnit(e.target.value)} /> { setTerminalIdentifier(e.target.value as string); }}> Gate Letter {tiOptions} setGateIdentifier(e.target.value)}> Gate Number {numberOptions} $/hr }} onChange={e => setHourlyPCA(+e.target.value)} /> $/hr }} onChange={e => setHourlyAPU(+e.target.value)} /> ); }; const ductProperties = () => { return ( { let type = +e.target.value; setDuctType(type); setDuctName("custom"); if (type > 1) { let describer = DuctDescriber(type); setDuctName(describer.name); setDuctProps({ diameter: ductProps.diameter, frictionFactor: describer.frictionFactor, length: ductProps.length, thermalConductivity: describer.thermalConductivity, thermalResistance: describer.thermalResistance }); } }}> Select Ducting Type {ductOptions.map(duct => ( {duct.label} ))} Custom mm }} onChange={e => { setDuctProps({ ...ductProps, diameter: parseFloat(e.target.value) }); }} /> m }} onChange={e => { setDuctProps({ ...ductProps, length: parseFloat(e.target.value) }); }} /> W/mK }} onChange={e => { setDuctProps({ ...ductProps, thermalConductivity: parseFloat(e.target.value) }); setDuctType(1); setDuctName("custom"); }} /> { setDuctProps({ ...ductProps, frictionFactor: parseFloat(e.target.value) }); setDuctType(1); setDuctName("custom"); }} /> K/W }} onChange={e => { setDuctProps({ ...ductProps, thermalResistance: parseFloat(e.target.value) }); setDuctType(1); setDuctName("custom"); }} /> ); }; const removeConfirmation = () => { return ( setRemoveDialog(false)}> Delete Gate Are you sure you wish to delete this gate? ); }; return ( close()}> {removeConfirmation()} {stepper()} {stepperContent(activeStep)} {gate && ( )} {(gate || activeStep === 0) && ( )} {!gate && activeStep > 0 && ( )} {(gate || activeStep === 1) && ( )} {!gate && activeStep === 0 && ( )} ); }