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;