all repos — caroster @ 5ed83071ddb9096ff61df7bcbb763178d4445e4d

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