cpns / packages /api /src /routers /rating.ts
pramudya-yb
Rename project from Labas to Pram
2b62b0c
Raw
History Blame Contribute Delete
4.99 kB
import { z } from "zod";
import { eq, and, avg } from "drizzle-orm";
import { router, protectedProcedure, publicProcedure } from "../index";
import { db } from "@pram/db";
import { questionRating, question, packageRating, testPackage } from "@pram/db";
import { checkRateLimit } from "../lib/rate-limit";
export const ratingRouter = router({
getQuestionRating: publicProcedure
.input(z.object({ questionId: z.string().uuid() }))
.query(async ({ ctx, input }) => {
const userId = ctx.session?.user.id;
const [avgResult] = await db
.select({ avgScore: avg(questionRating.score) })
.from(questionRating)
.where(eq(questionRating.questionId, input.questionId));
const avgRating = avgResult?.avgScore ? Math.round(Number(avgResult.avgScore)) : null;
let myRating: number | null = null;
if (userId) {
const [row] = await db
.select({ score: questionRating.score })
.from(questionRating)
.where(
and(
eq(questionRating.questionId, input.questionId),
eq(questionRating.userId, userId),
),
)
.limit(1);
myRating = row?.score ?? null;
}
return { avgRating, myRating };
}),
rateQuestion: protectedProcedure
.input(
z.object({
questionId: z.string().uuid(),
score: z.number().min(1).max(5),
}),
)
.mutation(async ({ ctx, input }) => {
await checkRateLimit({ key: `rate:${ctx.session.user.id}`, limit: 10, windowMs: 10_000 });
const existing = await db
.select()
.from(questionRating)
.where(
and(
eq(questionRating.questionId, input.questionId),
eq(questionRating.userId, ctx.session.user.id),
),
)
.limit(1);
const existingRating = existing[0];
if (existingRating) {
await db
.update(questionRating)
.set({ score: input.score })
.where(eq(questionRating.id, existingRating.id));
} else {
await db.insert(questionRating).values({
userId: ctx.session.user.id,
questionId: input.questionId,
score: input.score,
});
}
const [avgResult] = await db
.select({ avgScore: avg(questionRating.score) })
.from(questionRating)
.where(eq(questionRating.questionId, input.questionId));
await db
.update(question)
.set({ avgRating: avgResult?.avgScore ? Math.round(Number(avgResult.avgScore)) : null })
.where(eq(question.id, input.questionId));
return { success: true };
}),
getPackageRating: publicProcedure
.input(z.object({ packageId: z.string().uuid() }))
.query(async ({ ctx, input }) => {
const userId = ctx.session?.user.id;
const [avgResult] = await db
.select({ avgScore: avg(packageRating.score) })
.from(packageRating)
.where(eq(packageRating.packageId, input.packageId));
const avgRating = avgResult?.avgScore ? Math.round(Number(avgResult.avgScore)) : null;
let myRating: number | null = null;
if (userId) {
const [row] = await db
.select({ score: packageRating.score })
.from(packageRating)
.where(
and(
eq(packageRating.packageId, input.packageId),
eq(packageRating.userId, userId),
),
)
.limit(1);
myRating = row?.score ?? null;
}
return { avgRating, myRating };
}),
ratePackage: protectedProcedure
.input(
z.object({
packageId: z.string().uuid(),
score: z.number().min(1).max(5),
}),
)
.mutation(async ({ ctx, input }) => {
await checkRateLimit({ key: `rate:${ctx.session.user.id}`, limit: 10, windowMs: 10_000 });
const existing = await db
.select()
.from(packageRating)
.where(
and(
eq(packageRating.packageId, input.packageId),
eq(packageRating.userId, ctx.session.user.id),
),
)
.limit(1);
const existingRating = existing[0];
if (existingRating) {
await db
.update(packageRating)
.set({ score: input.score })
.where(eq(packageRating.id, existingRating.id));
} else {
await db.insert(packageRating).values({
userId: ctx.session.user.id,
packageId: input.packageId,
score: input.score,
});
}
const [avgResult] = await db
.select({ avgScore: avg(packageRating.score) })
.from(packageRating)
.where(eq(packageRating.packageId, input.packageId));
await db
.update(testPackage)
.set({ avgRating: avgResult?.avgScore ? Math.round(Number(avgResult.avgScore)) : null })
.where(eq(testPackage.id, input.packageId));
return { success: true };
}),
});