feat: lunch picker on attending-members card + admin slide-over
LunchPickForm shared between applicant dashboard rows (member-self / team-lead context) and the admin manifest's edit-pencil slide-over. Adds lunch.getMemberPick read for the per-row hydration. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2727,7 +2727,9 @@ export const applicantRouter = router({
|
||||
},
|
||||
finalistConfirmation: {
|
||||
include: {
|
||||
attendingMembers: { select: { userId: true, needsVisa: true } },
|
||||
attendingMembers: {
|
||||
select: { id: true, userId: true, needsVisa: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -2757,6 +2759,7 @@ export const applicantRouter = router({
|
||||
project: {
|
||||
id: project.id,
|
||||
title: project.title,
|
||||
programId: project.program.id,
|
||||
teamMembers: project.teamMembers.map((tm) => ({
|
||||
userId: tm.userId,
|
||||
role: tm.role,
|
||||
|
||||
@@ -227,6 +227,46 @@ export const lunchRouter = router({
|
||||
return { ok: true as const }
|
||||
}),
|
||||
|
||||
// ─── Single-row pick read (used by per-row picker UI) ────────────────────
|
||||
|
||||
/**
|
||||
* Read the current MemberLunchPick for an AttendingMember plus the dishes
|
||||
* for the parent event. Permission: any user with a TeamMember row on the
|
||||
* project, OR the AttendingMember.userId itself, OR admin.
|
||||
*/
|
||||
getMemberPick: protectedProcedure
|
||||
.input(z.object({ attendingMemberId: z.string() }))
|
||||
.query(async ({ ctx, input }) => {
|
||||
const am = await ctx.prisma.attendingMember.findUnique({
|
||||
where: { id: input.attendingMemberId },
|
||||
include: {
|
||||
confirmation: {
|
||||
select: {
|
||||
project: {
|
||||
select: {
|
||||
id: true,
|
||||
programId: true,
|
||||
teamMembers: { select: { userId: true } },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
lunchPick: true,
|
||||
},
|
||||
})
|
||||
if (!am) throw new TRPCError({ code: 'NOT_FOUND' })
|
||||
const userId = ctx.user.id
|
||||
const role = ctx.user.role
|
||||
const isAdmin = role === 'SUPER_ADMIN' || role === 'PROGRAM_ADMIN'
|
||||
const isOnTeam = am.confirmation.project.teamMembers.some(
|
||||
(tm) => tm.userId === userId,
|
||||
)
|
||||
if (!isAdmin && !isOnTeam && am.userId !== userId) {
|
||||
throw new TRPCError({ code: 'FORBIDDEN' })
|
||||
}
|
||||
return { pick: am.lunchPick }
|
||||
}),
|
||||
|
||||
// ─── Manifest + CSV export ───────────────────────────────────────────────
|
||||
|
||||
getManifest: adminProcedure
|
||||
|
||||
Reference in New Issue
Block a user