Add image cropping to avatar upload and show avatars platform-wide
- Add react-easy-crop for circular crop + zoom UI on avatar upload - Create server-side getUserAvatarUrl utility for generating pre-signed URLs - Update all nav components (admin, jury, mentor, observer) to show user avatars - Add avatar URLs to user list, mentor list, and project detail API responses - Replace initials-only avatars with UserAvatar component across admin pages Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { z } from 'zod'
|
||||
import { TRPCError } from '@trpc/server'
|
||||
import { router, protectedProcedure, adminProcedure } from '../trpc'
|
||||
import { getUserAvatarUrl } from '../utils/avatar-url'
|
||||
import {
|
||||
generateAIAssignments,
|
||||
generateFallbackAssignments,
|
||||
@@ -31,14 +32,25 @@ export const assignmentRouter = router({
|
||||
listByProject: adminProcedure
|
||||
.input(z.object({ projectId: z.string() }))
|
||||
.query(async ({ ctx, input }) => {
|
||||
return ctx.prisma.assignment.findMany({
|
||||
const assignments = await ctx.prisma.assignment.findMany({
|
||||
where: { projectId: input.projectId },
|
||||
include: {
|
||||
user: { select: { id: true, name: true, email: true, expertiseTags: true } },
|
||||
user: { select: { id: true, name: true, email: true, expertiseTags: true, profileImageKey: true, profileImageProvider: true } },
|
||||
evaluation: { select: { status: true, submittedAt: true, globalScore: true, binaryDecision: true } },
|
||||
},
|
||||
orderBy: { createdAt: 'desc' },
|
||||
})
|
||||
|
||||
// Attach avatar URLs
|
||||
return Promise.all(
|
||||
assignments.map(async (a) => ({
|
||||
...a,
|
||||
user: {
|
||||
...a.user,
|
||||
avatarUrl: await getUserAvatarUrl(a.user.profileImageKey, a.user.profileImageProvider),
|
||||
},
|
||||
}))
|
||||
)
|
||||
}),
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user