diff --git a/src/bin/BinTour.tsx b/src/bin/BinTour.tsx index a685ada..e885527 100644 --- a/src/bin/BinTour.tsx +++ b/src/bin/BinTour.tsx @@ -1,6 +1,6 @@ // import { useAuth0 } from "@auth0/auth0-react"; import { Typography } from "@mui/material"; -import Tour from "common/Tour"; +import Tour, { TourStep } from "common/Tour"; import { random } from "lodash"; import moment from "moment"; import { useGlobalState, useSnackbar, useUserAPI } from "providers"; @@ -8,8 +8,13 @@ import React, { useEffect, useState } from "react"; import { Step } from "react-joyride"; // import Emoji from "react-emoji-render"; -export default function BinTour() { +interface Props { + setDetailTabState?: ( detail: "inventory" | "sensors" | "analytics" | "presets" | "alerts" | "transactions", buttonIndex: number) => void +} + +export default function BinTour(props: Props) { // const { userID } = useAuth0(); + const {setDetailTabState} = props const [{ user }, dispatch] = useGlobalState(); const userID = user.id() const { error } = useSnackbar(); @@ -35,8 +40,8 @@ export default function BinTour() { } }; - const getTourSteps = (): Step[] => { - let steps: Step[] = [ + const getTourSteps = (): TourStep[] => { + let steps: TourStep[] = [ { title: ( @@ -103,24 +108,12 @@ export default function BinTour() { disableBeacon: false }, { - title: "Graphs", + title: "View Other Data", content: ( - Bin related analytics are displayed here. - - - ), - target: "#tour-graphs", - placement: "left", - disableBeacon: false - }, - { - title: "Choose your graphs", - content: ( - - - Use this tab to view other sets of data. Sensors must be attached to view sensor data. + Use these tabs to view other Bin Details such as inventory levels over time, + alerts and interactions for connected components, and data for attached sensors ), @@ -128,6 +121,122 @@ export default function BinTour() { placement: "bottom", disableBeacon: false }, + { + title: "Inventory", + content: ( + + + The inventory tab shows your bins inventory level over a specified window as well as the times the bin mode was changed. + + + ), + target: "#tour-details", + placement: "left-start", + disableBeacon: false, + onNext: () => { + if (setDetailTabState) setDetailTabState("sensors", 1) + } + }, + { + title: "Sensors", + content: ( + + + The sensors tab shows readings from attached sensors over time + + + ), + target: "#tour-details", + placement: "left-start", + disableBeacon: false, + onNext: () => { + if (setDetailTabState) setDetailTabState("analytics", 2) + } + }, + { + title: "Analytics", + content: ( + + + The analysis tab shows analytic bin data using attached sensors + + + ), + target: "#tour-details", + placement: "left-start", + disableBeacon: false, + onNext: () => { + if (setDetailTabState) setDetailTabState("alerts", 3) + } + }, + { + title: "Alerts and Interactions", + content: ( + + + The Alerts tab allows you to view or add any new interactions or alerts for connected components + and displays recent notifications from those alerts + + + ), + target: "#tour-details", + placement: "left-start", + disableBeacon: false, + onNext: () => { + if (setDetailTabState) setDetailTabState("presets", 4) + } + }, + { + title: "Bin Mode Presets", + content: ( + + + The Presets tab allows you to create custom presets for the interactions for a device when changing bin modes + + + ), + target: "#tour-details", + placement: "left-start", + disableBeacon: false, + onNext: () => { + if (setDetailTabState) setDetailTabState("transactions", 5) + } + }, + { + title: "Bin Transactions", + content: ( + + + The transactions tab allows view any pending transaction when using a hybrid inventory control + + + ), + target: "#tour-details", + placement: "left-start", + disableBeacon: false, + onNext: () => { + if (setDetailTabState) setDetailTabState("inventory", 0) + } + }, + { + title: "Bin Conditions", + content: ( + + + This section will display conditions based on the bin mode + + + Storage Mode: simply displays the Storage conditions by itself with the target temperature and moisture set in the bin settings + + + Other Modes: will display the interactions for the bins devices that are controlling a fan or heater on the bin as well as the storage conditions + + + ), + target: "#tour-conditions", + placement: "right", + disableBeacon: false + }, { title: "Change Mode", content: ( @@ -138,12 +247,15 @@ export default function BinTour() { diff --git a/src/bin/BinVisualizerV2.tsx b/src/bin/BinVisualizerV2.tsx index 7d99671..baa27f6 100644 --- a/src/bin/BinVisualizerV2.tsx +++ b/src/bin/BinVisualizerV2.tsx @@ -1727,32 +1727,34 @@ export default function BinVisualizer(props: Props) { {modeChangeInProgress && } - { - setModeStorage() + + { + setModeStorage() + } + }, + { + title: "Cooldown", + function: () => { + setModeCooldown() + } + }, + { + title: bin.settings.inventory && bin.settings.inventory?.initialMoisture < bin.settings.inventory?.targetMoisture ? "Hydrating" : "Drying", + function: () => { + // setShowInputMoisture(true) + setModeConditioning() //will set it to either drying or hydrating based on the initial and target moisture + } } - }, - { - title: "Cooldown", - function: () => { - setModeCooldown() - } - }, - { - title: bin.settings.inventory && bin.settings.inventory?.initialMoisture < bin.settings.inventory?.targetMoisture ? "Hydrating" : "Drying", - function: () => { - // setShowInputMoisture(true) - setModeConditioning() //will set it to either drying or hydrating based on the initial and target moisture - } - } - ]} - toggledButtons={determineToggle(mode)} - toggle - /> + ]} + toggledButtons={determineToggle(mode)} + toggle + /> + ); }; diff --git a/src/common/ButtonGroup.tsx b/src/common/ButtonGroup.tsx index 3c2c64c..e326d64 100644 --- a/src/common/ButtonGroup.tsx +++ b/src/common/ButtonGroup.tsx @@ -57,6 +57,7 @@ interface Props { * When true will disable all of the buttons in the group, will be overridded by individual buttons disabled state in the button data */ disableAll?: boolean + } const useStyles = makeStyles((theme: Theme) => { diff --git a/src/pages/Bin.tsx b/src/pages/Bin.tsx index 9fa36b6..cc667d8 100644 --- a/src/pages/Bin.tsx +++ b/src/pages/Bin.tsx @@ -195,6 +195,7 @@ export default function Bin(props: Props) { const [headspaceCO2, setHeadspaceCO2] = useState([]); const [heaters, setHeaters] = useState([]); const [fans, setFans] = useState([]); + const [activeDetails, setActiveDetails] = useState([0]) const [detail, setDetail] = useState< "inventory" | "sensors" | "analytics" | "presets" | "alerts" | "transactions" >("inventory"); @@ -805,7 +806,7 @@ export default function Bin(props: Props) { {overview()} {preferences && binComponents(preferences)} - + {(bin.settings.mode === pond.BinMode.BIN_MODE_DRYING || bin.settings.mode === pond.BinMode.BIN_MODE_HYDRATING || bin.settings.mode === pond.BinMode.BIN_MODE_COOLDOWN) && ( @@ -824,34 +825,53 @@ export default function Bin(props: Props) { - - - + + setDetail("inventory") + function: () => { + setDetail("inventory") + setActiveDetails([0]) + } }, { title: "Sensors", - function: () => setDetail("sensors") + function: () => { + setDetail("sensors") + setActiveDetails([1]) + } }, { title: "Analysis", - function: () => setDetail("analytics") + function: () => { + setDetail("analytics") + setActiveDetails([2]) + } }, { title: "Alerts", - function: () => setDetail("alerts") + function: () => { + setDetail("alerts") + setActiveDetails([3]) + } }, { title: "Presets", - function: () => setDetail("presets") + function: () => { + setDetail("presets") + setActiveDetails([4]) + } }, { title: "Transactions", - function: () => setDetail("transactions") + function: () => { + setDetail("transactions") + setActiveDetails([5]) + } } ]} /> @@ -880,23 +900,27 @@ export default function Bin(props: Props) { /> )} - {(detail === "inventory" || detail === "sensors" || detail === "analytics") && ( - - )} {detail === "transactions" && + + } + {(detail === "inventory" || detail === "sensors" || detail === "analytics") && ( + + + + )} @@ -1141,7 +1165,11 @@ export default function Bin(props: Props) { {objectTeams()} {deviceMenu()} - + { + setDetail(detail) + setActiveDetails([buttonIndex]) + }}/> ); } diff --git a/src/pages/SignupCallback.tsx b/src/pages/SignupCallback.tsx index a22dbfc..43c8c5b 100644 --- a/src/pages/SignupCallback.tsx +++ b/src/pages/SignupCallback.tsx @@ -1,13 +1,15 @@ import { useDeviceAPI, useMobile, useUserAPI } from "hooks"; import PageContainer from "./PageContainer"; import { useEffect, useState } from "react"; -import { Button, CircularProgress, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, Divider, Typography } from "@mui/material"; +import { Button, CircularProgress, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, Divider, Grid2, MenuItem, TextField, Typography } from "@mui/material"; import { useBinAPI, useGlobalState, useTeamAPI } from "providers"; import { CheckCircleOutline } from "@mui/icons-material"; import { green } from "@mui/material/colors"; import Tour, { TourStep } from "common/Tour"; import Emoji from "react-emoji-render"; import { getWhitelabel, IsAdaptiveAgriculture } from "services/whiteLabel"; +import { pond } from "protobuf-ts/pond"; +import { User } from "models"; // import { color } from "framer-motion"; // interface Props { @@ -21,7 +23,7 @@ export default function SignupCallback () { const deviceAPI = useDeviceAPI(); const binAPI = useBinAPI(); const isMobile = useMobile() - const [{ user }] = useGlobalState(); + const [globalState, dispatch] = useGlobalState(); const whiteLabel = getWhitelabel() const [loading, setLoading] = useState(false) @@ -35,6 +37,7 @@ export default function SignupCallback () { const [doneBins, setDoneBins] = useState(false) const [doneTeams, setDoneTeams] = useState(false) const [doneDevices, setDoneDevices] = useState(false) + const [user, setUser] = useState(globalState.user); useEffect(() => { setLoading(true) @@ -55,6 +58,124 @@ export default function SignupCallback () { return loading === false && doneBins && doneTeams && doneDevices } + const changePressureUnit = (value: any) => { + let updatedUser = User.clone(user) + let pressureUnit: pond.PressureUnit; + switch (value) { + case 1: + pressureUnit = pond.PressureUnit.PRESSURE_UNIT_KILOPASCALS; + break; + case 2: + pressureUnit = pond.PressureUnit.PRESSURE_UNIT_INCHES_OF_WATER; + break; + default: + pressureUnit = pond.PressureUnit.PRESSURE_UNIT_UNKNOWN; + break; + } + updatedUser.settings.pressureUnit = pressureUnit; + setUser(updatedUser) + }; + + const changeTemperatureUnit = (value: any) => { + let updatedUser = User.clone(user); + let temperatureUnit: pond.TemperatureUnit; + switch (value) { + case 1: + temperatureUnit = pond.TemperatureUnit.TEMPERATURE_UNIT_CELSIUS; + break; + case 2: + temperatureUnit = pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT; + break; + default: + temperatureUnit = pond.TemperatureUnit.TEMPERATURE_UNIT_UNKNOWN; + break; + } + updatedUser.settings.temperatureUnit = temperatureUnit; + setUser(updatedUser); + }; + + const unitPreferences = () => { + const { pressureUnit, temperatureUnit, distanceUnit, grainUnit } = user.settings; + return ( + + + changePressureUnit(event.target.value)} + margin="normal" + variant="outlined" + InputLabelProps={{ shrink: true }}> + + Kilopascals (kPa) + + + Inches of Water (iwg) + + + + + changeTemperatureUnit(event.target.value)} + margin="normal" + variant="outlined" + InputLabelProps={{ shrink: true }}> + Celsius (°C) + + Fahrenheit (°F) + + + + + changeDistanceUnit(event.target.value)} + margin="normal" + variant="outlined" + InputLabelProps={{ shrink: true }}> + Meters (m) + Feet (ft) + + + {IsAdaptiveAgriculture() && ( + + changeGrainUnit(event.target.value)} + margin="normal" + variant="outlined" + InputLabelProps={{ shrink: true }}> + Bushels (bu) + Tonnes (mT) + + + )} + + ); + }; + const content = () => { return ( @@ -104,12 +225,17 @@ export default function SignupCallback () { content: ( <> - In the user menu, you can make changes to your profile, and adjust unit preferences. + In the user menu, you can make changes to your profile, such as adjusting unit preferences.
If you are part of a team, you can select it here as well. +
+ + Set your unit preferences here now, they can be changed later from this menu: + + {unitPreferences()} ), target: "#tour-user-menu", @@ -150,35 +276,104 @@ export default function SignupCallback () { target: "#tour-dashboard", placement: "right" }) - if (IsAdaptiveAgriculture()) steps.push({ - title: "Bins", + steps.push({ + title: "Tasks", content: ( <> - You can view your bins and their inventory here. + You can view and create tasks here and assign a start and end time for them.
- If you are viewing as a team, your team's bins will be displayed here instead. + If you are viewing as a team you will see the teams tasks, you can even assign tasks to team members. ), - target: "#tour-bins", - placement: "right", - disableBeacon: true, + target: "#tour-tasks", + placement: "right" }) + //tasks step + if (IsAdaptiveAgriculture()) { + steps.push({ + title: "Visual Farm", + content: ( + <> + + You can view your Visual Farm here, it will allow tou to draw fields and plot bins an a map. + +
+ + If you are viewing as a team, your team's fields and bins will be displayed here instead. + + + ), + target: "#tour-visual-farm", + placement: "right", + disableBeacon: true, + }) + steps.push({ + title: "Fields", + content: ( + <> + + You can view your fields you have drawn on the map here. + +
+ + If you are viewing as a team, your team's fields will be displayed here instead. + + + ), + target: "#tour-field-list", + placement: "right", + disableBeacon: true, + }) + steps.push({ + title: "Bins", + content: ( + <> + + You can view your bins and their inventory here. + +
+ + If you are viewing as a team, your team's bins will be displayed here instead. + + + ), + target: "#tour-bins", + placement: "right", + disableBeacon: true, + }) + steps.push({ + title: "Contracts", + content: ( + <> + + You can view and track any contracts you have created here. + +
+ + If you are viewing as a team, your team's contracts will be displayed here instead. + + + ), + target: "#tour-contracts", + placement: "right", + disableBeacon: true, + }) + } return steps; }; const endTour = () => { setIsTourRunning(false); - // if (user) { - // user.status.finishedBinIntro = moment().toJSON(); - // userAPI - // .updateUser(userID, user.protobuf()) - // .then(() => dispatch({ key: "user", value: user })) - // .catch((err: any) => error(err)); - // } + if (user) { + userAPI + .updateUser(user.id(), user.protobuf()) + .then(() => dispatch({ key: "user", value: user })) + .catch((err: any) => console.error(err)); + } }; const closeDialog = () => {