all repos — caroster @ d25fd2970a46f8b86f2abaaff47a8ebef62e4f73

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