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 {useTranslation} from 'next-i18next';
8import EditPassword from './EditPassword';
9import ProfileField from './ProfileField';
10import useToastStore from '../../stores/useToastStore';
11import {
12 UsersPermissionsUser,
13 useUpdateMeMutation,
14} from '../../generated/graphql';
15import ManagingNotificationsField from './ManagingNotificationsField';
16import StripeDashboardLink from './StripeDashboardLink';
17import {Box, Divider} from '@mui/material';
18import theme from '../../theme';
19
20interface Props {
21 profile: UsersPermissionsUser;
22 logout: () => void;
23}
24
25const Profile = ({profile, logout}: Props) => {
26 const {t} = useTranslation();
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 <Box>
119 <ProfileField
120 name="firstName"
121 value={firstName}
122 label={t('profile.firstName')}
123 defaultValue={t('profile.not_defined', {
124 field: '$t(profile.firstName)',
125 })}
126 onChange={setFirstName}
127 isEditing={isEditing}
128 />
129 <ProfileField
130 name="lastName"
131 value={lastName}
132 label={t('profile.lastName')}
133 defaultValue={t('profile.not_defined', {
134 field: '$t(profile.lastName)',
135 })}
136 onChange={setLastName}
137 isEditing={isEditing}
138 />
139 <ProfileField
140 name="email"
141 value={email}
142 label={t('profile.email')}
143 defaultValue={t('profile.not_defined', {
144 field: '$t(profile.email)',
145 })}
146 onChange={setEmail}
147 isEditing={isEditing}
148 disabled={!isStrapiUser}
149 />
150 </Box>
151 </CardContent>
152 <Divider />
153 <Box my={4}>
154 <ManagingNotificationsField
155 isEditing={isEditing}
156 notificationChecked={notificationEnabled}
157 newsletterChecked={newsletterConsent}
158 toggleNotification={toggleNotification}
159 toggleNewsletter={toggleNewsletter}
160 />
161 <StripeDashboardLink />
162 </Box>
163 <Divider />
164 <CardActions sx={{justifyContent: 'flex-end'}}>
165 {!isEditing && (
166 <>
167 <Button type="button" onClick={logout}>
168 {t('profile.actions.logout')}
169 </Button>
170 <Button
171 type="button"
172 color="primary"
173 onClick={() => setIsEditing(true)}
174 variant="contained"
175 >
176 {t('profile.actions.edit')}
177 </Button>
178 </>
179 )}
180 {isEditing && isStrapiUser && (
181 <Button
182 type="button"
183 onClick={evt => {
184 if (evt.preventDefault) evt.preventDefault();
185 setIsEditingPassword(true);
186 }}
187 >
188 {t('profile.actions.change_password')}
189 </Button>
190 )}
191 {isEditing && (
192 <Button
193 type="submit"
194 color="primary"
195 onClick={onSave}
196 variant="contained"
197 >
198 {t('profile.actions.save')}
199 </Button>
200 )}
201 </CardActions>
202 </Card>
203 </Container>
204 );
205};
206
207export default Profile;