add admin dashboard, fix s3 uploading workflow#37
Merged
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds an Admin Console (overview/users/reports + warn/ban actions), extends notifications with admin “WARNING” events and follow-state UI, and reworks chat image uploads to an async BullMQ/S3 workflow (plus reply + shared media UI). It also introduces an AI-assisted listing auto-fill endpoint and UI, and makes minor frontend performance tweaks (Next Image sizes) and repo hygiene updates (.clerk in gitignore).
Changes:
- Add admin dashboard (frontend routes + backend admin module/guard/service) with user management, report triage, and warning notifications.
- Add chat reply/shared-media UI and move chat image uploads to a BullMQ background upload processor, emitting a new
message_images_uploadedsocket event. - Add AI listing suggestion endpoint (
/listings/ai-suggest) and Add Product UI auto-fill action.
Reviewed changes
Copilot reviewed 31 out of 32 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Updates clone instructions to Orbit repo URL. |
| frontend/components/NotificationsMenu.tsx | Adds WARNING notification rendering, follow button + expanded content behavior. |
| frontend/components/MiniChatWidget.tsx | Adds reply/media/actions + image sending in mini chat; updates toast UX. |
| frontend/components/CustomUserButton.tsx | Adds Admin Dashboard link gated by role check. |
| frontend/components/ChatBadge.tsx | Updates socket listeners to resync unread count on more events. |
| frontend/components/admin/WarningModal.tsx | Adds modal UI for sending admin warnings. |
| frontend/app/page.tsx | Adds sizes props to Next <Image /> usage; adds a footer link. |
| frontend/app/chat/page.tsx | Adds reply/media/actions + image upload flow with optimistic UI + socket reconciliation. |
| frontend/app/admin/users/page.tsx | Admin UI for listing users, banning/unbanning, and warning. |
| frontend/app/admin/reports/page.tsx | Admin UI for reviewing reports and warning reported users. |
| frontend/app/admin/page.tsx | Admin overview stats page. |
| frontend/app/admin/layout.tsx | Admin layout shell + client-side role gate. |
| frontend/app/add-product/page.tsx | Adds AI auto-fill action based on first uploaded image. |
| frontend/.gitignore | Ignores /.clerk/ config directory. |
| backend/src/modules/storage/upload.processor.ts | Adds BullMQ worker to upload images to S3 and emit message_images_uploaded. |
| backend/src/modules/storage/storage.service.ts | Adjusts S3 upload parameters (adds ACL). |
| backend/src/modules/storage/storage.module.ts | Registers upload queue + processor; wires Prisma/Chat dependencies. |
| backend/src/modules/notifications/notifications.service.ts | Adds actor.id + isFollowedByMe computed field. |
| backend/src/modules/listings/listings.service.ts | Adds AI suggestion service method; refactors listing image creation. |
| backend/src/modules/listings/listings.controller.ts | Adds /listings/ai-suggest endpoint. |
| backend/src/modules/chat/chat.service.ts | Adds image-message creation via BullMQ and replyTo support. |
| backend/src/modules/chat/chat.module.ts | Registers upload-queue for chat module. |
| backend/src/modules/chat/chat.gateway.ts | Extends send_message payload to include replyToId. |
| backend/src/modules/chat/chat.controller.ts | Adds REST endpoint for sending image messages. |
| backend/src/modules/ai/ai.service.ts | Adds Gemini-based image-to-listing suggestion method. |
| backend/src/modules/admin/admin.service.ts | Implements admin stats/reports/users, warn + auto-ban workflow. |
| backend/src/modules/admin/admin.module.ts | Registers admin module. |
| backend/src/modules/admin/admin.controller.ts | Exposes admin endpoints guarded by AdminGuard. |
| backend/src/common/guards/admin.guard.ts | Adds admin role guard on top of Clerk auth. |
| backend/src/app.module.ts | Wires AdminModule into the application. |
| backend/prisma/schema.prisma | Adds Role/isBanned fields, message imageUrls/replies, and WARNING notification type. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
34
to
40
| const command = new PutObjectCommand({ | ||
| Bucket: bucketName, | ||
| Key: uniqueFilename, | ||
| Body: file.buffer, | ||
| ContentType: file.mimetype, | ||
| ACL: 'public-read', | ||
| }); |
Comment on lines
+35
to
+40
| // Update the message in DB | ||
| const updatedMessage = await this.prisma.message.update({ | ||
| where: { id: messageId }, | ||
| data: { imageUrls }, | ||
| include: { sender: true }, | ||
| }); |
Comment on lines
58
to
64
| socket.on("receive_message", onReceiveMessage); | ||
| socket.on("messages_read", onReceiveMessage); // when we read messages on another device or tab | ||
|
|
||
| return () => { | ||
| socket.off("receive_message", onReceiveMessage); | ||
| socket.off("messages_read", onReceiveMessage); | ||
| }; |
Comment on lines
+397
to
+408
| const onMessageImagesUploaded = (updatedMessage: Message) => { | ||
| setMessages((prev) => { | ||
| const idx = prev.findIndex(m => m.id.startsWith('temp-')); | ||
| if (idx !== -1) { | ||
| const newMsgs = [...prev]; | ||
| newMsgs[idx] = updatedMessage; | ||
| return newMsgs; | ||
| } | ||
| return [...prev, updatedMessage]; | ||
| }); | ||
| setRefreshInbox((r) => r + 1); | ||
| }; |
Comment on lines
+843
to
+864
| // Optimistically add to UI with local blobs | ||
| const optimisticMessage: Message = { | ||
| id: 'temp-' + Date.now(), | ||
| content: newMessage, | ||
| conversationId: activeConversationId, | ||
| senderId: clerkUser?.id || '', | ||
| createdAt: new Date().toISOString(), | ||
| imageUrls: selectedImages.map(f => URL.createObjectURL(f)), | ||
| replyToId: replyingToMessage?.id || null, | ||
| replyTo: replyingToMessage ? { | ||
| sender: { name: replyingToMessage.sender?.name || null, username: replyingToMessage.sender?.username || null }, | ||
| content: replyingToMessage.content | ||
| } : null, | ||
| sender: { | ||
| id: clerkUser?.id || '', | ||
| name: clerkUser?.fullName || null, | ||
| username: clerkUser?.username || null, | ||
| avatarUrl: clerkUser?.imageUrl || null, | ||
| clerkUserId: clerkUser?.id || '', | ||
| } | ||
| }; | ||
| setMessages(prev => [...prev, optimisticMessage]); |
Comment on lines
+866
to
+876
| const token = await getToken(); | ||
| await axios.post( | ||
| `http://localhost:3000/chat/message/${activeConversationId}/images`, | ||
| formData, | ||
| { | ||
| headers: { | ||
| Authorization: `Bearer ${token}`, | ||
| "Content-Type": "multipart/form-data", | ||
| }, | ||
| } | ||
| ); |
Comment on lines
+167
to
+171
| setNotifications(prev => prev.map(notif => | ||
| notif.actor?.id === targetId | ||
| ? { ...notif, actor: { ...notif.actor, isFollowedByMe: true } } | ||
| : notif | ||
| )); |
Comment on lines
+184
to
+188
| setNotifications(prev => prev.map(notif => | ||
| notif.actor?.id === targetId | ||
| ? { ...notif, actor: { ...notif.actor, isFollowedByMe: false } } | ||
| : notif | ||
| )); |
Comment on lines
+310
to
+314
| <Button | ||
| variant={notif.actor.isFollowedByMe ? "outline" : "secondary"} | ||
| size="sm" | ||
| className={`h-7 text-[11px] px-3 font-bold rounded-full ${!notif.actor.isFollowedByMe ? "hover:bg-primary hover:text-primary-foreground" : ""}`} | ||
| onClick={(e) => { |
Comment on lines
+123
to
127
| ), { | ||
| duration: 4000, | ||
| }); | ||
| } | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.