created a change grain dialog component and made the grain display a 'button' to be able to change the grain without going into the settings
This commit is contained in:
parent
dc52ef77a7
commit
b8a49197cb
3 changed files with 263 additions and 107 deletions
175
src/grain/ChangeGrainDialog.tsx
Normal file
175
src/grain/ChangeGrainDialog.tsx
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
import { Box, Button, DialogActions, DialogContent, DialogTitle, Grid2, Switch, TextField } from "@mui/material";
|
||||
import ResponsiveDialog from "common/ResponsiveDialog";
|
||||
import SearchSelect, { Option } from "common/SearchSelect";
|
||||
import { Bin } from "models";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
import GrainDescriber, { GrainOptions, ToGrainOption } from "grain/GrainDescriber";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import React from "react";
|
||||
import CustomGrainSelector from "./CustomGrainSelector";
|
||||
import { cloneDeep } from "lodash";
|
||||
import { useBinAPI, useSnackbar } from "providers";
|
||||
|
||||
interface Props {
|
||||
bin: Bin
|
||||
open: boolean
|
||||
closeDialog: () => void
|
||||
permissions: pond.Permission[]
|
||||
/**
|
||||
* this function can be passed in if you want to just return a new bin with the changes and handle the actual update in the parent,
|
||||
* it will stop the component from doing the update itself
|
||||
* @param bin the bin with the new changes
|
||||
* @returns
|
||||
*/
|
||||
updateBin?: (bin: Bin) => void
|
||||
/**
|
||||
* this function can be passed in as a callback function if the component handles the update
|
||||
* @param updated whether the bin api was used to update the bin
|
||||
* @returns
|
||||
*/
|
||||
updateCallback?: (bin: Bin) => void
|
||||
}
|
||||
|
||||
export default function ChangeGrainDialog(props: Props){
|
||||
const { bin, open, permissions, closeDialog, updateBin, updateCallback } = props
|
||||
const canEdit = useMemo(()=>{
|
||||
return permissions ? permissions.includes(pond.Permission.PERMISSION_WRITE) : false;
|
||||
},[permissions])
|
||||
|
||||
const [isCustom, setIsCustom] = useState(false)
|
||||
const grainOptions = GrainOptions();
|
||||
const [grainOption, setGrainOption] = useState<Option>();
|
||||
const [newGrainType, setNewGrainType] = useState<pond.Grain>(0);
|
||||
const [newGrainSettings, setNewGrainSettings] = useState<pond.GrainSettings | undefined>()
|
||||
const binAPI = useBinAPI()
|
||||
const {openSnack} = useSnackbar()
|
||||
const [grainSubtype, setGrainSubtype] = useState("")
|
||||
|
||||
useEffect(()=>{
|
||||
setGrainOption(ToGrainOption(bin.grain()))
|
||||
setIsCustom(bin.grain() === pond.Grain.GRAIN_CUSTOM)
|
||||
setGrainSubtype(bin.subtype())
|
||||
setNewGrainType(bin.grain())
|
||||
},[bin])
|
||||
|
||||
/**
|
||||
* this function is where the split happens,
|
||||
* if update bin is passed in it will just clone the bin, change the settings and pass the updated clone to the parent so that it can handle the api call
|
||||
* otherwise the component will update the bin itself through the bin api and upon completion pass that updated bin to the parent if successfull
|
||||
* in the event both functions are passed in the parent update will be given priority and the internal update will not occur
|
||||
*/
|
||||
const updateBinSettings = () => {
|
||||
let clone = cloneDeep(bin)
|
||||
let inventory = clone.settings.inventory ?? pond.BinInventory.create()
|
||||
inventory.grainType = newGrainType
|
||||
inventory.customGrain = newGrainSettings
|
||||
inventory.grainSubtype = grainSubtype
|
||||
if(updateBin){
|
||||
//simply pass the clone up to the parent and it can deal with it
|
||||
updateBin(clone)
|
||||
}else if (updateCallback) {
|
||||
//use the actual bin api to update the bin inside the component and upon completion return the updated bin
|
||||
binAPI.updateBin(bin.key(), clone.settings).then(resp => {
|
||||
openSnack("Updated the grain type")
|
||||
updateCallback(clone)
|
||||
}).catch(err => {
|
||||
openSnack("There was a problem changing the grain type")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
//closes the dialog
|
||||
const close = () => {
|
||||
closeDialog()
|
||||
}
|
||||
|
||||
return (
|
||||
<ResponsiveDialog
|
||||
open={open}
|
||||
onClose={close}>
|
||||
<DialogTitle>Change Grain Type</DialogTitle>
|
||||
<DialogContent>
|
||||
<Grid2 container justifyContent="space-between" alignItems="center">
|
||||
<Grid2>
|
||||
<Grid2 container alignItems="center">
|
||||
<Grid2 >Grain</Grid2>
|
||||
<Grid2 >
|
||||
<Switch
|
||||
color="default"
|
||||
value={isCustom}
|
||||
checked={isCustom}
|
||||
onChange={(_, checked) => {
|
||||
setIsCustom(checked)
|
||||
if(checked){
|
||||
setNewGrainType(pond.Grain.GRAIN_CUSTOM)
|
||||
}else{
|
||||
setNewGrainType(bin.grain())
|
||||
setNewGrainSettings(undefined)
|
||||
}
|
||||
}}
|
||||
name="storage"
|
||||
/>
|
||||
</Grid2>
|
||||
<Grid2 >Custom</Grid2>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
{!isCustom && (
|
||||
<Box>
|
||||
<SearchSelect
|
||||
label="Type"
|
||||
selected={grainOption}
|
||||
changeSelection={option => {
|
||||
let newGrainType = option
|
||||
? pond.Grain[option.value as keyof typeof pond.Grain]
|
||||
: pond.Grain.GRAIN_INVALID;
|
||||
setGrainOption(ToGrainOption(newGrainType));
|
||||
setNewGrainType(newGrainType);
|
||||
//setBushPerTonne(GrainDescriber(newGrainType).bushelsPerTonne.toFixed(2));
|
||||
}}
|
||||
group
|
||||
disabled={!canEdit}
|
||||
options={grainOptions}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
{isCustom ? (
|
||||
<React.Fragment>
|
||||
<CustomGrainSelector initialGrain={bin.customGrain()} onGrainSettingsChange={settings => {setNewGrainSettings(settings)}}/>
|
||||
</React.Fragment>
|
||||
) : (
|
||||
<TextField
|
||||
sx={{marginTop: 2}}
|
||||
label="Grain Variant"
|
||||
value={grainSubtype}
|
||||
type="text"
|
||||
onChange={event => {
|
||||
setGrainSubtype(event.target.value);
|
||||
}}
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
disabled={!grainOption}
|
||||
/>
|
||||
)}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
onClick={() => {
|
||||
close();
|
||||
}}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
// disabled={grainErrorCheck()}
|
||||
onClick={() => {
|
||||
updateBinSettings();
|
||||
close()
|
||||
}}>
|
||||
Confirm
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</ResponsiveDialog>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue