all repos — caroster @ 69a8f789f50a85eb1d8519dd7d3c54eba39233c3

[Octree] Group carpool to your event https://caroster.io

frontend/containers/Profile/index.tsx (view raw)

  1import {useReducer, useState} from 'react';
  2import Container from '@mui/material/Container';
  3import Card from '@mui/material/Card';
  4import CardContent from '@mui/material/CardContent';
  5import CardActions from '@mui/material/CardActions';
  6import Button from '@mui/material/Button';
  7import {useTheme} from '@mui/material/styles';
  8import {useTranslation} from 'react-i18next';
  9import EditPassword from './EditPassword';
 10import ProfileField from './ProfileField';
 11import useToastStore from '../../stores/useToastStore';
 12import {
 13  UsersPermissionsUser,
 14  useUpdateMeMutation,
 15} from '../../generated/graphql';
 16import ManagingNotificationsField from './ManagingNotificationsField';
 17
 18interface Props {
 19  profile: UsersPermissionsUser;
 20  logout: () => void;
 21}
 22
 23const Profile = ({profile, logout}: Props) => {
 24  const {t} = useTranslation();
 25  const theme = useTheme();
 26  const addToast = useToastStore(s => s.addToast);
 27
 28  const [updateProfile] = useUpdateMeMutation();
 29  const [isEditing, setIsEditing] = useState(false);
 30  const [isEditingPassword, setIsEditingPassword] = useState(false);
 31  const [firstName, setFirstName] = useState(profile.firstName);
 32  const [lastName, setLastName] = useState(profile.lastName);
 33  const [email, setEmail] = useState(profile.email);
 34  const [newsletterConsent, toggleNewsletter] = useReducer(
 35    i => !i,
 36    profile.newsletterConsent
 37  );
 38  const [notificationEnabled, toggleNotification] = useReducer(
 39    i => !i,
 40    profile.notificationEnabled
 41  );
 42
 43  const [oldPassword, setOldPassword] = useState('');
 44  const [newPassword, setNewPassword] = useState('');
 45  const [errorPassword, setErrorPassword] = useState('');
 46  const isStrapiUser = profile.provider === 'local';
 47
 48  const resetPassword = () => {
 49    setIsEditingPassword(false);
 50    setNewPassword('');
 51    setOldPassword('');
 52    setErrorPassword('');
 53  };
 54
 55  const savePassword = async () => {
 56    try {
 57      await updateProfile({
 58        variables: {
 59          userUpdate: {oldPassword, password: newPassword},
 60        },
 61      });
 62      addToast(t('profile.password_changed'));
 63      resetPassword();
 64    } catch (err) {
 65      if (err.message === 'Wrong password') {
 66        setErrorPassword(t('profile.errors.password_nomatch'));
 67        return;
 68      }
 69    }
 70  };
 71
 72  const onSave = async () => {
 73    try {
 74      await updateProfile({
 75        variables: {
 76          userUpdate: {
 77            firstName,
 78            lastName,
 79            email,
 80            newsletterConsent,
 81            notificationEnabled,
 82          },
 83        },
 84      });
 85      setIsEditing(false);
 86    } catch (error) {
 87      console.error(error);
 88    }
 89  };
 90
 91  if (isEditingPassword)
 92    return (
 93      <EditPassword
 94        oldPassword={oldPassword}
 95        newPassword={newPassword}
 96        setOldPassword={setOldPassword}
 97        setNewPassword={setNewPassword}
 98        error={errorPassword}
 99        save={savePassword}
100        cancel={resetPassword}
101      />
102    );
103
104  return (
105    <Container
106      maxWidth="sm"
107      sx={{
108        margin: 0,
109        ml: 4,
110        [theme.breakpoints.down('sm')]: {
111          ml: 0,
112        },
113      }}
114    >
115      <Card sx={{width: '480px', maxWidth: '100%'}}>
116        <CardContent>
117          <ProfileField
118            name="firstName"
119            value={firstName}
120            label={t('profile.firstName')}
121            defaultValue={t('profile.not_defined', {
122              field: '$t(profile.firstName)',
123            })}
124            onChange={setFirstName}
125            isEditing={isEditing}
126          />
127          <ProfileField
128            name="lastName"
129            value={lastName}
130            label={t('profile.lastName')}
131            defaultValue={t('profile.not_defined', {
132              field: '$t(profile.lastName)',
133            })}
134            onChange={setLastName}
135            isEditing={isEditing}
136          />
137          <ProfileField
138            name="email"
139            value={email}
140            label={t('profile.email')}
141            defaultValue={t('profile.not_defined', {
142              field: '$t(profile.email)',
143            })}
144            onChange={setEmail}
145            isEditing={isEditing}
146            disabled={!isStrapiUser}
147          />
148        </CardContent>
149        <ManagingNotificationsField
150          isEditing={isEditing}
151          notificationChecked={notificationEnabled}
152          newsletterChecked={newsletterConsent}
153          toggleNotification={toggleNotification}
154          toggleNewsletter={toggleNewsletter}
155        />
156
157        <CardActions sx={{justifyContent: 'flex-end'}}>
158          {!isEditing && (
159            <>
160              <Button type="button" onClick={logout}>
161                {t('profile.actions.logout')}
162              </Button>
163              <Button
164                type="button"
165                color="primary"
166                onClick={() => setIsEditing(true)}
167                variant="contained"
168              >
169                {t('profile.actions.edit')}
170              </Button>
171            </>
172          )}
173          {isEditing && isStrapiUser && (
174            <Button
175              type="button"
176              onClick={evt => {
177                if (evt.preventDefault) evt.preventDefault();
178                setIsEditingPassword(true);
179              }}
180            >
181              {t('profile.actions.change_password')}
182            </Button>
183          )}
184          {isEditing && (
185            <Button
186              type="submit"
187              color="primary"
188              onClick={onSave}
189              variant="contained"
190            >
191              {t('profile.actions.save')}
192            </Button>
193          )}
194        </CardActions>
195      </Card>
196    </Container>
197  );
198};
199
200export default Profile;