diff --git a/src/theme/theme.ts b/src/theme/theme.ts index 9edf9af..08c42db 100644 --- a/src/theme/theme.ts +++ b/src/theme/theme.ts @@ -27,6 +27,7 @@ function options(themeType: "light" | "dark"): ThemeOptions { const signature = getSignatureColour(); const accent = getSignatureAccentColour(); + const highlight = themeType === "light" ? "black" : "white"; const bg = generateBackgroundShades(themeType) return { palette: { @@ -195,13 +196,10 @@ function options(themeType: "light" | "dark"): ThemeOptions { styleOverrides: { root: { '& .MuiTouchRipple-root': { - color: accent, // Customize ripple color here - // color: "white" + color: highlight, }, '&:hover': { - // color: themeType === "light" ? signature : "black", - // color: "white" - color: accent + color: highlight }, }, }, diff --git a/src/user/UserAvatar.tsx b/src/user/UserAvatar.tsx new file mode 100644 index 0000000..45a23fb --- /dev/null +++ b/src/user/UserAvatar.tsx @@ -0,0 +1,57 @@ +import { Avatar } from "@mui/material"; +import { Team, User } from "models"; +import React from "react"; + +function stringToColor(string: string) { + let hash = 0; + let i; + + /* eslint-disable no-bitwise */ + for (i = 0; i < string.length; i += 1) { + hash = string.charCodeAt(i) + ((hash << 5) - hash); + } + + let color = "#"; + + for (i = 0; i < 3; i += 1) { + const value = (hash >> (i * 8)) & 0xff; + color += `00${value.toString(16)}`.slice(-2); + } + /* eslint-enable no-bitwise */ + return color; +} + +function stringAvatar(name: string) { + let letters = ""; + if (name.split(" ").length > 1) { + letters = name.split(" ")[0][0] + name.split(" ")[1][0]; + } else { + letters = name.split(" ")[0][0]; + } + return { + sx: { + bgcolor: stringToColor(name) + }, + children: `${letters}` + }; +} + +interface Props { + user: User | Team; + className?: string; + style?: React.CSSProperties; +} + +export default function UserSettings(props: Props) { + const { user, className, style } = props; + + return ( + + ); +} diff --git a/src/user/UserMenu.tsx b/src/user/UserMenu.tsx index 3652d51..7cbf2f9 100644 --- a/src/user/UserMenu.tsx +++ b/src/user/UserMenu.tsx @@ -1,13 +1,16 @@ -import { Avatar, Box, Button, IconButton, PaletteColor, Theme, Typography, useTheme } from "@mui/material"; +import { Avatar, Box, Button, IconButton, ListItemIcon, ListItemText, Menu, MenuItem, PaletteColor, Theme, Typography, useTheme } from "@mui/material"; import { useGlobalState } from "../providers/StateContainer"; import { getSecondaryColour, getSignatureAccentColour } from "../services/whiteLabel"; import { makeStyles } from "@mui/styles"; -import { LockOpen, Person, Lock, } from "@mui/icons-material"; -import { useEffect, useState } from "react"; +import { LockOpen, Person, Lock, Settings, SupervisedUserCircle as TeamIcon } from "@mui/icons-material"; +import { useState } from "react"; import UserTeamName from "./UserTeamName"; import React from "react"; import ThemeIcon from "../common/ThemeIcon"; import { useAuth0 } from "@auth0/auth0-react"; +import UserSettings from "./UserSettings"; +import UserAvatar from "./UserAvatar"; +import { purple } from "@mui/material/colors"; const useStyles = makeStyles((theme: Theme) => ({ userAvatar: { @@ -18,6 +21,28 @@ const useStyles = makeStyles((theme: Theme) => ({ height: "32px" } }, + userAvatar2: { + color: "#fff", + backgroundColor: theme.palette.secondary["700" as keyof PaletteColor], + [theme.breakpoints.down("xs")]: { + width: "30px", + height: "30px" + }, + position: "relative", + top: -6, + left: 0 + }, + teamAvatar: { + color: "#fff", + backgroundColor: theme.palette.secondary["700" as keyof PaletteColor], + [theme.breakpoints.down("xs")]: { + width: "30px", + height: "30px" + }, + position: "absolute", + top: -34, + left: 8 + }, profileButton: { maxWidth: "50vw" }, @@ -48,101 +73,138 @@ interface Props { export default function UserMenu(props: Props) { - const { toggleTheme } = props; - const [{ user, team }] = useGlobalState(); - const { loginWithRedirect } = useAuth0(); - const classes = useStyles(); - const theme = useTheme(); + const { toggleTheme } = props; + const [{ user, team, as }] = useGlobalState(); + const { loginWithRedirect } = useAuth0(); + const classes = useStyles(); + const theme = useTheme(); - const name = user.name(); - const picture = user.settings.avatar; - const [lockIsHovered, setLockIsHovered] = useState(false); - // const hasAdmin = user.hasFeature ? user.hasFeature("admin") : false; - // const allowedToCopyToken = user.allowedTo("copy-token"); - // const hasTeams = user.hasFeature ? user.hasFeature("teams") : false; + const name = user.name(); + const picture = user.settings.avatar; + const [lockIsHovered, setLockIsHovered] = useState(false); + const [userMenuIsOpen, setUserMenuIsOpen] = useState(false); + const [anchorEl, setAnchorEl] = useState(null); + const [userSettingsIsOpen, setUserSettingsIsOpen] = useState(false); + // const hasAdmin = user.hasFeature ? user.hasFeature("admin") : false; + // const allowedToCopyToken = user.allowedTo("copy-token"); + const hasTeams = user.hasFeature ? user.hasFeature("teams") : false; - const lockHover = () => { - setLockIsHovered(true); - }; + const lockHover = () => { + setLockIsHovered(true); + }; + + const lockNoHover = () => { + setLockIsHovered(false); + }; + + const handleLogin = () => { + loginWithRedirect() + } + + const openUserMenu = (event: any) => { + setAnchorEl(event.currentTarget); + setUserMenuIsOpen(true); + }; + + const closeUserMenu = () => { + setUserMenuIsOpen(false); + setAnchorEl(null); + }; + + const openUserSettingsDialog = () => { + setUserMenuIsOpen(false); + setAnchorEl(null); + setUserSettingsIsOpen(true) + } - const lockNoHover = () => { - setLockIsHovered(false); - }; - - const handleLogin = () => { - loginWithRedirect() - } - - const unauthenticatedUserMenu = () => { - return ( - - - - - - - - ); - }; - - if (user.id().length < 1) return unauthenticatedUserMenu() + const closeUserSettingsDialog = () => { + setUserSettingsIsOpen(false) + } + const unauthenticatedUserMenu = () => { return ( - <> + + + + + + + ); + }; + + if (user.id().length < 1) return unauthenticatedUserMenu() + + return ( + <> + + + + + + + + + + ) } \ No newline at end of file diff --git a/src/user/UserSettings.tsx b/src/user/UserSettings.tsx new file mode 100644 index 0000000..72c7fdb --- /dev/null +++ b/src/user/UserSettings.tsx @@ -0,0 +1,102 @@ +import { Close } from "@mui/icons-material"; +import { AppBar, Button, IconButton, Theme, Toolbar, Typography } from "@mui/material"; +import ResponsiveDialog from "common/ResponsiveDialog"; +import UserAvatar from "./UserAvatar"; +import { useGlobalState, useUserAPI } from "providers"; +import { useState } from "react"; +import { makeStyles } from "@mui/styles"; +import { blue } from "@mui/material/colors"; + +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 { isOpen, closeDialogCallback } = props; + const [{ user }, dispatch] = useGlobalState() + const userAPI = useUserAPI(); + const classes = useStyles() + + const [isLoading, setIsLoading] = useState(false); + + 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 closeDialog = () => { + // setDefaultState(); + closeDialogCallback(); + }; + + return ( + + + + + + + + + User Settings + + + + + {/* {settingsList()} */} + + ); +} \ No newline at end of file