user settings icon picker

This commit is contained in:
Carter 2024-11-27 11:37:04 -06:00
parent 5c79f9a633
commit 1da5faf59c
2 changed files with 203 additions and 5 deletions

View file

@ -1,4 +1,4 @@
import { Avatar, Box, Button, IconButton, ListItemIcon, ListItemText, Menu, MenuItem, PaletteColor, Theme, Typography, useTheme } from "@mui/material"; import { Avatar, Box, Button, IconButton, ListItemIcon, ListItemText, Menu, MenuItem, PaletteColor, Theme, useTheme } from "@mui/material";
import { useGlobalState } from "../providers/StateContainer"; import { useGlobalState } from "../providers/StateContainer";
import { getSecondaryColour, getSignatureAccentColour } from "../services/whiteLabel"; import { getSecondaryColour, getSignatureAccentColour } from "../services/whiteLabel";
import { makeStyles } from "@mui/styles"; import { makeStyles } from "@mui/styles";

View file

@ -1,11 +1,18 @@
import { Close } from "@mui/icons-material"; import { AccountBox, Close, ExpandLess, ExpandMore, Face, Share as ShareIcon } from "@mui/icons-material";
import { AppBar, Button, IconButton, Theme, Toolbar, Typography } from "@mui/material"; import { AppBar, Box, Button, CircularProgress, Collapse, Divider, FormControl, FormLabel, Grid2, IconButton, List, ListItem, ListItemButton, ListItemIcon, ListItemText, TextField, Theme, Toolbar, Tooltip, Typography } from "@mui/material";
import ResponsiveDialog from "common/ResponsiveDialog"; import ResponsiveDialog from "common/ResponsiveDialog";
import UserAvatar from "./UserAvatar"; import UserAvatar from "./UserAvatar";
import { useGlobalState, useUserAPI } from "providers"; import { useGlobalState, useUserAPI } from "providers";
import { useState } from "react"; import { useState } from "react";
import { makeStyles } from "@mui/styles"; import { makeStyles } from "@mui/styles";
import { blue } from "@mui/material/colors"; 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";
const useStyles = makeStyles((theme: Theme) => { const useStyles = makeStyles((theme: Theme) => {
return ({ return ({
@ -44,11 +51,16 @@ interface Props {
export default function UserSettings(props: Props) { export default function UserSettings(props: Props) {
const { isOpen, closeDialogCallback } = props; const { isOpen, closeDialogCallback } = props;
const [{ user }, dispatch] = useGlobalState() const [globalState, dispatch] = useGlobalState()
const [sharing, setSharing] = useState(false)
const userAPI = useUserAPI(); const userAPI = useUserAPI();
const classes = useStyles() const classes = useStyles()
const [isLoading, setIsLoading] = useState<boolean>(false); const [isLoading, setIsLoading] = useState<boolean>(false);
const [user, setUser] = useState<User>(globalState.user);
const [profileExpanded, setProfileExpanded] = useState<boolean>(false);
const [avatarExpanded, setAvatarExpanded] = useState<boolean>(false);
const [avatarUrl, setAvatarUrl] = useState<string>("");
const submit = () => { const submit = () => {
userAPI userAPI
@ -75,6 +87,192 @@ export default function UserSettings(props: Props) {
closeDialogCallback(); closeDialogCallback();
}; };
const loading = () => {
return <CircularProgress variant="indeterminate" color="primary" />;
};
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 generalSettings = () => {
const { name, email, phoneNumber, timezone } = user.settings;
return (
<Grid2 container direction="column" spacing={4} justifyContent="flex-start" alignItems="flex-start">
<ShareObject
scope={userScope(user.id())}
label={""}
permissions={[
pond.Permission.PERMISSION_READ,
pond.Permission.PERMISSION_SHARE,
pond.Permission.PERMISSION_USERS,
pond.Permission.PERMISSION_WRITE
]}
isDialogOpen={sharing}
closeDialogCallback={() => setSharing(false)}
/>
<Tooltip title={"Share control of profile with another user"}>
<IconButton
aria-label="Share"
className={classes.iconButton}
onClick={() => setSharing(true)}>
<ShareIcon className={classes.shareIcon} />
</IconButton>
</Tooltip>
<Grid2>
<TextField
label="Preferred Name"
value={name}
helperText={"Email: " + email}
onChange={event => changeName(event.target.value.toString())}
/>
</Grid2>
<Grid2>
<FormControl component="fieldset">
<FormLabel component="legend" htmlFor="phone-number-input">
Phone Number
</FormLabel>
{/* <MuiPhoneNumber
onChange={(value: string) => changePhoneNumber(value)}
value={phoneNumber}
onlyCountries={["ca", "us"]}
defaultCountry={"ca"}
countryCodeEditable={false}
/> */}
lol
</FormControl>
</Grid2>
<Grid2 size={{xs: 12}}>
<Box minWidth="250px">
<SearchSelect
label="Timezone"
selected={{ label: timezone, value: timezone } as OptionType}
options={moment.tz.names().map(tz => ({ label: tz, value: tz } as OptionType))}
changeSelection={(selected: OptionType | null) =>
changeTimezone(selected ? selected.value : "")
}
/>
</Box>
</Grid2>
</Grid2>
);
};
const avatarSettings = () => {
return <IconPicker url={user.settings.avatar} setUrl={setAvatarUrl} id={user.settings.id} />;
};
const settingsList = () => {
return (
<List disablePadding>
<ListItemButton onClick={() => setProfileExpanded(!profileExpanded)}>
<ListItemIcon>
<AccountBox />
</ListItemIcon>
<ListItemText primary={"Profile"} />
{profileExpanded ? <ExpandLess /> : <ExpandMore />}
</ListItemButton>
<Collapse in={profileExpanded} timeout="auto" unmountOnExit>
<List component="div">
<ListItem>
<ListItemText disableTypography inset>
{isLoading ? loading() : generalSettings()}
</ListItemText>
</ListItem>
</List>
</Collapse>
<Divider />
<ListItemButton onClick={() => setAvatarExpanded(!avatarExpanded)}>
<ListItemIcon>
<Face />
</ListItemIcon>
<ListItemText primary={"Display Picture"} />
{avatarExpanded ? <ExpandLess /> : <ExpandMore />}
</ListItemButton>
<Collapse in={avatarExpanded} timeout="auto" unmountOnExit>
<List
component="div"
sx={{
paddingLeft: 4,
paddingRight: 4
}}>
{isLoading ? loading() : avatarSettings()}
</List>
</Collapse>
{/* <Divider />
<ListItem button onClick={() => setNotificationsExpanded(!notificationsExpanded)}>
<ListItemIcon>
<NotificationsIcon />
</ListItemIcon>
<ListItemText primary="Notifications" />
{notificationsExpanded ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse in={notificationsExpanded} timeout="auto" unmountOnExit>
<List component="div">
<ListItem>
<ListItemText disableTypography inset>
{isLoading ? loading() : notificationsSettings()}
</ListItemText>
</ListItem>
</List>
</Collapse>
<Divider />
<ListItem button onClick={() => setUnitsExpanded(!unitsExpanded)}>
<ListItemIcon>
<UnitsIcon />
</ListItemIcon>
<ListItemText primary="Preferred Units" />
{unitsExpanded ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse in={unitsExpanded} timeout="auto" unmountOnExit>
<List component="div">
<ListItem>
<ListItemText disableTypography inset>
{isLoading ? loading() : unitPreferences()}
</ListItemText>
</ListItem>
</List>
</Collapse>
<Divider />
<ListItem button onClick={() => setMapsExpanded(!mapsExpanded)}>
<ListItemIcon>
<FieldsIcon />
</ListItemIcon>
<ListItemText primary={"Map Settings"} />
{mapsExpanded ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse in={mapsExpanded} timeout="auto" unmountOnExit>
<List component="div">
<ListItem>
<ListItemText disableTypography inset>
{isLoading ? loading() : mapSettings()}
</ListItemText>
</ListItem>
</List>
</Collapse> */}
</List>
);
};
return ( return (
<ResponsiveDialog <ResponsiveDialog
maxWidth="sm" maxWidth="sm"
@ -96,7 +294,7 @@ export default function UserSettings(props: Props) {
</Button> </Button>
</Toolbar> </Toolbar>
</AppBar> </AppBar>
{/* {settingsList()} */} {settingsList()}
</ResponsiveDialog> </ResponsiveDialog>
); );
} }