import { AccountBox, Close, ExpandLess, ExpandMore, Face, Share as ShareIcon, Notifications as NotificationsIcon, Email as EmailIcon, Textsms as TextIcon, Contrast, } from "@mui/icons-material"; import { AppBar, Box, Button, Checkbox, CircularProgress, Collapse, Divider, FormControl, FormControlLabel, FormGroup, FormHelperText, FormLabel, Grid2, IconButton, List, ListItem, ListItemButton, ListItemIcon, ListItemText, MenuItem, Radio, RadioGroup, TextField, Theme, ToggleButton, ToggleButtonGroup, Toolbar, Tooltip, Typography } from "@mui/material"; import ResponsiveDialog from "common/ResponsiveDialog"; import UserAvatar from "./UserAvatar"; import { useGlobalState, useSnackbar, useUserAPI } from "providers"; import { useEffect, useState } from "react"; import { makeStyles } from "@mui/styles"; import { blue } from "@mui/material/colors"; import ShareObject from "./ShareObject"; import { pond } from "protobuf-ts/pond"; import { User, userScope } from "models"; import SearchSelect from "common/SearchSelect"; import {Option as OptionType} from "common/SearchSelect"; import moment from "moment"; import { IconPicker } from "common/IconPicker"; import { MuiTelInput } from "mui-tel-input"; import { useThemeMode } from "theme/AppThemeProvider"; // import ContractsIcon from "products/CommonIcons/contractIcon"; import UnitsIcon from "@mui/icons-material/Category"; import { setThemeType } from "theme"; import { IsAdaptiveAgriculture } from "services/whiteLabel"; import { setDistanceUnit, setGrainUnit, setPressureUnit, setTemperatureUnit } from "utils"; const useStyles = makeStyles((theme: Theme) => { return ({ title: { marginLeft: theme.spacing(2), marginRight: theme.spacing(2), flex: 1 }, checkboxIcon: { minWidth: theme.spacing(5), [theme.breakpoints.up("sm")]: { minWidth: theme.spacing(6) }, [theme.breakpoints.up("md")]: { minWidth: theme.spacing(7) } }, shareIcon: { color: blue["600"], "&:hover": { color: blue["700"] } }, iconButton: { margin: theme.spacing(1), position: "absolute", right: theme.spacing(6) } }); }); interface Props { isOpen: boolean; closeDialogCallback: () => void; } export default function UserSettings(props: Props) { const themeMode = useThemeMode() const { isOpen, closeDialogCallback } = props; const [globalState, dispatch] = useGlobalState() const [sharing, setSharing] = useState(false) const userAPI = useUserAPI(); const classes = useStyles() const { success } = useSnackbar(); const [isLoading, setIsLoading] = useState(false); const [user, setUser] = useState(globalState.user); const [profileExpanded, setProfileExpanded] = useState(false); const [avatarExpanded, setAvatarExpanded] = useState(false); const [notificationsExpanded, setNotificationsExpanded] = useState(false); const [unitsExpanded, setUnitsExpanded] = useState(false); const [avatarUrl, setAvatarUrl] = useState(""); // const [themeValue, setThemeValue] = useState<"light" | "dark" | "system">(themeMode.mode) useEffect(() => { function changeIcon(icon: string | undefined) { let updatedUser = User.clone(user); updatedUser.settings.avatar = icon ? icon : user.settings.avatar; setUser(updatedUser); } if (avatarUrl === "") { changeIcon(undefined); } else { changeIcon(avatarUrl); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [avatarUrl]); const submit = () => { userAPI .updateUser(user.id(), user.protobuf()) .then(() => { dispatch({ key: "user", value: user }); success("User settings successfully updated!"); setTemperatureUnit(user.settings.temperatureUnit); setPressureUnit(user.settings.pressureUnit); setDistanceUnit(user.settings.distanceUnit); setGrainUnit(user.settings.grainUnit); }) .catch((error: any) => { error("Error occurred while updating your profile"); }) .finally(() => { setIsLoading(false); closeDialogCallback(); }); }; const setDefaultState = () => { setIsLoading(false); setUser(globalState.user); }; const closeDialog = () => { setDefaultState(); closeDialogCallback(); }; const loading = () => { return ; }; const changeName = (name: string) => { let updatedUser = User.clone(user); updatedUser.settings.name = name; setUser(updatedUser); }; const changeTimezone = (tz: string) => { let updatedUser = User.clone(user); updatedUser.settings.timezone = tz; setUser(updatedUser); }; const changePhoneNumber = (newPhoneNumber: string) => { let updatedUser = User.clone(user); updatedUser.settings.phoneNumber = newPhoneNumber; setUser(updatedUser); }; const generalSettings = () => { const { name, email, phoneNumber, timezone } = user.settings; return ( setSharing(false)} /> setSharing(true)}> changeName(event.target.value.toString())} /> Phone Number ({ label: tz, value: tz } as OptionType))} changeSelection={(selected: OptionType | null) => changeTimezone(selected ? selected.value : "") } /> ); }; const handleChangeNotifyByDefault = (notifyByDefault: boolean) => { let updatedUser = User.clone(user); updatedUser.settings.notifyByDefault = notifyByDefault; setUser(updatedUser); }; const handleNotificationMethod = ( checked: boolean, notificationMethod: pond.NotificationMethod ) => { let updatedUser = User.clone(user); let notificationMethods = updatedUser.settings.notificationMethods; if (checked) { if (!notificationMethods.includes(notificationMethod)) { notificationMethods.push(notificationMethod); } } else { notificationMethods = notificationMethods.filter(element => element !== notificationMethod); } updatedUser.settings.notificationMethods = notificationMethods; setUser(updatedUser); }; const notificationsSettings = () => { const { notifyByDefault, notificationMethods } = user.settings; return ( Notification Preference handleChangeNotifyByDefault(event.target.value === "true")}> } label="Opt-in" /> } label="Opt-out" /> {notifyByDefault ? "Notifications are enabled by default" : "Notifications are disabled by default"} Notification Methods handleNotificationMethod( checked, pond.NotificationMethod.NOTIFICATION_METHOD_EMAIL ) } checked={ notificationMethods ? notificationMethods.includes( pond.NotificationMethod.NOTIFICATION_METHOD_EMAIL ) : false } /> } label={ } /> handleNotificationMethod( checked, pond.NotificationMethod.NOTIFICATION_METHOD_TEXT ) } checked={ notificationMethods ? notificationMethods.includes( pond.NotificationMethod.NOTIFICATION_METHOD_TEXT ) : false } /> } label={ } /> handleNotificationMethod( checked, pond.NotificationMethod.NOTIFICATION_METHOD_APP ) } checked={ notificationMethods ? notificationMethods.includes( pond.NotificationMethod.NOTIFICATION_METHOD_APP ) : false } /> } label={ } /> ); }; const avatarSettings = () => { return ; }; const handleChange = (event: React.MouseEvent, theme: "light" | "dark" | "system") => { event.preventDefault() themeMode.setMode(theme) setThemeType(theme) }; 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 changeDistanceUnit = (value: any) => { let updatedUser = User.clone(user); let distanceUnit: pond.DistanceUnit; switch (value) { case 1: distanceUnit = pond.DistanceUnit.DISTANCE_UNIT_FEET; break; case 2: distanceUnit = pond.DistanceUnit.DISTANCE_UNIT_METERS; break; default: distanceUnit = pond.DistanceUnit.DISTANCE_UNIT_UNKNOWN; break; } updatedUser.settings.distanceUnit = distanceUnit; setUser(updatedUser); }; const changeGrainUnit = (value: any) => { let updatedUser = User.clone(user); let grainUnit: pond.GrainUnit; switch (value) { case 1: grainUnit = pond.GrainUnit.GRAIN_UNIT_BUSHELS; break; case 2: grainUnit = pond.GrainUnit.GRAIN_UNIT_WEIGHT; break; default: grainUnit = pond.GrainUnit.GRAIN_UNIT_UNKNOWN; break; } updatedUser.settings.grainUnit = grainUnit; 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 themeToggle = () => { return ( light system dark ) } const settingsList = () => { return ( {themeToggle()} setProfileExpanded(!profileExpanded)}> {profileExpanded ? : } {isLoading ? loading() : generalSettings()} setAvatarExpanded(!avatarExpanded)}> {avatarExpanded ? : } {isLoading ? loading() : avatarSettings()} setNotificationsExpanded(!notificationsExpanded)}> {notificationsExpanded ? : } {isLoading ? loading() : notificationsSettings()} setUnitsExpanded(!unitsExpanded)}> {unitsExpanded ? : } {isLoading ? loading() : unitPreferences()} {/* setMapsExpanded(!mapsExpanded)}> {mapsExpanded ? : } {isLoading ? loading() : mapSettings()} */} ); }; return ( User Settings {settingsList()} ); }