Fix first-login error, awards performance, filter animation, cache invalidation, and query fixes
- Guard onboarding tRPC queries with session hydration check (fixes UNAUTHORIZED on first login) - Defer expensive queries on awards page until UI elements are opened (dialog/tab) - Fix perPage: 500 exceeding backend Zod max of 100 on awards eligibility query - Add smooth open/close animation to project filters collapsible bar - Fix seeded user status from ACTIVE to INVITED in seed-candidatures.ts - Add router.refresh() cache invalidation across ~22 admin forms - Fix geographic analytics query to use programId instead of round.programId - Fix dashboard queries to scope by programId correctly - Fix project.listPool and round queries for projects outside round context - Add rounds page useEffect for state sync after mutations Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -597,6 +597,51 @@ export const projectRouter = router({
|
||||
return project
|
||||
}),
|
||||
|
||||
/**
|
||||
* Bulk delete projects (admin only)
|
||||
*/
|
||||
bulkDelete: adminProcedure
|
||||
.input(
|
||||
z.object({
|
||||
ids: z.array(z.string()).min(1).max(200),
|
||||
})
|
||||
)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
const projects = await ctx.prisma.project.findMany({
|
||||
where: { id: { in: input.ids } },
|
||||
select: { id: true, title: true },
|
||||
})
|
||||
|
||||
if (projects.length === 0) {
|
||||
throw new TRPCError({
|
||||
code: 'NOT_FOUND',
|
||||
message: 'No projects found to delete',
|
||||
})
|
||||
}
|
||||
|
||||
const result = await ctx.prisma.$transaction(async (tx) => {
|
||||
await logAudit({
|
||||
prisma: tx,
|
||||
userId: ctx.user.id,
|
||||
action: 'BULK_DELETE',
|
||||
entityType: 'Project',
|
||||
detailsJson: {
|
||||
count: projects.length,
|
||||
titles: projects.map((p) => p.title),
|
||||
ids: projects.map((p) => p.id),
|
||||
},
|
||||
ipAddress: ctx.ip,
|
||||
userAgent: ctx.userAgent,
|
||||
})
|
||||
|
||||
return tx.project.deleteMany({
|
||||
where: { id: { in: projects.map((p) => p.id) } },
|
||||
})
|
||||
})
|
||||
|
||||
return { deleted: result.count }
|
||||
}),
|
||||
|
||||
/**
|
||||
* Import projects from CSV data (admin only)
|
||||
* Projects belong to a program. Optionally assign to a round.
|
||||
@@ -887,7 +932,7 @@ export const projectRouter = router({
|
||||
const skip = (page - 1) * perPage
|
||||
|
||||
const where: Record<string, unknown> = {
|
||||
round: { programId },
|
||||
programId,
|
||||
roundId: null,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user