frontend/src/grain/CustomGrainForm.tsx
2026-03-06 10:24:12 -06:00

225 lines
No EOL
8.6 KiB
TypeScript

import {MenuItem, TextField } from "@mui/material"
import { cloneDeep } from "lodash"
import { pond } from "protobuf-ts/pond"
import React, { useEffect, useRef, useState } from "react"
import { getGrainUnit } from "utils"
interface Props {
grainSettings?: pond.GrainSettings
onGrainSettingsChange: (settings: pond.GrainSettings, formValid: boolean) => void
}
export default function CustomGrainForm(props: Props) {
const {grainSettings, onGrainSettingsChange} = props
const [newGrainSettings, setNewGrainSettings] = useState(pond.GrainSettings.create())
const [name, setName] = useState("")
const [group, setGroup] = useState("")
const [equation, setEquation] = useState<pond.MoistureEquation>(pond.MoistureEquation.MOISTURE_EQUATION_NONE)
const [constantA, setConstantA] = useState("0")
const [constantB, setConstantB] = useState("0")
const [constantC, setConstantC] = useState("0")
const [kgPerBushel, setKgPerBushel] = useState("0")
const [bushelsConversion, setBushelConversion] = useState("0")//this is either per tonne or per US ton depending on user preferences
const valid = useRef(false)
useEffect(()=>{
if(grainSettings){
setName(grainSettings.name)
setGroup(grainSettings.group)
setEquation(grainSettings.equation)
setConstantA(grainSettings.a.toString())
setConstantB(grainSettings.b.toString())
setConstantC(grainSettings.c.toString())
setKgPerBushel(grainSettings.kgPerBushel.toString())
setBushelConversion(grainSettings.bushelsPerTonne.toString())
setNewGrainSettings(grainSettings)
}
},[grainSettings])
const validate = (
name: string,
group: string,
constA: string,
constB: string,
constC: string,
kgPerBushel: string,
bushelsPerTonne: string) => {
if (name === "") return false
if (group === "") return false
if (isNaN(parseFloat(constA))) return false
if (isNaN(parseFloat(constB))) return false
if (isNaN(parseFloat(constC))) return false
if (isNaN(parseFloat(kgPerBushel))) return false
if (isNaN(parseFloat(bushelsPerTonne))) return false
return true
}
const settingsChanged = (newSettings: pond.GrainSettings) => {
setNewGrainSettings(newSettings)
onGrainSettingsChange(newSettings, valid.current)
}
const grainForm = () => {
return (
<React.Fragment>
<TextField
sx={{marginBottom: 2}}
fullWidth
label="Name*"
value={name}
onChange={(e) => {
let name = e.target.value
setName(name)
let settings = cloneDeep(newGrainSettings)
settings.name = name
valid.current = validate(name, group, constantA, constantB, constantC, kgPerBushel, bushelsConversion)
settingsChanged(settings)
}}/>
<TextField
sx={{marginBottom: 2}}
fullWidth
label="Group*"
value={group}
onChange={(e) => {
let group = e.target.value
setGroup(group)
let settings = cloneDeep(newGrainSettings)
settings.group = group
valid.current = validate(name, group, constantA, constantB, constantC, kgPerBushel, bushelsConversion)
settingsChanged(settings)
}}/>
<TextField
sx={{marginBottom: 2}}
fullWidth
value={equation}
helperText={"Not selecting an EMC equation to use will return the humidity instead of EMC"}
label="EMC Equation"
onChange={(e) => {
let enumVal = parseFloat(e.target.value)
setEquation(enumVal)
let settings = cloneDeep(newGrainSettings)
settings.equation = enumVal
valid.current = validate(name, group, constantA, constantB, constantC, kgPerBushel, bushelsConversion)
settingsChanged(settings)
}}
select>
<MenuItem key={pond.MoistureEquation.MOISTURE_EQUATION_NONE} value={pond.MoistureEquation.MOISTURE_EQUATION_NONE}>
None
</MenuItem>
<MenuItem key={pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST} value={pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST}>
Chung-Pfost
</MenuItem>
<MenuItem key={pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON} value={pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON}>
Henderson
</MenuItem>
<MenuItem key={pond.MoistureEquation.MOISTURE_EQUATION_HALSEY} value={pond.MoistureEquation.MOISTURE_EQUATION_HALSEY}>
Halsey
</MenuItem>
<MenuItem key={pond.MoistureEquation.MOISTURE_EQUATION_OSWIN} value={pond.MoistureEquation.MOISTURE_EQUATION_OSWIN}>
Oswin
</MenuItem>
</TextField>
<TextField
sx={{marginBottom: 2}}
fullWidth
type="number"
value={constantA}
error={isNaN(parseFloat(constantA))}
helperText={isNaN(parseFloat(constantA)) ? "Must be a valid number" : ""}
onChange={(e) => {
let val = e.target.value
setConstantA(val)
valid.current = validate(name, group, val, constantB, constantC, kgPerBushel, bushelsConversion)
let settings = cloneDeep(newGrainSettings)
if(!isNaN(parseFloat(val))){
settings.a = parseFloat(val)
}
settingsChanged(settings)
}}
label="Constant A"/>
<TextField
sx={{marginBottom: 2}}
fullWidth
type="number"
value={constantB}
error={isNaN(parseFloat(constantB))}
helperText={isNaN(parseFloat(constantB)) ? "Must be a valid number" : ""}
onChange={(e) => {
let val = e.target.value
setConstantB(val)
valid.current = validate(name, group, constantA, val, constantC, kgPerBushel, bushelsConversion)
let settings = cloneDeep(newGrainSettings)
if(!isNaN(parseFloat(val))){
settings.b = parseFloat(val)
}
settingsChanged(settings)
}}
label="Constant B"/>
<TextField
sx={{marginBottom: 2}}
fullWidth
type="number"
value={constantC}
error={isNaN(parseFloat(constantC))}
helperText={isNaN(parseFloat(constantC)) ? "Must be a valid number" : ""}
onChange={(e) => {
let val = e.target.value
setConstantC(val)
valid.current = validate(name, group, constantA, constantB, val, kgPerBushel, bushelsConversion)
let settings = cloneDeep(newGrainSettings)
if(!isNaN(parseFloat(val))){
settings.c = parseFloat(val)
}
settingsChanged(settings)
}}
label="Constant C"/>
<TextField
sx={{marginBottom: 2}}
fullWidth
type="number"
value={kgPerBushel}
error={isNaN(parseFloat(kgPerBushel))}
helperText={isNaN(parseFloat(kgPerBushel)) ? "Must be a valid number" : ""}
onChange={(e) => {
let val = e.target.value
setKgPerBushel(val)
valid.current = validate(name, group, constantA, constantB, constantC, val, bushelsConversion)
let settings = cloneDeep(newGrainSettings)
if(!isNaN(parseFloat(val))){
settings.kgPerBushel = parseFloat(val)
}
settingsChanged(settings)
}}
label="kg per Bushel"/>
<TextField
sx={{marginBottom: 2}}
fullWidth
type="number"
value={bushelsConversion}
error={isNaN(parseFloat(bushelsConversion))}
helperText={isNaN(parseFloat(bushelsConversion)) ? "Must be a valid number" : ""}
onChange={(e) => {
let val = e.target.value
setBushelConversion(val)
valid.current = validate(name, group, constantA, constantB, constantC, kgPerBushel, val)
let settings = cloneDeep(newGrainSettings)
if(!isNaN(parseFloat(val))){
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON){
settings.bushelsPerTonne = parseFloat(val)/0.907
}else{
settings.bushelsPerTonne = parseFloat(val)
}
}
settingsChanged(settings)
}}
label={"Bushels per " + (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE ? " Tonne" : "Ton")}/>
</React.Fragment>
)
}
return (
<React.Fragment>
{grainForm()}
</React.Fragment>
)
}