You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tech-interview-handbook/apps/portal/src/server/router/questions/questions-answer-router.ts

170 lines
4.1 KiB

import { z } from 'zod';
import { Vote } from '@prisma/client';
import { TRPCError } from '@trpc/server';
import { createRouter } from '../context';
import type { Answer } from '~/types/questions';
import { SortOrder, SortType } from '~/types/questions.d';
export const questionsAnswerRouter = createRouter()
.query('getAnswers', {
input: z.object({
cursor: z.string().nullish(),
limit: z.number().min(1).default(50),
questionId: z.string(),
sortOrder: z.nativeEnum(SortOrder),
sortType: z.nativeEnum(SortType),
}),
async resolve({ ctx, input }) {
const { questionId, cursor } = input;
const sortCondition =
input.sortType === SortType.TOP
? [
{
upvotes: input.sortOrder,
},
{
id: input.sortOrder,
},
]
: [
{
updatedAt: input.sortOrder,
},
{
id: input.sortOrder,
},
];
const answersData = await ctx.prisma.questionsAnswer.findMany({
cursor: cursor ? { id: cursor } : undefined,
include: {
_count: {
select: {
comments: true,
},
},
user: {
select: {
image: true,
name: true,
},
},
votes: true,
},
orderBy: sortCondition,
take: input.limit + 1,
where: {
questionId,
},
});
const processedAnswersData = answersData.map((data) => {
const votes: number = data.votes.reduce(
(previousValue: number, currentValue) => {
let result: number = previousValue;
switch (currentValue.vote) {
case Vote.UPVOTE:
result += 1;
break;
case Vote.DOWNVOTE:
result -= 1;
break;
}
return result;
},
0,
);
const answer: Answer = {
content: data.content,
createdAt: data.createdAt,
id: data.id,
numComments: data._count.comments,
numVotes: votes,
user: data.user?.name ?? '',
userImage: data.user?.image ?? '',
};
return answer;
});
let nextCursor: typeof cursor | undefined = undefined;
if (answersData.length > input.limit) {
const nextItem = answersData.pop()!;
processedAnswersData.pop();
const nextIdCursor: string | undefined = nextItem.id;
nextCursor = nextIdCursor;
}
return {
data: processedAnswersData,
nextCursor,
};
},
})
.query('getAnswerById', {
input: z.object({
answerId: z.string(),
}),
async resolve({ ctx, input }) {
const answerData = await ctx.prisma.questionsAnswer.findUnique({
include: {
_count: {
select: {
comments: true,
},
},
user: {
select: {
image: true,
name: true,
},
},
votes: true,
},
where: {
id: input.answerId,
},
});
if (!answerData) {
throw new TRPCError({
code: 'NOT_FOUND',
message: 'Answer not found',
});
}
const votes: number = answerData.votes.reduce(
(previousValue: number, currentValue) => {
let result: number = previousValue;
switch (currentValue.vote) {
case Vote.UPVOTE:
result += 1;
break;
case Vote.DOWNVOTE:
result -= 1;
break;
}
return result;
},
0,
);
const answer: Answer = {
content: answerData.content,
createdAt: answerData.createdAt,
id: answerData.id,
numComments: answerData._count.comments,
numVotes: votes,
user: answerData.user?.name ?? '',
userImage: answerData.user?.image ?? '',
};
return answer;
},
});