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;