123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- import React, { useEffect, useState } from "react";
- import { withAuthenticationRequired } from "@auth0/auth0-react";
- import { Box, Button, Card, CardContent, CardHeader, Collapse, IconButton, InputBase, Table, TableBody, TableCell, TableContainer, TableRow, Typography } from "@material-ui/core";
- import { ExpandLess, ExpandMore, InfoTwoTone } from "@material-ui/icons";
- import ImageUpload from "../Images/ImageUpload";
- import { updateUser, updateUserMetadata } from "./settings.util";
- import { makeStyles } from "@material-ui/styles";
- import { useTranslation } from "react-i18next";
- import Navbar from "../Navbar";
- import BackButton from "../Buttons/BackButton";
- import { muiTableBorder } from "../util";
- import { Navigate, useLocation, useNavigate } from "react-router-dom";
- import SavingButton from "../Buttons/SavingButton";
- const useStyles = makeStyles(theme => ({
- userProfile: {
- padding: '1rem 0',
- overflow: 'auto',
- },
- table: {
- borderTop: muiTableBorder(theme),
- margin: '1rem 0',
- },
- tableCell: {
- padding: '10px',
- backgroundColor: theme.palette.background.default,
- '&:first-child': {
- width: '25%',
- },
- '&:last-child': {
- fontStyle: "italic",
- }
- },
- label: {
- color: theme.palette.secondary.light,
- fontSize: '1rem',
- },
- deleteImage: {
- fontSize: '1rem',
- fontStyle: 'italic',
- textAlign: 'center',
- marginTop: '0.5rem',
- color: theme.palette.error.main,
- textTransform: 'none',
- width: 'max-content',
- margin: '0.2rem auto',
- display: 'block',
- padding: '0rem 0.5rem',
- },
- submitButton: {
- minWidth: '10rem',
- maxWidth: '60%',
- margin: '0 auto 1.5rem',
- display: "block",
- },
- }));
- const IS_SECONDARY = true;
- /** Dialog page to edit user data, looks like Profile but is editable */
- const EditProfile = () => {
- const classes = useStyles();
- const { t } = useTranslation();
- let { state } = useLocation();
- const navigate = useNavigate();
- if (!state || !state.userData) {
- return <Navigate replace to="/settings" />;
- }
- const colorA = IS_SECONDARY ? "primary" : "secondary";
- // const colorB = IS_SECONDARY ? "secondary" : "primary";
- let {
- userData,
- userData: {
- user_metadata: metadata,
- user_id: userId,
- name: userName,
- email: userEmail,
- }
- } = state;
- const [profileImage, setProfileImage] = useState(metadata.picture || userData.picture);
- const [showReset, setShowReset] = useState(!!metadata.picture);
- const [username, setUsername] = useState(metadata.username);
- const [name, setName] = useState(userName);
- const [email, setEmail] = useState(userEmail);
- const [usingOAuth, setUsingOAuth] = useState(false);
- const [infoCollapsed, setInfoCollapsed] = useState(false);
- const [foreignAccountProvider, setForeignAccountProvider] = useState('');
- const [isSaving, setIsSaving] = useState(false);
- useEffect(() => {
- setUsingOAuth(userId.includes("oauth"));
- if (userId.includes("google")) {
- setForeignAccountProvider('Google');
- }
- }, [userId]);
- const editAndClose = (event) => {
- event.preventDefault();
- setIsSaving(true);
- // saving is only waiting for metadata for now because in Emilia there is only google login, not email/password
- updateUserMetadata(userId, { username: username }, onSave);
- if (!usingOAuth) {
- const newUserData = {
- name, email, nickname: username
- };
- updateUser(userId, newUserData, null);
- }
- }
- const onSave = () => {
- setIsSaving(false);
- goToSettings();
- };
- const updateProfileImage = (image) => {
- const imageSrc = image.url;
- console.log('set uploaded source', imageSrc);
- setProfileImage(imageSrc);
- updateProfileImageInMetadata(imageSrc);
- }
- const updateProfileImageInMetadata = (imageSrc) => {
- updateUserMetadata(userId, {
- picture: imageSrc,
- }, (newUserData) => {
- setProfileImage(newUserData.user_metadata.picture || newUserData.picture);
- setShowReset(!!newUserData.user_metadata.picture);
- });
- }
- const deleteProfileImage = () => {
- updateProfileImageInMetadata(null);
- }
- const goToSettings = () => {
- // send state to make Profile reload new data
- navigate('../', { state: { newUsername: username } });
- }
- return (
- <>
- <Navbar pageTitle={t('Edit Profile')} leftSideComponent={<BackButton onClick={goToSettings} />} secondary={IS_SECONDARY} />
- <Box className={classes.userProfile}>
- <ImageUpload uploadedImages={[profileImage]}
- imageName={t('profile picture of {{name}}', { name })}
- category="userProfile"
- categoryId={userId}
- onChangeUploadedImages={updateProfileImage}
- useSingleUploadOverlay />
- {showReset && <Button disableRipple className={classes.deleteImage} onClick={deleteProfileImage}>{t('Reset Image')}</Button>}
- {usingOAuth && <Card style={{ marginTop: '1rem' }}>
- <CardHeader avatar={<InfoTwoTone />}
- title={t('Logged in via {{provider}}', { provider: foreignAccountProvider })}
- action={<IconButton aria-label="collapse info" onClick={() => {setInfoCollapsed(!infoCollapsed)}}>
- {infoCollapsed ? <ExpandMore /> : <ExpandLess />}
- </IconButton>} />
- <Collapse in={!infoCollapsed} timeout="auto" unmountOnExit>
- <CardContent style={{ paddingTop: 0 }}>
- <Typography variant="body2" color="textSecondary" component="p">
- {t(`Since you are logged in via your {{provider}} account, you cannot change your data here. You can change the data directly in your {{provider}} account and it will be adopted on the next login.`, { provider: foreignAccountProvider })}
- </Typography>
- <Typography variant="body2" color="textSecondary" component="p">
- {t('You can, however, set a custom profile picture and username.')}
- </Typography>
- </CardContent>
- </Collapse>
- </Card>}
- <form name="edit-user-form" onSubmit={editAndClose}>
- <TableContainer className={classes.table}>
- <Table aria-label="edit profile data" size="small">
- <TableBody>
- <TableRow>
- <TableCell className={classes.tableCell}><Typography className={classes.label}>{t('Name')}</Typography></TableCell>
- <TableCell className={classes.tableCell}>
- <InputBase value={name} name="name" onChange={e => setName(e.target.value)} label={t('Name')} disabled={usingOAuth} />
- </TableCell>
- </TableRow>
- <TableRow>
- <TableCell className={classes.tableCell}><Typography className={classes.label}>{t('Username')}</Typography></TableCell>
- <TableCell className={classes.tableCell}>
- <InputBase value={username} name="username" onChange={e => setUsername(e.target.value)} label={t('Username')} />
- </TableCell>
- </TableRow>
- <TableRow>
- <TableCell className={classes.tableCell}><Typography className={classes.label}>{t('Email address')}</Typography></TableCell>
- <TableCell className={classes.tableCell}>
- <InputBase prop value={email} name="email" type="email" onChange={e => setEmail(e.target.value)} label={t('example@company.com')} disabled={usingOAuth} />
- </TableCell>
- </TableRow>
- </TableBody>
- </Table>
- </TableContainer>
- <SavingButton isSaving={isSaving} color={colorA} type="submit" variant="contained" size="large" className={classes.submitButton}>
- {t('Save Changes')}
- </SavingButton>
- </form>
- </Box>
- </>
- );
- };
- export default withAuthenticationRequired(EditProfile);
|