Skip to content

Commit 5fddcec

Browse files
committed
feat: Photo profile update
1 parent baffae7 commit 5fddcec

4 files changed

Lines changed: 81 additions & 37 deletions

File tree

src/admin/pages/ProfileEditPage.tsx

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -87,34 +87,34 @@ export default function ProfileEditPage() {
8787
};
8888

8989
const handleAvatarUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
90-
const file = e.target.files?.[0];
91-
if (!file || !profile?.id) return;
90+
const file = e.target.files?.[0];
91+
if (!file || !profile?.id) return;
9292

93-
try {
94-
setUploadingAvatar(true);
95-
const formDataUpload = new FormData();
96-
formDataUpload.append('files', file);
97-
formDataUpload.append('ref', 'api::profile.profile');
98-
formDataUpload.append('refId', String(profile.id));
99-
formDataUpload.append('field', 'avatar');
100-
101-
const uploadResponse = await fetch('/api/upload', {
102-
method: 'POST',
103-
body: formDataUpload,
104-
});
93+
try {
94+
setUploadingAvatar(true);
10595

106-
if (uploadResponse.ok) {
107-
const uploadedFiles = await uploadResponse.json();
108-
if (uploadedFiles?.[0]) {
109-
setProfile(prev => prev ? { ...prev, avatar: uploadedFiles[0] } : null);
110-
}
111-
}
112-
} catch (err) {
113-
console.error('Error uploading avatar:', err);
114-
} finally {
115-
setUploadingAvatar(false);
96+
const formData = new FormData();
97+
formData.append('avatar', file);
98+
99+
// send the profile id in query or body
100+
const uploadResponse = await fetch(`/api/profiles/avatar?userId=${user.id}`, {
101+
method: 'PUT',
102+
body: formData,
103+
});
104+
105+
if (!uploadResponse.ok) throw new Error('Upload failed');
106+
107+
const uploadedFiles = await uploadResponse.json();
108+
if (uploadedFiles?.[0]) {
109+
setProfile(prev => prev ? { ...prev, avatar: uploadedFiles[0] } : null);
116110
}
117-
};
111+
} catch (err) {
112+
console.error('Error uploading avatar:', err);
113+
} finally {
114+
setUploadingAvatar(false);
115+
}
116+
};
117+
118118

119119
const handleSubmit = async (e: React.FormEvent) => {
120120
e.preventDefault();
@@ -194,7 +194,7 @@ export default function ProfileEditPage() {
194194
</Box>
195195
)}
196196
</Box>
197-
{/* <Box>
197+
<Box>
198198
<Button
199199
variant="secondary"
200200
startIcon={<Upload />}
@@ -212,7 +212,7 @@ export default function ProfileEditPage() {
212212
<Typography variant="pi" textColor="neutral600" marginTop={2}>
213213
JPG, PNG or GIF. Max size 2MB.
214214
</Typography>
215-
</Box> */}
215+
</Box>
216216
</Flex>
217217
<Flex gap={4} wrap="wrap">
218218
<Box flex="1" minWidth="280px">

src/api/profile/controllers/profile.ts

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44

55
import { factories } from '@strapi/strapi';
6+
import profile from '../services/profile';
67

78
export default factories.createCoreController('api::profile.profile', ({ strapi }) => ({
89
async getMe(ctx) {
@@ -83,15 +84,50 @@ export default factories.createCoreController('api::profile.profile', ({ strapi
8384
},
8485
});
8586

86-
// await strapi.documents('admin::user').update({
87-
// documentId: profile.user.documentId,
88-
// data: {
89-
// firstname: data.firstname,
90-
// lastname: data.lastname,
91-
// email: data.email,
92-
// },
93-
// });
94-
9587
return { data:profile };
9688
},
89+
async updateAvatar(ctx) {
90+
const { userId } = ctx.query;
91+
const userIdNumber = Number(userId);
92+
93+
if (Number.isNaN(userIdNumber)) {
94+
return ctx.badRequest('Invalid userId');
95+
}
96+
97+
const { avatar } = ctx.request.files;
98+
if (!avatar) {
99+
return ctx.badRequest('No file uploaded');
100+
}
101+
102+
// Find the profile
103+
const profiles = await strapi.entityService.findMany('api::profile.profile', {
104+
filters: {
105+
user: {
106+
id: userIdNumber
107+
}
108+
},
109+
populate: {
110+
avatar: true,
111+
user: true,
112+
},
113+
limit: 1,
114+
});
115+
116+
const profile = profiles[0];
117+
if (!profile) return ctx.notFound('Profile not found for this user');
118+
119+
// Upload avatar
120+
const uploaded = await strapi.plugin('upload').service('upload').upload({
121+
data: {
122+
ref: 'api::profile.profile',
123+
refId: profile.id,
124+
field: 'avatar',
125+
},
126+
files: avatar,
127+
});
128+
129+
ctx.body = uploaded;
130+
return uploaded;
131+
}
132+
97133
}));

src/api/profile/routes/custom-profile.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,13 @@ export default {
1616
auth: false
1717
},
1818
},
19+
{
20+
method: 'PUT',
21+
path: '/profiles/avatar',
22+
handler: 'api::profile.profile.updateAvatar',
23+
config: {
24+
auth: false
25+
},
26+
},
1927
],
2028
};

src/extensions/documentation/documentation/1.0.0/full_documentation.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"name": "Apache 2.0",
1515
"url": "https://www.apache.org/licenses/LICENSE-2.0.html"
1616
},
17-
"x-generation-date": "2026-01-23T10:52:37.730Z"
17+
"x-generation-date": "2026-01-23T11:44:52.992Z"
1818
},
1919
"servers": [
2020
{

0 commit comments

Comments
 (0)